STM32 Bootloader loading FreeRTOS problems

Folks, I have a bootloader for the STM32 working on a program that is run-to-complete. Another node in this project runs FreeRTOS and although  it seems I can load the image using the bootloader, it just gets stuck in the SVC_Handler when I try and run it. If I try and run FreeRTOS at 0x8003000 (which is where the bootloader sticks FreeRTOS rather than 0x8000000) it also doesn’t run. With my run-to-complete program I was simply able to recompile to be at 0x8003000 and it ran fine. Is the something else I have to do when recompiling for FreeRTOS to run further up in memory please? Thanks! Rob

STM32 Bootloader loading FreeRTOS problems

FreeRTOS needs three handlers to be installed in the Cortex vector table. When you jump from your bootloader code to the FreeRTOS code, are you remapping the vector table to where ever you have it in your memory map (probably at 0x8003000 as it is normally at 0x00000000).

STM32 Bootloader loading FreeRTOS problems

Hi Dave, I am, indeed, remapping the vector table as follows: void JumpToNormalApplication(void)
{     volatile unsigned long JumpAddress;     SCB_VTOR = (unsigned long)0x8003000;
    JumpAddress = *(volatile unsigned long*) (0x8003000 + 4);
    Jump_To_Application = (pFunction) JumpAddress;
    Jump_To_Application();
   
} This is exactly how I do it with the bootloader that works fine with my run-to-complete program that runs on a different  pieice of hardware but still with an almost identical STM32 (the one that works is a 64k part, the FreeRTOS one a 128k part).  I am wondering whether there’s something extra that is needed with FreeRTOS I’m not aware of. Thanks for the help. Rob

STM32 Bootloader loading FreeRTOS problems

It is not something I have direct experience of, but this topic comes up from time to time.  I recommend entering “bootloader” as a search term into the archive to see what turns up. http://www.freertos.org/FreeRTOS_Support_Forum_Archive/freertos_support_forum_archive_index.html Regards.

STM32 Bootloader loading FreeRTOS problems

Having ploughed through those I can see a lot of no-solves, one or two aha moments without actually explaining what it was and some talking about interrupts being left over from the bootloader being serviced when FreeRTOS starts. I only have one interrupt enabled in the bootloader and that is the UART. There are definitely no interrupts pending before I hit the OS. When I tyy and run the version of FreeRTOS that is compiled to start at 0x8003000 I get stuck here: void vPortStartFirstTask( void )
{
__asm volatile(
” ldr r0, =0xE000ED08 n” /* Use the NVIC offset register to locate the stack. */
” ldr r0,  n”
” ldr r0,  n”
” msr msp, r0 n” /* Set the msp back to the start of the stack. */
” svc 0 n” /* System call to start first task. */
);
} It’s the last line: svc 0 That jumps off to address 0x00020E which has this to keep jumping back to itself. E7FE        b 0x0800020E I suspect that  maybe there’s something hardcoded in FreeRTOS that is jumping to where it thinks the vector table should be? If that’s the case, it’s probably nothing to do with the bootloader but somethign else in FreeRTOS needs changing when remapped? svc seems to be something to do with supervisor mode. I must confess I don’t understamd what supervisor mode is. Thanks again.

STM32 Bootloader loading FreeRTOS problems

” msr msp, r0 n” /* Set the msp back to the start of the stack. / ” svc 0 n” / System call to start first task. */ It looks like you are using quite an old version of FreeRTOS.  The code sequence should be:
" msr msp, r0           n" /* Set the msp back to the start of the stack. */
"cpsie                              n"
" svc 0                 n" /* System call to start first task. */
The extra line is only required if interrupts are in the wrong state when the function is called – which would not normally happen with a standard reboot power up sequence, but in your case could well happen when you come through the boot loader.
0x00020E
This address looks like it is in your bootloader code, if the application code is starting at 0x8003000.  As it is just jumping to itself it sounds like it is a default handler for something, but which handler? If it is a hard fault handler, then the additional cpsie instruction as above will fix that, but even then it still seems to be using the boot loaders vector table. If it is the SVC handler, and it is the boot loaders SVC handler, then it looks like the vector table is not remapped as you expect. If it is the SVC handler, but a default SVC handler for the application, then it looks like the FreeRTOS interrupt handler has not been installed into the applications vector table. Regards.

STM32 Bootloader loading FreeRTOS problems

The thing is, this is not the bootloader version that I have found this problem with. This is just normal FreeRTOS – no bootloader involved right now – with the start of code remapped in the linker to start from 0x8003000. I am having a go, not using the bootloader to try and suss out whether it’s something to do with the bootloader or the remapping of FreeRTOS.  The fact that is is falling over when I do this, suggests to my simple mind that with FreeRTOS, there’s more to do than simply change the start of code inn the linker to the new address from 0x8000000. I can do this with my run-to-complete program on the other STM32 based bit of hardware in the project. That address should read 0x0800020E, not 0x00020E – sorry about that. The port is around two years old by the way.

STM32 Bootloader loading FreeRTOS problems

Ok, I didn’t realise that. When a Cortex-M boots it expects to find the vector table at address 0.  The first thing in the vector table is the address of its stack and the second the address of the program entry point.  In your current experiment, without the bootloader, presumably you only have one vector table and you are not remapping it, so the second entry in the vector table should point somewhere above 0x8003000. From previous posts, it looks like the entry point is being hit correctly, because you are getting as far as vPortStartFirstTask().  When the SVC instruction is hit, you say it then starts executing a handler at 0x0800020E, so it also appears to be the case that it is running a handler in the correct address range too – so the vector table at address 0 is causing a jump to an address above 0x8003000.  All good so far.  Do I have this right now? So what happens then is the mystery. Have you determined the function that is actually being executed when it is branching to itself?  It is definitely not the FreeRTOS SVC call handler, so again it is either a default handler for the SVC call (in which case the FreeRTOS handler is not installed in the vector table correctly) or it is a fault handler.  I think we need to determine which it is, and the map file produced by the linker should be able to tell you (if not just breaking in the debugger and attempting to look at the source code view). How are you installing the FreeRTOS interrupt vectors into the vector table?  There are two methods that can be used, either by modifying the vector table directly, or by mapping the FreeRTOS interrupts to their CMSIS equivalents if you are using a CMSIS compliant vector table. Can you post the vector table? Regards.

STM32 Bootloader loading FreeRTOS problems

I hope what is below is what you’re after in regards the vector table. All I am doing to normal FreeRTOS is going into the xml file that descibes the processor and changing the memory map for flash to start at 0x8003000 and change its length accordingly. I would stress that if I do this for a normal run-to-compete program then everything works fine, both as a standalone program and with the bootloader. If I look into memory at address zero with the debugger it has: 0x200001A4
0x080001F1 I would have thought all addresses should be above 0x8003000 as that is where everything has been shifted to as a base address.
.vectors        0x08003000      0x130
                0x08003000                __vectors_start__ = .
 *(.vectors .vectors.*)
 .vectors       0x08003000      0x130 THUMB Flash Debug/STM32F10x_Startup.o
                0x08003000                _vectors
                0x08003130                __vectors_end__ = (__vectors_start__ + SIZEOF (.vectors))
                0x08003130                __vectors_load_end__ = __vectors_end__
                0x00000001                . = ASSERT (((__vectors_end__ >= __FLASH_segment_start__) && (__vectors_end__ <= (__FLASH_segment_start__ + 0x1d000))), error: .vectors is too large to fit in FLASH memory segment)
                0x08003130                __init_load_start__ = ALIGN (__vectors_end__, 0x4)
.init           0x08003130      0x202
                0x08003130                __init_start__ = .
 *(.init .init.*)
 .init          0x08003130      0x108 THUMB Flash Debug/thumb_crt0.o
                0x08003130                _start
                0x080031b2                exit
 .init          0x08003238       0xfa THUMB Flash Debug/STM32F10x_Startup.o
                0x08003238                reset_handler
                0x0800323a                NMIException
                0x0800323c                HardFaultException
                0x0800323e                MemManageException
                0x08003240                BusFaultException
                0x08003242                UsageFaultException
                0x08003244                SVCHandler
                0x08003246                DebugMonitor
                0x08003248                PendSV
                0x0800324a                SysTickHandler
                0x0800324c                WWDG_IRQHandler
                0x0800324e                PVD_IRQHandler
                0x08003250                TAMPER_IRQHandler
                0x08003252                RTC_IRQHandler
                0x08003254                FLASH_IRQHandler
                0x08003256                RCC_IRQHandler
                0x08003258                EXTI0_IRQHandler
                0x0800325a                EXTI1_IRQHandler
                0x0800325c                EXTI2_IRQHandler
                0x0800325e                EXTI3_IRQHandler
                0x08003260                EXTI4_IRQHandler
                0x08003262                DMAChannel1_IRQHandler
                0x08003264                DMAChannel2_IRQHandler
                0x08003268                DMAChannel4_IRQHandler
                0x0800326c                DMAChannel6_IRQHandler
                0x08003270                ADC_IRQHandler
                0x08003272                USB_HP_CAN_TX_IRQHandler
                0x08003276                CAN_RX1_IRQHandler
                0x08003278                CAN_SCE_IRQHandler
                0x0800327a                EXTI9_5_IRQHandler
                0x0800327c                TIM1_BRK_IRQHandler
                0x0800327e                TIM1_UP_IRQHandler
                0x08003280                TIM1_TRG_COM_IRQHandler
                0x08003282                TIM1_CC_IRQHandler
                0x08003284                TIM2_IRQHandler
                0x08003286                TIM3_IRQHandler
                0x08003288                TIM4_IRQHandler
                0x0800328a                I2C1_EV_IRQHandler
                0x0800328c                I2C1_ER_IRQHandler
                0x0800328e                I2C2_EV_IRQHandler
                0x08003290                I2C2_ER_IRQHandler
                0x08003292                SPI1_IRQHandler
                0x08003294                SPI2_IRQHandler
                0x0800329a                USART3_IRQHandler
                0x0800329c                EXTI15_10_IRQHandler
                0x0800329e                RTCAlarm_IRQHandler
                0x080032a0                USBWakeUp_IRQHandler
                0x080032a2                TIM8_BRK_IRQHandler
                0x080032a4                TIM8_UP_IRQHandler
                0x080032a6                TIM8_TRG_COM_IRQHandler
                0x080032a8                TIM8_CC_IRQHandler
                0x080032aa                ADC3_IRQHandler
                0x080032ac                FSMC_IRQHandler
                0x080032ae                SDIO_IRQHandler
                0x080032b0                TIM5_IRQHandler
                0x080032b2                SPI3_IRQHandler
                0x080032b4                UART4_IRQHandler
                0x080032b6                UART5_IRQHandler
                0x080032b8                TIM6_IRQHandler
                0x080032ba                TIM7_IRQHandler
                0x080032bc                DMA2_Channel1_IRQHandler
                0x080032be                DMA2_Channel2_IRQHandler
                0x080032c0                DMA2_Channel3_IRQHandler
                0x080032c2                DMA2_Channel4_5_IRQHandler
                0x080032c4                __WFI
                0x080032c8                __WFE
                0x080032cc                __SEV
                0x080032d0                __ISB
                0x080032d6                __DSB
                0x080032dc                __DMB
                0x080032e2                __SVC
                0x080032e6                __MRS_CONTROL
                0x080032ec                __MSR_CONTROL
                0x080032f6                __MRS_PSP
                0x080032fc                __MSR_PSP
                0x08003302                __MRS_MSP
                0x08003308                __MSR_MSP
                0x0800330e                __SETPRIMASK
                0x08003312                __RESETPRIMASK
                0x08003316                __SETFAULTMASK
                0x0800331a                __RESETFAULTMASK
                0x0800331e                __BASEPRICONFIG
                0x08003324                __GetBASEPRI
                0x0800332a                __REV_HalfWord
                0x0800332e                __REV_Word
                0x08003332                __init_end__ = (__init_start__ + SIZEOF (.init))
                0x08003332                __init_load_end__ = __init_end__
                0x00000001                . = ASSERT (((__init_end__ >= __FLASH_segment_start__) && (__init_end__ <= (__FLASH_segment_start__ + 0x1d000))), error: .init is too large to fit in FLASH memory segment)
                0x08003334                __text_load_start__ = ALIGN (__init_end__, 0x4)

STM32 Bootloader loading FreeRTOS problems

I’m not sure how the linker will behave if you tell it there is no flash at address 0, because the CPU is hard coded to load the stack address from that address when it boots.
If I look into memory at address zero with the debugger it has:
0x200001A4
0x080001F1 0x200001A4 is presumably a RAM address.  Address 0 would be expected to hold a RAM address because it is the stack address.  Either the linker is still putting the RAM address at address zero, even though you have told it there is no memory there, because the linker knows it has to.  Or, the value you are seeing there is just left over from the last time you ran an application from address zero because the flash memory has not been overwritten or cleared.  Are you still remapping the vector table using the CPU vector base register?  It is difficult to see how because it would have to boot through the vector before the code that remapped the vector could be set – unless you have a debugger macro that is doing that before the CPU is taken out of reset. In any case, the vector table you have posted does not show the FreeRTOS interrupt handler having been installed.  Looking just at the SVC handler, I would expect to see a function named vPortSVCHandler() being installed, but what is actually installed is SVCHandler().  That might be ok, if you are #define’ing one name to the other and SVCHandler() is declared as a weak symbol, but otherwise it is an error. If you find the address of SVCHandler in the map file you will probably find it is the address you end up at branching to yourself when you execute the SVC instruction. Regards.

STM32 Bootloader loading FreeRTOS problems

As far as I know I’m not telling the processor there’s no flash at address zero. I am not doing any sort of manual remapping at all. The linker is doing it all. I am sure that the issue is not there because with a run-to-complete program, this method works beautifully. I’m probably misunderstanding what you’re saying though. I have found this in the map file:
 .text.vPortSVCHandler
                0x08003394       0x20 THUMB Flash Debug/port.o
                0x08003394                vPortSVCHandler
Which to me looks fine as it’s above 0x8003000. As far as I understand, you can map the start of code to be anywhere in the legitimate flash region and the linker just takes care of it. My suspicion is that something in FreeRTOS does some hard coding to point at an area below my new start address. I would stress that this is only a suspicion and I could be talking through my backside! :~) I would also stress that if this technique didn’t work for a run-to-complete program I would think it’s a problem with my methodology. Does that make sense or am I talking nonsense? I am aware that this is taking your valuable time and I am quite happy to pay you to help fix this with some off-line help and then post the solution when we have fixed it. Thanks again.

STM32 Bootloader loading FreeRTOS problems

As far as I know I’m not telling the processor there’s no flash at address zero.
Previously you said:
All I am doing to normal FreeRTOS is going into the xml file that descibes the processor and changing the memory map for flash to start at 0x8003000 and change its length accordingly
Presumably it used to start at address 0x8000000, and then again presumably that memory region is mirrored at address 0 when you boot (you would have to look at the memory map for the device you are using in its reference manual).
I have found this in the map file:
.text.vPortSVCHandler
                0x08003394       0x20 THUMB Flash Debug/port.o
                0x08003394                vPortSVCHandler
Which confirms my suspicion that the vector table is not populated with the FreeRTOS interrupt handlers, because is shows that vPortSVCHandler and SVCHandler are not #defined to be the same thing.  SVCHandler is the function that is in the vector table, and it shouldn’t be.
My suspicion is that something in FreeRTOS does some hard coding to point at an area below my new start address.
You can be assured that is not the case.
I would also stress that if this technique didn’t work for a run-to-complete program I would think it’s a problem with my methodology.
Is the run to complete code executing an SVC instruction that has its own bespoke handler though?
I am aware that this is taking your valuable time and I am quite happy to pay you to help fix this with some off-line help and then post the solution when we have fixed it.
Thanks for the offer – but I prefer to keep these threads online so people with the same problems in the future can hopefully get prompts to sort their own issues without having to start their own threads.  I think these support forums, over time (and this one has been here a long time!) are an invaluable developer resource.  We all struggle with these low level issue from time to time. Could you please post the code that actually sets up the vector table – that is the source code rather than the linker output?  It will be defined in one of the start up files, which could be either a C file or an asm file. Regards.

STM32 Bootloader loading FreeRTOS problems

Presumably it used to start at address 0x8000000, and then again presumably that memory region is mirrored at address 0 when you boot (you would have to look at the memory map for the device you are using in its reference manual).
Ah, yes. I didn’t understand about the mirroring at address zero.
Is the run to complete code executing an SVC instruction that has its own bespoke handler though?
No, I have never come across an SVC instruction before this investigation. I assume this source code is what you’re after for setting up the vector table (this looks quite like a standard Crossworks file to me):
_vectors:
  .word __stack_end__
#ifdef STARTUP_FROM_RESET
  .word reset_handler
#else
  .word reset_wait
#endif /* STARTUP_FROM_RESET */
  .word NMIException
  .word HardFaultException
  .word MemManageException
  .word BusFaultException
  .word UsageFaultException
  .word 0 // Reserved
  .word 0 // Reserved
  .word 0 // Reserved
  .word 0 // Reserved
  .word vPortSVCHandler
  .word DebugMonitor
  .word 0 // Reserved
  .word xPortPendSVHandler
  .word xPortSysTickHandler
  .word WWDG_IRQHandler
  .word PVD_IRQHandler
  .word TAMPER_IRQHandler
  .word RTC_IRQHandler
  .word FLASH_IRQHandler
  .word RCC_IRQHandler
  .word EXTI0_IRQHandler
  .word EXTI1_IRQHandler
  .word EXTI2_IRQHandler
  .word EXTI3_IRQHandler
  .word EXTI4_IRQHandler
  .word DMAChannel1_IRQHandler
  .word DMAChannel2_IRQHandler
  .word DMAChannel3_IRQHandler
  .word DMAChannel4_IRQHandler
  .word DMAChannel5_IRQHandler
  .word DMAChannel6_IRQHandler
  .word DMAChannel7_IRQHandler
  .word ADC_IRQHandler
  .word USB_HP_CAN_TX_IRQHandler
  .word USB_LP_CAN_RX0_IRQHandler
  .word CAN_RX1_IRQHandler
  .word CAN_SCE_IRQHandler
  .word EXTI9_5_IRQHandler
  .word TIM1_BRK_IRQHandler
  .word TIM1_UP_IRQHandler
  .word TIM1_TRG_COM_IRQHandler
  .word TIM1_CC_IRQHandler
  .word TIM2_IRQHandler
  .word TIM3_IRQHandler
  .word TIM4_IRQHandler 
  .word I2C1_EV_IRQHandler
  .word I2C1_ER_IRQHandler
  .word I2C2_EV_IRQHandler
  .word I2C2_ER_IRQHandler
  .word SPI1_IRQHandler
  .word SPI2_IRQHandler
  .word USART1_IRQHandler
  .word USART2_IRQHandler
  .word USART3_IRQHandler
  .word EXTI15_10_IRQHandler
  .word RTCAlarm_IRQHandler
  .word USBWakeUp_IRQHandler
  .word TIM8_BRK_IRQHandler
  .word TIM8_UP_IRQHandler
  .word TIM8_TRG_COM_IRQHandler
  .word TIM8_CC_IRQHandler
  .word ADC3_IRQHandler
  .word FSMC_IRQHandler
  .word SDIO_IRQHandler
  .word TIM5_IRQHandler
  .word SPI3_IRQHandler
  .word UART4_IRQHandler
  .word UART5_IRQHandler
  .word TIM6_IRQHandler
  .word TIM7_IRQHandler
  .word DMA2_Channel1_IRQHandler
  .word DMA2_Channel2_IRQHandler
  .word DMA2_Channel3_IRQHandler
  .word DMA2_Channel4_5_IRQHandler
  .section .init, “ax”
  .thumb_func   reset_handler:
#ifndef __FLASH_BUILD
  /* If this is a RAM build, configure vector table offset register to point
     to the RAM vector table. */
  ldr r0, =0xE000ED08
  ldr r1, =_vectors
  str r1,
#endif
  b _start DEFAULT_ISR_HANDLER NMIException
DEFAULT_ISR_HANDLER HardFaultException
DEFAULT_ISR_HANDLER MemManageException
DEFAULT_ISR_HANDLER BusFaultException
DEFAULT_ISR_HANDLER UsageFaultException
DEFAULT_ISR_HANDLER SVCHandler
DEFAULT_ISR_HANDLER DebugMonitor 
DEFAULT_ISR_HANDLER PendSV
DEFAULT_ISR_HANDLER SysTickHandler
DEFAULT_ISR_HANDLER WWDG_IRQHandler
DEFAULT_ISR_HANDLER PVD_IRQHandler
DEFAULT_ISR_HANDLER TAMPER_IRQHandler
DEFAULT_ISR_HANDLER RTC_IRQHandler
DEFAULT_ISR_HANDLER FLASH_IRQHandler
DEFAULT_ISR_HANDLER RCC_IRQHandler
DEFAULT_ISR_HANDLER EXTI0_IRQHandler
DEFAULT_ISR_HANDLER EXTI1_IRQHandler
DEFAULT_ISR_HANDLER EXTI2_IRQHandler
DEFAULT_ISR_HANDLER EXTI3_IRQHandler
DEFAULT_ISR_HANDLER EXTI4_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel1_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel2_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel3_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel4_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel5_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel6_IRQHandler
DEFAULT_ISR_HANDLER DMAChannel7_IRQHandler
DEFAULT_ISR_HANDLER ADC_IRQHandler
DEFAULT_ISR_HANDLER USB_HP_CAN_TX_IRQHandler
DEFAULT_ISR_HANDLER USB_LP_CAN_RX0_IRQHandler
DEFAULT_ISR_HANDLER CAN_RX1_IRQHandler
DEFAULT_ISR_HANDLER CAN_SCE_IRQHandler
DEFAULT_ISR_HANDLER EXTI9_5_IRQHandler
DEFAULT_ISR_HANDLER TIM1_BRK_IRQHandler
DEFAULT_ISR_HANDLER TIM1_UP_IRQHandler
DEFAULT_ISR_HANDLER TIM1_TRG_COM_IRQHandler
DEFAULT_ISR_HANDLER TIM1_CC_IRQHandler
DEFAULT_ISR_HANDLER TIM2_IRQHandler
DEFAULT_ISR_HANDLER TIM3_IRQHandler
DEFAULT_ISR_HANDLER TIM4_IRQHandler
DEFAULT_ISR_HANDLER I2C1_EV_IRQHandler
DEFAULT_ISR_HANDLER I2C1_ER_IRQHandler
DEFAULT_ISR_HANDLER I2C2_EV_IRQHandler
DEFAULT_ISR_HANDLER I2C2_ER_IRQHandler
DEFAULT_ISR_HANDLER SPI1_IRQHandler
DEFAULT_ISR_HANDLER SPI2_IRQHandler
DEFAULT_ISR_HANDLER USART1_IRQHandler
DEFAULT_ISR_HANDLER USART2_IRQHandler
DEFAULT_ISR_HANDLER USART3_IRQHandler
DEFAULT_ISR_HANDLER EXTI15_10_IRQHandler
DEFAULT_ISR_HANDLER RTCAlarm_IRQHandler
DEFAULT_ISR_HANDLER USBWakeUp_IRQHandler
DEFAULT_ISR_HANDLER TIM8_BRK_IRQHandler
DEFAULT_ISR_HANDLER TIM8_UP_IRQHandler
DEFAULT_ISR_HANDLER TIM8_TRG_COM_IRQHandler
DEFAULT_ISR_HANDLER TIM8_CC_IRQHandler
DEFAULT_ISR_HANDLER ADC3_IRQHandler
DEFAULT_ISR_HANDLER FSMC_IRQHandler
DEFAULT_ISR_HANDLER SDIO_IRQHandler
DEFAULT_ISR_HANDLER TIM5_IRQHandler
DEFAULT_ISR_HANDLER SPI3_IRQHandler
DEFAULT_ISR_HANDLER UART4_IRQHandler
DEFAULT_ISR_HANDLER UART5_IRQHandler
DEFAULT_ISR_HANDLER TIM6_IRQHandler
DEFAULT_ISR_HANDLER TIM7_IRQHandler
DEFAULT_ISR_HANDLER DMA2_Channel1_IRQHandler
DEFAULT_ISR_HANDLER DMA2_Channel2_IRQHandler
DEFAULT_ISR_HANDLER DMA2_Channel3_IRQHandler
DEFAULT_ISR_HANDLER DMA2_Channel4_5_IRQHandler

STM32 Bootloader loading FreeRTOS problems

Hmm.  That is curious.  The correct vectors do seem to be being installed, but the linker output from your previous post would seem to show the wrong vectors actually in the table. Could you zip up your entire project (all source files, and project files) in a way that allows me to build it easily (don’t use any absolute paths to source files or include files) and send it to me?  You can send it to r dot barry at freertos.org. Regards.

STM32 Bootloader loading FreeRTOS problems

I have not yet managed to program the board, but I have found that the code in post 9 is not what I thought it was.  It is not the vector table at all.  It seems the correct handler is being installed. Regards.

STM32 Bootloader loading FreeRTOS problems

Ok – running your code, now. When the svc instruction is executed it jumps to address 0x8000100, which according to the map file is not in your program.  Trying to execute instructions from that address results in a branch to 0x800018E, which then just branches to itself.  Note that 0x800018E is not in the intended defined memory range either.  Just to prove the point, I erased all the flash, and tried running it again and, sure enough now it just branches wildly off the planet as far as the CPU is concerned. I think your problems start with the way you have attempted to move the program, and I believe the correct thing to do is leave the memory map file alone, and edit the section placement file (having first made a local copy in your project). Look up flash_placement in the Rowley help system.  I believe the thing to do is use the project properties section placement macros to move the start of the .text section to 0x8003000.  Having said that, I have before just manually edited one.  Below is an example (not correct for your application) I created some time ago to generate extra sections for specific placement when using the MPU.  [note the privileged_functions sections I added in, and defined its size, there is also a start parameter you can use I think).
<!DOCTYPE Linker_Placement_File>
<Root name="FLASH Section Placement">
  <MemorySegment name="FLASH">
    <ProgramSection load="Yes" inputsections="*(.vectors .vectors.*)" name=".vectors"/>
    <ProgramSection alignment="4" size="16K - 0x100" load="Yes" inputsections="*(privileged_functions)" name="privileged_functions"/>
    <ProgramSection alignment="4" load="Yes" inputsections="*(.init .init.*)" name=".init"/>
    <ProgramSection alignment="4" load="Yes" inputsections="*(.text .text.* .glue_7t .glue_7 .gnu.linkonce.t.* .gcc_except_table)" name=".text"/>
    <ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors))" name=".dtors"/>
    <ProgramSection alignment="4" load="Yes" inputsections="KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors))" name=".ctors"/>
    <ProgramSection alignment="4" load="Yes" inputsections="*(.rodata .rodata.* .gnu.linkonce.r.*)" name=".rodata"/>
    <ProgramSection alignment="4" load="Yes" runin=".data_run" inputsections="*(.data .data.* .gnu.linkonce.d.*)" name=".data"/>
    <ProgramSection alignment="4" load="Yes" runin=".fast_run" inputsections="*(.fast .fast.*)" name=".fast"/>
  </MemorySegment>
  <MemorySegment name="SRAM">
    <ProgramSection alignment="4" size="256" alignment="256" load="No" inputsections="*(privileged_data)" name="privileged_data"/>
    <ProgramSection name=".vectors_ram" size="" alignment="0x100" load="No"/>    
    <ProgramSection alignment="4" load="No" name=".data_run"/>
    <ProgramSection alignment="4" load="No" inputsections="*(.bss .bss.* .gnu.linkonce.b.*) *(COMMON)" name=".bss"/>
    <ProgramSection alignment="4" load="No" inputsections="*(.non_init .non_init.*)" name=".non_init"/>
    <ProgramSection alignment="4" size="__HEAPSIZE__" load="No" name=".heap"/>
    <ProgramSection alignment="4" size="__STACKSIZE__" load="No" name=".stack"/>    
    <ProgramSection alignment="4" load="No" name=".fast_run"/>
  </MemorySegment>
</Root>
Regards.

STM32 Bootloader loading FreeRTOS problems

Hi Richard, I really don’t think that is the answer I’m afraid. I’ve tried changing it and it makes no difference. I went back to an email I had from Michael at Rowley, describing what I’d done when I initially had issues with by run-to-complete program with the bootloader. He said: You can use the section placement macro “FLASH_START=0x08003000″ and this will have the same effect as the memory map change. So Michael was essentially saying said that my way is one method of doing it, the other is FLASH_START=0x08003000 I have searched high and wide and I cannot find anywhere that describes how to use FLASH_START=0x08003000. I’ve found places that say do this: <MemorySegment name=”FLASH” start=”0x8003000″ size=”0x1D000″ /> In the flash_placement.xml file, but that does nothing. I’ve written to Rowley for clarification, but this: https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSTM32F207IG%20w%20STM3220G%20eval%20bootloading%20issue&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=575 To me indicates I am doing the right thing. Hopefully, Michael will be able to shed some light on it.

STM32 Bootloader loading FreeRTOS problems

It seems Michael is making the same suggestion as me – to use the placement macros.  Have you actually tried it though? I just went back to the original, unmodified FreeRTOS demo (as downloaded in the official FreeRTOS zip file), then copied the section placement file into the project file (as per my post above) and made a single edit to move the start of the flash, as:
<ProgramSection alignment="4" load="Yes" name=".text"  start="0x8003000"/>
compiled and downloaded – and it appears to do exactly what you want.  main() is above “0x8003000”, and calling SVC jumps to the correct SVC handler, which is also above “0x8003000”, the kernel starts and the tasks seem to be running. Regards.

STM32 Bootloader loading FreeRTOS problems

Slight correction – I didn’t move the start of the flash, I moved the start of the .text section.  The .vectors section is still at zero. Regards.

STM32 Bootloader loading FreeRTOS problems

That does, indeed, load and execute from 0x8003000, thanks. The bootloader now seems to be corrupting something, so is not working. That”ll be a bug in my code I imagine. I’ll report back once it’s going.

STM32 Bootloader loading FreeRTOS problems

Actually, that’s not right. Although the C code seems to start later that 0x8003000, all the assembler initialisation starts below there. That’s why it was crashing once I tried the bootloader.

STM32 Bootloader loading FreeRTOS problems

What I did was get your experimental case working – when all that was done was move the .text section up to leave a gap for your boot loader.  Now it is back to the start of the thread, which was originally about getting a boot loader to work. Moving the .text section has left the .vectors where it was, so the CPU is booting normally from 0x00 and the vector table is telling it to run code that starts at 0x8003000.  Now you have to have a second copy of the vector table for the application, and remap the vector table the CPU is used (using the vector base register).  You can do that by either having the vector table in the flash image starting at 0x8003000, or copy the vector table to RAM.  That is over to you … Regards.

STM32 Bootloader loading FreeRTOS problems

Would you email me that project back please? -The one you now have going I mean because I simply cannot get it going. I guess I am missing a step out or something; this is driving me absolutely nuts.  Thanks again.

STM32 Bootloader loading FreeRTOS problems

I have been playing endlessly today and the only way I can get the vectors to live at 0x8003000 is to change the ST_STM32F103RB_MemoryMap.xml with the line  <MemorySegment size=”0x1D000″ access=”ReadOnly” name=”FLASH” start=”0x08003000″/> I have tried a million different things now and nothing else will do it. I can get your method to shift the *code* start to 0x08003000, but it does not change the vectors. The only thing that shifts the vectors is my method, but once it gets to the svc 0 Instruction it leaps off to somewhere before 0x8003000. What on earth am I missing here? What do I not understand? What does this svc instruction *do* and who do non-FreeRTOS programs work just fine? I must confess I just do not understand what this means:
Moving the .text section has left the .vectors where it was, so the CPU is booting normally from 0x00 and the vector table is telling it to run code that starts at 0x8003000. Now you have to have a second copy of the vector table for the application, and remap the vector table the CPU is used (using the vector base register).
I’m on the verge of throwing the computer out of the window and/or having an embolism here.

STM32 Bootloader loading FreeRTOS problems

I must confess I just do not understand what this means:
Moving the .text section has left the .vectors where it was, so the CPU is booting normally from 0x00 and the vector table is telling it to run code that starts at 0x8003000. Now you have to have a second copy of the vector table for the application, and remap the vector table the CPU is used (using the vector base register). Knowing these things, I have to say, is a prerequisite for writing a boot loader.  If you look at the section placement file, and the map file, you will see the vector table is in a section called .vectors that heads up the entire program.  Your application code then sits in the .text section. The SVC instruction is a software interrupt.  It causes the CPU to act just like a hardware interrupt or exception has been accepted, and branch to an address stored in the exception table.  Again, this is really detailed information that is required to write a boot loader. If you have a boot loader running, and the (non-FreeRTOS) application it is loading and running from 0x8003000 is using interrupts, and the interrupts it is using are different to those used by your bootloader, then the same bootloader should work for an application that uses FreeRTOS. As per my previous posts – the first thing the CM3 is going to do when it comes out of reset is load its stack and execution start point from address zero (or whatever memory is mapped to address 0 by whatever configuration methods there are).  There is nothing you can do about that – you must have these values, and any other interrupt vectors used by the boot loader in a vector table that starts at a logical address 0. If you want to load another program than has a separate vector table, like a FreeRTOS application, or in fact any application, then you need to have another vector table loaded too – and set the vector base address to point to the right one at the right time (the bootloader one when the bootloader is running, and the application one when the application is running).  How you do that is up to you.  A very common way of doing it is to copy the hard coded vector table from the flash image into RAM, where you can then simply write in the handler addresses as part of your start up code. Regards.

STM32 Bootloader loading FreeRTOS problems

First of all I want to say, I really appreciate your patience with me, so thank you ever so much for that. I appreciate I have gaps in my knowledge and I am doing my best to fill these gaps. :~) I totally understand what you are saying about having to have two vector tables, this completely makes sense. However, if I use my method of remapping everything (which works with the run-to-complete program), this does not work with FreeRTOS. I can see in the map file that *everything* starts at 0x8003000, including all the vectors. Now, one thing I have just stumbled across is this line in the prvSetupHardware() routine:
/* Set the Vector Table base address at 0x08000000. */
NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 );
Now, is this not hardcoding the Vector table away from 0x8003000 and therefore screwing things up when the svc instruction is called? Thanks again.

STM32 Bootloader loading FreeRTOS problems

Yes – that makes sense, and that will definitely mess you up – but it is also outside the FreeRTOS kernel code (i.e. it is in the demo app code).  It looks like an STM32 driver library function and should not be needed anyway.  I suspect it originated from a demo that copied vectors to RAM and then remapped the vector table, them when the code was executed from Flash the line was adjusted rather than removed.  You should definitely remove it. Regards.

STM32 Bootloader loading FreeRTOS problems

That was a red herring. Makes no difference at all. I am now suspecting there’s something else amiss because I went back to my run-to-complete program starting at 8003000, so I could look at the SCB registers and try to make sense of it. After erasing all flash, that  jumped off into the middle of nowhere. If I then first program from 8000000, don’t erase and then program from 8003000 it works again without jumping into the middle of nowhere.  So, now I’m even further away from having things working and understanding what’s going on. That line: NVIC_SetVectorTable( NVIC_VectTab_FLASH, 0x0 ); Is in the demo you sent too.

STM32 Bootloader loading FreeRTOS problems

Well, I think it was all down to the flash not being locked after the self programming was finished. I finally tracked it down after having a friend sit with me and we went through FreeRTOS vs run-to-complete versions line -by-line.  What seemed to happen was for some reason the vector table, even though it was being programmed correctly, was getting corrupted somehow once the last line had come in over RS485. Locking the flash seems to have solved it. Thanks again for your patience in deal with such a dullard.