2014-03-13 08:18 AM
Hi guys,
I've been working on a bootloader program which is loosely based around the FW_Upgrade demo for the STM32F4 discovery board. My Bootloader so far correctly finds a file on a USB stick and downloads it to flash in the right location(0x0800C000), but I'm having issues jumping to that location to run my downloaded program once I'm done putting it in flash. The demo from ST has the MCU reset after it has downloaded to flash and then jumps to the program. Is the reset necessary or can I just jump straight to the location in flash? Also, how do I actually do the jump. I'm using the code from st which looks like this, but it doesn't seem to work:/* Check Vector Table: Test if user code is programmed starting from address
''APPLICATION_ADDRESS'' */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}
2014-03-14 07:47 AM
clive, are you saying that I need to into my app code and define the IROM1 start address as 0x0800C000 instead of 0x08000000?
Well if that's where it's residing, then yes, because the vector table has fixed addresses in it, and there may be other hard addresses the linker has resolved. Review the project/structure of the IAP components.http://www.st.com/web/en/catalog/tools/PF257903
2014-03-14 09:16 AM
2014-03-14 10:02 AM
Hi
''Still got two issues:'' ''Firstly, my iap code initialises the usb host to check for the file, so when it actually loads my application code and the application code attempts to intialise usb, it crashes.'' Firstly, it is a good idea for any application to re- configure the peripherals it needs to use. Do not assume that they are going to be in reset state (now that you are using a bootloader). Secondly, just before you start the application, the bootloader should so a 'soft disconnect' of the USB otherwise anything it is connect to it does not know that the connection has been 'reset'. ''Secondly: My app code only works on a reboot( my iap checks for a usb stick and if it can't find one it loads the app). But it should also jump to the code after programming. Why would it work after a reboot and not after programming. my code is exactly the same in both locations...'' Sounds like the jump to application is not working correctly. Use you r debugger to step through it. It is a good idea to implement some kind of a flag/indication system to indicate a valid application has been programmed.2014-03-17 02:46 AM
The code for the jump is the same piece of code whether there is a reset or if it's straight after a program of flash though, so I know the code should work as it works with a reset. I also know that the code is programming into flash correctly. Is there maybe something I need to do to flash after programming to allow me to jump to the location? The fact that my bootloader will jump to the location if it's not programmed the flash suggests there's something I'm missing to close off flash or something? Maybe some sort of close command? My flash program code does this:
void COMMAND_ProgramFlashMemory(void)
{
__IO uint32_t programcounter = 0x00;
uint8_t readflag = TRUE;
uint16_t BytesRead;
/* RAM Address Initialization */
RamAddress = (uint32_t) & RAM_Buf;
/* Erase address init */
LastPGAddress = APPLICATION_ADDRESS;
/* While file still contain data */
while ((readflag == TRUE) && (HCD_IsDeviceConnected(&USB_OTG_Core) == 1))
{
/* Read maximum 512 Kbyte from the selected file */
f_read (&file, RAM_Buf, BUFFER_SIZE, (void *)&BytesRead);
/* Temp variable */
TmpReadSize = BytesRead;
/* The read data < ''BUFFER_SIZE'' Kbyte */
if (TmpReadSize < BUFFER_SIZE)
{
readflag = FALSE;
}
/* Program flash memory */
for (programcounter = TmpReadSize; programcounter != 0; programcounter -= 4)
{
TmpProgramCounter = programcounter;
/* Write word into flash memory */
if (FLASH_If_ProgramWord((LastPGAddress - TmpProgramCounter + TmpReadSize), \
*(__IO uint32_t *)(RamAddress - programcounter + TmpReadSize)) != FLASH_COMPLETE)
{
/* Toggle Red LED in infinite loop: Flash programming error */
Fail_Handler();
}
}
/* Update last programmed address value */
LastPGAddress = LastPGAddress + TmpReadSize;
}
}
2014-03-17 05:24 AM
Hi
''The code for the jump is the same piece of code whether there is a reset or if it's straight after a program of flash though, so I know the code should work as it works with a reset. I also know that the code is programming into flash correctly. Is there maybe something I need to do to flash after programming to allow me to jump to the location?'' I do not know. Have you stepped through the code after programming to see why the jump is no working? ''The fact that my bootloader will jump to the location if it's not programmed the flash suggests there's something I'm missing to close off flash or something?'' Yes, either the bootloader needs some way to detect if there is valid code to jump to OR The bootloader needs a 'marker' to be able to tell whether it can launch the application or not. The marker is cleared at very first start up. The marker is cleared by flash erase. The marker is set when programming is successful. '' Maybe some sort of close command? My flash program code does this:'' This is nothing to do with programming the Flash - this is the logic that the bootloader needs to determine if it can start the application.2014-03-17 05:28 AM
You could always checksum the image you wrote and check that.
It is possible that the ART cache would hold stale data, would depend if you are executing code in the app prior to erasing and reprogramming it. The simplest way to figure out what's going on is to use the debugger and step into the transition code and observe what the failure mode is. Then we wouldn't have to play guessing games.2014-05-15 06:24 AM
Jump problem:
I am writing a bootloader. Please let me know if the steps I perform are ok: 1 I obtain the bin file form the elf file with: arm-atollic-eabi-objcopy.exe -O binary Application.elf test.bin 2 The bin is copied to the internal flash starting with address 0x08008000 I have: #define APPLICATION_ADDRESS (uint32_t)0x08008000 3 the firmware copy is ok, as I monitor internal flash changes with Atollic memory view. the binary file starts with: D8 68 00 20 45 11 00 08 At 0x08008000 I see 200068D8 ( the same data but reversed) 5 When performing the jump, the verification fails: if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000) Thank you.2014-05-15 06:56 AM
No, I think your bigger problem is that you haven't linked your code to operate at the alternate address. So you'll need to fix that in your user interface, or linker script, or whatever Atollic does with it.
The bytes are stored in small-endian fashion (ie low order first) D8 68 00 20 45 11 00 08 The SP is at 0x200068D8, and the PC at 0x08001145 If the code was built properly the PC address would exceed 0x08008000 which is the base/floor of you application build.2014-05-15 06:59 AM
2014-05-15 07:45 AM
The app is built as:
linker: MEMORY { flash (rx) : ORIGIN = 0x08004000, LENGTH = 1024K - 0x4000 sram (rwx) : ORIGIN = 0x20000000, LENGTH = 112K } In the code I have: NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x4000); I am not quite sure about how Atollic shows the content of teh memory.. If I choose ''hex'' view, there is: 200068D8 0800 1E45 If I choose ''traditional'' there is: D8680020 451E0008 I prepare my data as: fw[3] = serialFlashReadByte(); fw[2] = serialFlashReadByte(); fw[1] = serialFlashReadByte(); fw[0] = serialFlashReadByte(); //write 4 bytes of data to internal memory fwData = fw[0] << 24; fwData |= fw[1] << 16; fwData |= fw[2] << 8; fwData |= fw[3]; if (FLASH_ProgramWord(Address, fwData) == FLASH_COMPLETE) { Address = Address + 4; }