2021-06-22 08:00 AM
I developed my first canbus bootloader for a stm32f105.
Now im in need to use that same bootloader in a stm32f072.
The bootloader works but im unable to build a program that starts from a flash address other than 0x8000000.....
How are multi programm apps being programmes in stm32f0xx families?
Solved! Go to Solution.
2021-07-05 12:54 AM
Okay i built the courage to give this another go and made it work.
What i did ( following your steps @Community member :(
/* USER CODE BEGIN PD */
#define VECTOR_TABLE_SIZE (31 + 1 + 7 +9)//31 positive vectors, 0 vector, and 7 negative vectors (and extra 9 i dont know why)
#define SYSCFG_CFGR1_MEM_MODE__MAIN_FLASH 0 // x0: Main Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SYSTEM_FLASH 1 // 01: System Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SRAM 3 // 11: Embedded SRAM mapped at 0x0000 0000
/* USER CODE END PD */
..........
/* USER CODE BEGIN PV */
volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];
extern volatile uint32_t g_pfnVectors[VECTOR_TABLE_SIZE];
/* USER CODE END PV */
placed the function before system init
int main(void)
{
/* USER CODE BEGIN 1 */
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // early enable to ensure clock is up and running when it comes to usage
for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) {//copy vector table
ram_vector[i] = g_pfnVectors[i];
}
SYSCFG->CFGR1 = (SYSCFG->CFGR1 & ~SYSCFG_CFGR1_MEM_MODE) | (SYSCFG_CFGR1_MEM_MODE__SRAM * SYSCFG_CFGR1_MEM_MODE_0); // remap 0x0000000 to RAM
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
...............................
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/*javi*/
/*https://community.st.com/s/question/0D53W00000trgpiSAA/how-to-boot-to-random-address-without-vecttaboffset-stm32f072*/
/* redirected vector must go to top of the RAM */
.ram_vector :
{
*(.ram_vector)
} >RAM
/*javi*/
.................
2021-06-22 08:08 AM
okay, i found someone with my same issue in stack overflow
https://stackoverflow.com/questions/64152604/no-vtor-offset-given-in-stm32f072
2021-06-22 08:10 AM
There's no VTOR register in Cortex-M0.
You have to remap RAM to the 0x0000'0000 area (see SYSCFG_CFGR1.MEM_MODE), and copy the custom vector table (from the application's beginning) there.
JW
2021-06-23 12:18 AM
Reference manual page 168 explains the SYSCFG mem_mode bits.
MEM_MODE[1:0]: Memory mapping selection bits
These bits are set and cleared by software. They control the memory internal mapping at
address 0x0000 0000. After reset these bits take on the value selected by the actual boot
mode configuration. Refer to Chapter 2.5: Boot configuration for more details.
x0: Main Flash memory mapped at 0x0000 0000
01: System Flash memory mapped at 0x0000 0000
11: Embedded SRAM mapped at 0x0000 0000
So in a normal programm
But now we want
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 18K
APP (rx) : ORIGIN = 0x08004800, LENGTH = 34K
Configuration (rx) : ORIGIN = 0x0800D000, LENGTH = 2K
Patterns (rx) : ORIGIN = 0x0800D800, LENGTH = 10K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >RAM//<-- changed isr table to be in ram memory
@Community member Once i do this, Does the linker table know that the first part of the sram should not be overwriten?
2021-06-23 02:10 AM
> Also the ref manual says MEM_MODE value doesnt reset to 0x00 but it does, if i set it to 0x03 after reset appears as 0x00 again
It resets to the value set by the boot procedure, e.g. if BOOT0 pin is high, it is set during boot to 0b01 to boot from the System Memory (i.e. bootloader). Thus, "normally", after reset it is set to 0b00 to boot from the "normal" FLASH.
> Once i do this, Does the linker table know that the first part of the sram should not be overwriten?
No, you should do it yourself.
There are several ways to achieve this.
As an example, in 'F031, I declare this:
#define SYSCFG_CFGR1_MEM_MODE__MAIN_FLASH 0 // x0: Main Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SYSTEM_FLASH 1 // 01: System Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SRAM 3 // 11: Embedded SRAM mapped at 0x0000 0000
#define VECTOR_TABLE_SIZE (USART1_IRQn /* highest supported ISR in F031 */ + 1 + 16 /* because there are "negative counted" system-exceptions and interrupts, too */)
volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];
extern volatile uint32_t g_pfnVectors[VECTOR_TABLE_SIZE];
then, as first thing in main() (*) I do this:
int main(void) {
{
uint32_t i;
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // early enable to ensure clock is up and running when it comes to usage
for (i = 0; i < VECTOR_TABLE_SIZE; i++) {
ram_vector[i] = g_pfnVectors[i];
}
SYSCFG->CFGR1 = (SYSCFG->CFGR1 AND ~SYSCFG_CFGR1_MEM_MODE) OR (SYSCFG_CFGR1_MEM_MODE__SRAM * SYSCFG_CFGR1_MEM_MODE_0); // remap 0x0000000 to RAM
}
[continue with main()]
Note, that I don't use Cube's envirnoment, thus I don't have any SystemInit() or similar call in the startup code.
Symbol g_pfnVectors comes from the startup code, it's the label of the vector table, as it is located in FLASH at the beginning of the application:
startupXXXX.S:
[...]
/******************************************************************************
*
* The minimal vector table for a Cortex M0. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
[etc]
And I make sure the vector table copy in RAM goes as first to the top of RAM by placing an explicit section as the first input section going into RAM, in linker script:
[here ends the code (FLASH) section]
/* redirected vector must go to top of the RAM */
.ram_vector :
{
*(.ram_vector)
} >RAM
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
[etc]
JW
2021-06-23 02:48 AM
@Community member
>It resets to the value set by the boot procedure, e.g. if BOOT0 pin is high, it is set during boot to 0b01 to boot from the System Memory (i.e. bootloader). Thus, "normally", after reset it is set to 0b00 to boot from the "normal" FLASH.
Thats bad news because i have no acess to the BOOT0 pin.
So what youre doing is : (it took me some time to digest)
So somehow my bootloader needs to have its isrvector table at the beginning of my flash memory (0x8000 0000), as it normally would do.
Bootloader has a reserved space in RAM for the isr of my app?
Before jumping to my app i need to:
Is this doable?:
>And I make sure the vector table copy in RAM goes as first to the top of RAM by placing an explicit section as the first input section going into RAM, in linker script:
I would also need to do this
2021-06-23 03:25 AM
What I do is, I leave things as they are normally, for the bootloader.
I perform the copy of vector table and change to SYSCFG->CFGR1 as the first thing in main() of the application. I anticipate, that there's no interrupt enabled by that point, and that nothing will throw a fault (i.e. there's no need for the vector table).
As I've said, there are several ways to do this; yes, this all can be done also in the bootloader, but I decided to do it otherwise.
JW
2021-06-23 04:55 AM
I am trying it your way, i like it.
questions from your code
.ram_vector :
{
*(.ram_vector)
} >RAM
where is .ram_vector comming from?from the volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];?
#define VECTOR_TABLE_SIZE (USART1_IRQn /* highest supported ISR in F031 */ + 1 + 16 /* because there are "negative counted" system-exceptions and interrupts, too */)
////i didnt undestood that, the reference manual says STM32f0xx devices have a vector table the size of 31+1+7 vectors
volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];
////i have no idea of what this does, is this telling the linker what .ram_vector is?
extern volatile uint32_t g_pfnVectors[VECTOR_TABLE_SIZE];
////thisone looks for the somewhere else defined g_pfnVectors but i dont get the [VECTOR_TABLE_SIZE] part, shouldnt g_pfnVectors have a fixed already defined size?
2021-06-23 05:41 AM
> linker script
> where is .ram_vector coming from?
The name, "ram_vector" is a name arbitrarily chosen by me.
I need to tell the linker, "put my vector array as the first thing into RAM". So, in linker script, I insert those lines above anything else which would go into RAM.
Then, in program, I define the array as
> volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];
which tells the linker, that this variable should go to the .ram_vector section (the "\"aw\" etc. part... I honestly don't remember the exact reason, this is probably intended to prevent linker to put initialization values into FLASH; a similar effect should be achievable by tagging the .ram_vector as NOLOAD - usually there are several alternative ways to do things).
>> #define VECTOR_TABLE_SIZE (USART1_IRQn /* highest supported ISR in F031 */ + 1 + 16 /* because there are "negative counted" system-exceptions and interrupts, too */)
> ////i didnt undestood that, the reference manual says STM32f0xx devices have a vector table the size of 31+1+7 vectors
Yes, it's safe to define simply 31 + 1 + 7.
I always attempt to reduce consumed memory - there's no need to go beyond USART1 specifically in 'F031, for which this was intended, as there are no peripherals which have interrupts with higher numbers in that model. On the other hand, in this particular application where I took this from, USART1 is indeed used with interrupt; would it not be used I'd put the highest used ISR's number there.
This is a minor optimization which you may be not needing.
> extern volatile uint32_t g_pfnVectors[VECTOR_TABLE_SIZE];
> ////thisone looks for the somewhere else defined g_pfnVectors
Yes, I have it as a label at the beginning of the vector table, in the startup file.
> shouldnt g_pfnVectors have a fixed already defined size?
Yes, even with optimizing the size of the array in RAM, this indeed might always have the full size.
JW
2021-07-05 12:54 AM
Okay i built the courage to give this another go and made it work.
What i did ( following your steps @Community member :(
/* USER CODE BEGIN PD */
#define VECTOR_TABLE_SIZE (31 + 1 + 7 +9)//31 positive vectors, 0 vector, and 7 negative vectors (and extra 9 i dont know why)
#define SYSCFG_CFGR1_MEM_MODE__MAIN_FLASH 0 // x0: Main Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SYSTEM_FLASH 1 // 01: System Flash memory mapped at 0x0000 0000
#define SYSCFG_CFGR1_MEM_MODE__SRAM 3 // 11: Embedded SRAM mapped at 0x0000 0000
/* USER CODE END PD */
..........
/* USER CODE BEGIN PV */
volatile uint32_t __attribute__((section(".ram_vector,\"aw\",%nobits @"))) ram_vector[VECTOR_TABLE_SIZE];
extern volatile uint32_t g_pfnVectors[VECTOR_TABLE_SIZE];
/* USER CODE END PV */
placed the function before system init
int main(void)
{
/* USER CODE BEGIN 1 */
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // early enable to ensure clock is up and running when it comes to usage
for (uint32_t i = 0; i < VECTOR_TABLE_SIZE; i++) {//copy vector table
ram_vector[i] = g_pfnVectors[i];
}
SYSCFG->CFGR1 = (SYSCFG->CFGR1 & ~SYSCFG_CFGR1_MEM_MODE) | (SYSCFG_CFGR1_MEM_MODE__SRAM * SYSCFG_CFGR1_MEM_MODE_0); // remap 0x0000000 to RAM
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
...............................
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/*javi*/
/*https://community.st.com/s/question/0D53W00000trgpiSAA/how-to-boot-to-random-address-without-vecttaboffset-stm32f072*/
/* redirected vector must go to top of the RAM */
.ram_vector :
{
*(.ram_vector)
} >RAM
/*javi*/
.................