cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader and STM32F091

fabricepeden
Associate II
Posted on July 27, 2016 at 17:24

Hi everybody,

I try to make a bootloader with my STM32f091 to copy a new firmware to my boards using the Power Line Current. First, I bought the evaluation kit (STEVAL-IHP005V1), it works very without any problem (µc use on these boards : STM32F103VB - Cortex M3). The principle is that there are two zones in flash where the both firmwares are located. (cf. figure 21 of UM1619). So I'm trying to the same with my µc (STM32F091 - Cortex M0). So I use the same code :

/* Private define ------------------------------------------------------------*/
#define FLASH_BASE_ADDRESS ((uint32_t)0x08000000)
#define BOOT_LOADER_SIZE (0x1000) /* 4 Kb (3 Kb Boot loader firmware -max-, 1 Kb boot loader data) */
#define IMAGE_MAX_SIZE (0x19000)
#define BOOT_DATA_SIZE (0x400) /* 1 Kb */
//#define FLASH_PAGE_SIZE (0x400) /* 1 Kb */
#define BOOT_DATA_ADDRESS (FLASH_BASE_ADDRESS + BOOT_LOADER_SIZE - BOOT_DATA_SIZE)
#define ACTIVE_IMAGE_ADDRESS (BOOT_DATA_ADDRESS)
#define FIRST_IMAGE_ADDRESS (FLASH_BASE_ADDRESS + BOOT_LOADER_SIZE)
#define SECOND_IMAGE_ADDRESS (FIRST_IMAGE_ADDRESS + IMAGE_MAX_SIZE)
#define DEFAULT_IMAGE_ADDRESS FIRST_IMAGE_ADDRESS
/* ADRESSE DE BASE DU BOOTLOADER : 0x0800 0000 */
/* ACTIVE IMAGE ADRESSE : 0x0800 0C00 */
/* FIRMWARE #1 : 0x0800 1000 */
/* FIRMWARE #2 : 0x0801 9FFF */
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
int *application_address = (int *)BOOT_DATA_ADDRESS;
int vector_table_address;
int test = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/*******************************************************************************
* Function Name : main
* Description : Main program 
* Input : None
* Output : None
* Return : None
*******************************************************************************/
main(void)
{
/* Read the active image and default vector table address */
test = FIRST_IMAGE_ADDRESS;
application_address = &test;
/* Set the correct offsets before jump to new image */
vector_table_address = *application_address;
application_address = (int *)(vector_table_address + 4);
/* Jump to application */
__set_MSP(*(int*)vector_table_address);
*(int *)(0xE000ED08) = 0x08001000; /* SCB->VTOR */
((void (*)(void))(*application_address))();
while(1);
}

It seems to work up to the following line *(int *)(0xE000ED08) = 0x08001000 which normally allows to remap the vector table. I saw on different website also this instruction : SCB->VTOR = *** but my compiler doesn't know it. Then I have found on some website that with M0 I cannot remap the vector table. Could you confirm it or not ? https://www.lpcware.com/content/forum/2nd-bootloader-requiring-the-same-interrupt-in-bootloader-and-main-application http://www.embedded.com/print/4229843 Thank you in advance, Best regards, Fabrice #bootloader-cortex-m0
6 REPLIES 6
Posted on July 27, 2016 at 17:52

The Cortex-M0 doesn't have a VTOR you can change, it is always ZERO

The method for the M0 is to copy the new vector table to the base of RAM (0x20000000) and then use the STM32's method of mapping RAM at ZERO (register equivalent of BOOTx pins)

Covered here a bunch of times, review threads. Look also at M0 IAP examples.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabricepeden
Associate II
Posted on July 27, 2016 at 21:02

Thank you for your confirmation.

Just to know, only the vector table must be moved (and all the firmware will be in the flash or it'll be in the RAM also ?).

I'll check on the forum to find some examples.

Posted on July 27, 2016 at 21:23

Just the words from the vector table, and then remapping the RAM at 0x000000000 instead of the FLASH. You must make sure that the RAM area used by the vector table isn't used for other variables, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabricepeden
Associate II
Posted on July 28, 2016 at 15:29

Thank you for advices, it works perfectly.

jparera
Associate II
Posted on July 28, 2016 at 17:46

Hi clive thanks for answering,

I am using the 64kB nad i have 3 projects runing on the same flash, I did an IAP programming that writes the flash of App1 or App2 from App2 or App1

ROM and .intvect start  0x8000000  mineBOOT

ROM and .intvect start  0x8001800  App1

ROM and .intvect  start 0x8008800 App2

I managed to load the Binary from APP1,or App2 I just need the so called mineBoot for chosing wich App I run, by jumping to App1 or App2 I don't even need interrupts on the Boot code but I do need interrupts on the App1 or App2 Programs. and its the thing i dont manage to succed, I really thought that I solved this months ago but seems I didn't.

The remaptable function should be placed at first line of main in App1(remap to 0x8001800) or App2 ( remap to 0x807f00), the Ram on App1 or App2 should be offset 0x20000c0.

if I jump from 0x80000 to 0x80018 I don't have to place a remap to 0x8001800. I read that I musn't have pending interrupts before jumping, I disable interrupts before jumping with same result.I havent enable any interrupts anyways from mineBoot code.

 __disable_interrupt();      

 __disable_irq();

  RCC_DeInit();

 jump();

I also tried the remap function that does . What I am not so sure is that i have to do a RemapTable on the mineBoot main() too?

static void Main_RelocateVectorTable(void)

{

    int i;

    for(i = 0; i < 48; i++) {

        myVectorTable[i] = *(__IO uint32_t*)(APPLICATION_ADDRESS + (i << 2));

    }

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_SRAM);

}

Thanks for reading and the hints

Posted on July 28, 2016 at 18:11

I seem to have to go over this repeatedly,

If you disable interrupts at a CPU level, you need to reenable them on the other side. Ideally you tear down all the interrupts you have at the peripheral and NVIC level. ie if you have the SysTick running you turn it off, if you interrupt on USART1 RXNE you turn that off, so that interrupts aren't occurring, not that you stick a pole in the spokes of a moving wheel to make it stop turning. You can't transfer control from an IRQ or system handler. ie Don't use an EXTI on a button. Watch for RTOS'es, and the execution state the CPU is in. Perhaps more salient with M3/M4 designs. If the vector table is not a the base of FLASH (0x08000000) you must relocate it, otherwise things like fault handlers (Hard Fault, etc) vector into some entirely out-of-context code. It might sort of function, but is going to be a surprise or headache at some point. If you jump back to code that expects the FLASH to be mapped at zero, then you need to do that again if you previously changed it to RAM. Only a reset is going to automatically do this. I'd generally recommend not making assumptions about the initial state, and explicitly setting it to ensure the code that is running has the environment it expects.

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
SYSCFG_MemoryRemapConfig(SYSCFG_MemoryRemap_FLASH);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..