STM32 Bootloader loading FreeRTOS problems

dibosco wrote on Saturday, July 07, 2012:

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.

rtel wrote on Saturday, July 07, 2012:

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.

dibosco wrote on Saturday, July 07, 2012:

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.

dibosco wrote on Saturday, July 07, 2012:

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.

rtel wrote on Saturday, July 07, 2012:

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.

dibosco wrote on Saturday, July 07, 2012:

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.

rtel wrote on Saturday, July 07, 2012:

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.

dibosco wrote on Sunday, July 08, 2012:

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.

dibosco wrote on Sunday, July 08, 2012:

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.