Read the article stm32_iap online upgrade process

First, before diving into the theme, it's essential to understand some basic knowledge about the STM32 series chips and their models:

- startup_stm32f10x_cl.s: Interconnect devices, such as STM32F105xx and STM32F107xx.

- startup_stm32f10x_hd.s: Large capacity STM32F101xx, STM32F102xx, STM32F100xx.

- startup_stm32f10x_ld.s: STM32F103xx.

- startup_stm32f10x_hd_vl.s: Small-capacity large-capacity STM32F101xx, STM32F102xx, STM32F101xx, STM32F100xx.

- startup_stm32f10x_md.s: STM32F103xx.

- startup_stm32f10x_ld_vl.s: Small volume, such as STM32F102xx, STM32F103xx.

- startup_stm32f10x_md_vl.s: Medium capacity STM32F100xx (this chip is used in this project: STM32F100CB).

- startup_stm32f10x_xl.s: FLASH from 512K to 1024K bytes, such as STM32F101xx, STM32F102xx, STM32F103xx.

For example, if the chip flash is STM32F103RE with 512K, you can use either startup_stm32f10x_xl.s or startup_stm32f10x_hd.s.

Cl: Interconnected products; STM32F105/107 series. Vl: Value line products; STM32F100 series. Xl: Ultra high density products; STM32F101/103 series. Ld: Low density products; FLASH less than 64K. Md: Medium density products; FLASH = 64 or 128. Hd: High density products; FLASH greater than 128.

Second, after obtaining the official IAP program from ST company, we need to consider a few key points:

1. What is the official IAP for which chip model? Which chip model are we using?

2. We will use the official IAP program suitable for our chip upgrade and make necessary changes based on the original code.

(I have the official IAP source code in my resources: http://download.csdn.net/detail/yx_l128125/6445811)

After briefly reviewing the IAP source code, we can now answer the above two questions:

1. The official website downloaded the IAP for the STM32F103C8 chip, so its startup code file selects startup_stm32f10x_md.s. Since my chip is STM32F100CB, I choose startup_stm32f10x_md_vl.s.

2. The second question is more detailed and needs to be addressed thoroughly.

(1). Understand the differences between the official IAP source code chip and the chip we want to use. First, we must make chip-level changes based on the source code.

A. First, change the chip model in Keil's compiler settings to our chip type—STM32F100CB.

B. In Keil's options for target, under C/C++/PREPROCESSOR symbols, change the macro definition for STM32F10X_MD to STM32F10X_MD_VL.

Macro definitions can also be found in STM32F10X.H.

/* Uncomment the line below according to the target STM32 device used in your application */

#if !defined (STM32F10X_LD) && !defined (STM32F10X_LD_VL) && !defined (STM32F10X_MD) && !defined (STM32F10X_MD_VL) && !defined (STM32F10X_HD) && !defined (STM32F10X_HD_VL) && !defined (STM32F10X_XL) && !defined (STM32F10X_CL)

/* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */

/* #define STM32F10X_LD_VL */ /*!< STM32F10X_LD_VL: STM32 Low density Value Line devices */

/* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */

#define STM32F10X_MD_VL /*!< STM32F10X_MD_VL: STM32 Medium density Value Line devices */

/* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */

/* #define STM32F10X_HD_VL */ /*!< STM32F10X_HD_VL: STM32 High density value line devices */

/* #define STM32F10X_XL */ /*!< STM32F10X_XL: STM32 XL-density devices */

/* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */

#endif

The above code defines STM32F10X_MD_VL if not defined.

C. Modify the external clock based on the actual configuration in stm32f10x.h. If no macro defines the external clock HSE_VALUE, then if STM32F10X_CL is defined, the external clock is set to 25MHz; otherwise, it is set to 8MHz. Since the external crystal oscillator is 8MHz, there's no need to modify this part of the code.

#if !defined HSE_VALUE

#ifdef STM32F10X_CL

#define HSE_VALUE ((uint32_t)25000000) // Value of the External oscillator in Hz

#else

#define HSE_VALUE ((uint32_t)8000000) //Value of the External oscillator in Hz

#endif /* STM32F10X_CL */

#endif /* HSE_VALUE */

D. Modify the system main clock in system_stm32f10x.c according to the actual situation. The clock frequency of the chip I use is 24MHz.

#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

#else

/* #define SYSCLK_FREQ_HSE HSE_VALUE */

#define SYSCLK_FREQ_24MHz 24000000

/* #define SYSCLK_FREQ_36MHz 36000000 */

/* #define SYSCLK_FREQ_48MHz 48000000 */

/* #define SYSCLK_FREQ_56MHz 56000000 */

/* #define SYSCLK_FREQ_72MHz 72000000 */

#endif

E. The following is the key part of the operation. Let's first talk about memory mapping before discussing this part:

The following figure is from page 29 of the STM32F100 chip manual. We only take the key parts.

From the above picture, we see several key parts:

1. The internal flash starts from 0x08000000 to 0x0801FFFF, ending at 0x0801FFFF - 0x08000000 = 0x20000 = 128k, which is the size of the flash.

2. The starting address of SRAM is 0x20000000.

We need to place our online upgrade program IAP into the FLASH position starting from 0x08000000, and the application puts the APP starting from 0x08003000, with the interrupt vector table also placed at the position starting from 0x08003000.

So we need to look at the initial position of the interrupt vector table in the misc.h file. The macro is defined as NVIC_VectTab_Flash 0x08000000.

Then, set the IROM1 address in the target option of the compiler Keil to 0x08000000 and the size is 0x20000 or 128K.

The IRAM1 address is 0x20000000 and the size is 0x2000.

(Hint: This IROM1 address is the starting position of the address where the current program is downloaded to flash.)

Let's analyze the modified IAP code:

/************************************************* ******************************

* @function name main

* @function description main function

* @Input parameters none

* @output parameter

* @return parameters none

************************************************** *****************************/

int main(void)

{

// Flash unlock

FLASH_Unlock();

// Configure the PA15 pin

KEY_Configuration();

// Configure serial port 1

IAP_Init();

// PA15 is low

if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_15) == 0x00)

{

// Execute the IAP driver to update the Flash program

SerialPutString("=============================================================== =======================");

SerialPutString("= (C) COPYRIGHT 2011 Lierda =");

SerialPutString("= =");

SerialPutString("= In-Application Programming Application (Version 1.0.0) =");

SerialPutString("= =");

SerialPutString("= By wuguoyan =");

SerialPutString("=============================================================== =======================");

SerialPutString("");

Main_Menu();

}

// Otherwise execute the user program

else

{

// Determine whether the user program has been downloaded, because this address is the stack address under normal circumstances

// If there is no such sentence, even if there is no download program will enter and lead to run away.

if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000) == 0x20000000)

{

SerialPutString("Execute user Program");

// Jump to the user code

JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);

Jump_To_Application = (pFunction) JumpAddress;

// Initialize the stack pointer of the user program

__set_MSP(*(__IO uint32_t*) ApplicationAddress);

Jump_To_Application();

}

else

{

SerialPutString("no user Program");

}

}

Here are a few classic and very important pieces of code:

First sentence: if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000) == 0x20000000) // Determine whether the stack address value is between 0x20000000 - 0x20002000.

How to understand? (1) In the program, define ApplicationAddress 0x8003000, *(__IO uint32_t*)ApplicationAddress) takes the value of 0x8003000 to 0x8003003, because the setting in our application APP puts the interrupt vector table at 0x08003000 position; the first one in the interrupt vector table is the value of the top address of the stack.

In other words, this sentence judges whether the application has been downloaded by judging whether the stack top address value is correct (whether it is between 0x20000000 - 0x20002000), because the application startup file is initialized at the beginning of the startup file. If the top value of the stack is correct, the initialization of the startup file that the application has downloaded has also been executed;

The second sentence: JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); [command line of common.c file defines: pFunction Jump_To_Application;]

ApplicationAddress + 4 is 0x08003004, which puts the second "reset address" of the interrupt vector table. JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4); After this, JumpAddress

The third sentence: Jump_To_Application = (pFunction) JumpAddress; startup_stm32f10x_md_lv. The alias in the file is defined as void (*pFunction)(void); This looks a bit strange; the normal first integer variable typedef int a; is to define an alias for the integer a.

Void (*pFunction)(void); is to declare a function pointer. After adding a typedef, pFunction is just an alias of type void (*)(void); for example:

[cpp]

pFunction a1, a2, a3;

void fun(void)

{

......

}

a1 = fun;

So, Jump_To_Application = (pFunction) JumpAddress; At this point Jump_To_Application points to the address where the reset function is located;

Fourth and fifth sentences: __set_MSP(*(__IO uint32_t*) ApplicationAddress); \\Set main function stack pointer Jump_To_Application(); \\Execute reset function

Let's take a look at the startup file startup_stm32f10x_md_vl. The startup code in s is easier to understand

The ported IAP code is in my resource (if it is a stm32f100cb chip can be used directly): http://download.csdn.net/detail/yx_l128125/6475219

Third, let's take a brief look at the startup code in the startup file. It is more conducive to our understanding of IAP: (The following article is very good, there are wood!)

The following is from: http://blog.sina.com.cn/s/blog_69bcf45201019djx.html

Analyze the startup process of STM32

Analyze the startup process of STM32

The current embedded application development process, and C language has become the best choice for most occasions. As a result, the main function seems to be the starting point of course - because C programs often start from the main function. But one problem that is often overlooked is: How does the microcontroller (microcontroller) find and execute the main function after power-on? Obviously, the microcontroller cannot locate the entry address of the main function from the hardware. Because the C language is used as the development language, the address of the variable/function is allocated by the compiler at compile time, so that the entry address of the main function is microcontroller's internal storage space is no longer absolutely constant. I believe that readers can answer this question. The answer may be similar, but there must be a keyword called "boot file", which is described as "bootloader" in English words.

Regardless of high performance, simple structure, and high price, each type of microcontroller (processor) must have a startup file. The function of the startup file is to execute the microcontroller from "reset" to "start executing main function". The work that must be done during this period of time (called the startup process). The most common 51, AVR or MSP430 microcontrollers also have corresponding startup files, but the development environment often provides this startup file automatically and completely, without the need for developers to intervene in the startup process, only need to start the application from the main function. This design is all right.

The topic goes to the STM32 microcontroller. Whether it is Keil uVision4 or IAR EWARM development environment, ST provides ready-to-use boot files that can be directly used. Program developers can directly import C files and directly develop C applications. This can greatly reduce the developer's jump from other microcontroller platforms to the STM32 platform, and also reduces the difficulty of adapting to the STM32 microcontroller. (For the previous generation ARM's masterpiece, the startup file is often the first hard but it is difficult. Unsurpassable hurdles).

Compared with ARM's previous generation mainstream ARM7/ARM9 core architecture, the startup mode of the new generation Cortex-M3 core architecture has undergone considerable changes. After the ARM7/ARM9 core controller is reset, the CPU will start by taking the first instruction to execute the reset interrupt service routine from the absolute address 0x000000 of the memory space, that is, the start address after the reset is fixed is 0x000000 (PC = 0x000000). At the same time, the position of the interrupt vector table is not fixed. The Cortex-M3 core is just the opposite. There are 3 cases: 1. By setting pin boot may be located in the SRAM interrupt vector area, i.e., the starting address 0x2000000, while the pointer is reset at PC 0x2000000; 2, By setting pin boot may be located in the FLASH interrupt vector area, i.e., the starting address 0x8000000, while the pointer is reset at PC 0x8000000; 3, The interrupt vector table can be located in the built-in bootloader area by the boot pin setting. This article does not discuss this situation. The Cortex-M3 core specifies that the start address must store the top pointer and the second address must store the reset interrupt. The entry vector address, so that after the Cortex-M3 core is reset, the reset interrupt entry vector is automatically fetched from the next 32-bit space of the start address, and the jump performs the reset interrupt service routine. Compared to the ARM7/ARM9 core, the Cortex-M3 core fixes the location of the interrupt vector table and the starting address is changeable. After the above preparation is just the following, the startup file "stm32f10x_vector.s" provided by STM32's 2.02 firmware library is used as a template to make a brief and comprehensive analysis of the startup process of STM32.

Listing One: Files "stm32f10x_vector.s", which is a comment line number

DATA_IN_ExtSRAM EQU 0; 1Stack_Size EQU 0x00000400;

2AREA STACK, NOINIT, READWRITE, ALIGN = 3; 3Stack_Mem SPACE Stack_Size; 4__initial_sp; 5Heap_Size EQU 0x00000400; 6AREA HEAP, NOINIT, READWRITE, ALIGN = 3; 7__heap_base; 8Heap_Mem SPACE Heap_Size; 9__heap_limit; 10THUMB; 11PRESERVE8; 12IMPORT NMIException; 13IMPORT HardFaultException; 14IMPORT MemManageException; 15IMPORT BusFaultException; 16IMPORT UsageFaultException; 17IMPORT SVCHandler; 18IMPORT DebugMonitor; 19IMPORT PendSVC; 20IMPORT SysTickHandler; 21IMPORT WWDG_IRQHandler; 22IMPORT PVD_IRQHandler; 23IMPORT TAMPER_IRQHandler; 24IMPORT RTC_IRQHandler;

25IMPORT FLASH_IRQHandler; 26IMPORT RCC_IRQHandler; 27IMPORT EXTI0_IRQHandler; 28IMPORT EXTI1_IRQHandler; 29IMPORT EXTI2_IRQHandler; 30IMPORT EXTI3_IRQHandler; 31IMPORT EXTI4_IRQHandler; 32IMPORT DMA1_Channel1_IRQHandler; 33IMPORT DMA1_Channel2_IRQHandler; 34IMPORT DMA1_Channel3_IRQHandler; 35IMPORT DMA1_Channel4_IRQHandler; 36IMPORT DMA1_Channel5_IRQHandler; 37IMPORT DMA1_Channel6_IRQHandler; 38IMPORT DMA1_Channel7_IRQHandler; 39IMPORT ADC1_2_IRQHandler; 40IMPORT USB_HP_CAN_TX_IRQHandler; 41IMPORT USB_LP_CAN_RX0_IRQHandler; 42IMPORT CAN_RX1_IRQHandler; 43IMPORT CAN_SCE_IRQHandler; 44IMPORT EXTI9_5_IRQHandler; 45IMPORT TIM1_BRK_IRQHandler; 46IMPORT TIM1_UP_IRQHandler; 47IMPORT TIM1_TRG_COM_IRQHandler; 48IMPORT TIM1_CC_IRQHandler; 49IMPORT TIM2_IRQHandler; 50IMPORT TIM3_IRQHandler; 51IMPORT TIM4_IRQHandler; 52IMPORT I2C1_EV_IRQHandler; 53IMPORT I2C1_ER_IRQHandler; 54IMPORT I2C2_EV_IRQHandler; 55IMPORT I2C2_ER_IRQHandler; 56IMPORT SPI1_IRQHandler; 57IMPORT SPI2_IRQHandler; 58IMPORT USART1_IRQHandler; 59IMPORT USART2_IRQHandler; 60IMPORT USART3_IRQHandler; 61IMPORT EXTI15_10_IRQHandler; 62IMPORT RTCAlarm_IRQHandler; 63IMPORT USBWakeUp_IRQHandler; 64IMPORT TIM8_BRK_IRQHandler; 65IMPORT TIM8_UP_IRQHandler; 66IMPORT TIM8_TRG_COM_IRQHandler; 67IMPORT TIM8_CC_IRQHandler; 68IMPORT ADC3_IRQHandler; 69IMPORT FSMC_IRQHandler; 70IMPORT SDIO_IRQHandler; 71IMPORT TIM5_IRQHandler; 72IMPORT SPI3_IRQHandler; 73IMPORT UART4_IRQHandler; 74IMPORT UART5_IRQHandler; 75IMPORT TIM6_IRQHandler; 76IMPORT TIM7_IRQHandler; 77IMPORT DMA2_Channel1_IRQHandler; 78IMPORT DMA2_Channel2_IRQHandler; 79IMPORT DMA2_Channel3_IRQHandler; 80IMPORT DMA2_Channel4_5_IRQHandler; 81AREA RESET, DATA, READONLY; 82EXPORT __Vectors; 83__Vectors; 84DCD __initial_sp; 85DCD Reset_Handler; 86DCD NMIException; 87DCD HardFaultException; 88DCD MemManageException; 89DCD BusFaultException; 90DCD UsageFaultException; 91DCD 0; 92DCD 0; 93DCD 0; 94DCD 0; 95DCD SVCHandler; 96DCD DebugMonitor; 97DCD 0; 98DCD PendSVC; 99DCD SysTickHandler; 100DCD WWDG_IRQHandler; 101DCD PVD_IRQHandler; 102DCD TAMPER_IRQHandler; 103DCD RTC_IRQHandler; 104DCD FLASH_IRQHandler; 105DCD RCC_IRQHandler; 106DCD EXTI0_IRQHandler; 107DCD EXTI1_IRQHandler; 108DCD EXTI2_IRQHandler; 109DCD EXTI3_IRQHandler; 110DCD EXTI4_IRQHandler; 111DCD DMA1_Channel1_IRQHandler; 112DCD DMA1_Channel2_IRQHandler; 113DCD DMA1_Channel3_IRQHandler; 114DCD DMA1_Channel4_IRQHandler; 115DCD DMA1_Channel5_IRQHandler; 116DCD DMA1_Channel6_IRQHandler; 117DCD DMA1_Channel7_IRQHandler; 118DCD ADC1_2_IRQHandler; 119DCD USB_HP_CAN_TX_IRQHandler; 120DCD USB_LP_CAN_RX0_IRQHandler; 121DCD CAN_RX1_IRQHandler; 122DCD CAN_SCE_IRQHandler; 123DCD EXTI9_5_IRQHandler; 124DCD TIM1_BRK_IRQHandler; 125DCD TIM1_UP_IRQHandler; 126DCD TIM1_TRG_COM_IRQHandler; 127DCD TIM1_CC_IRQHandler; 128DCD TIM2_IRQHandler; 129DCD TIM3_IRQHandler; 130DCD TIM4_IRQHandler; 131DCD I2C1_EV_IRQHandler; 132DCD I2C1_ER_IRQHandler; 133DCD I2C2_EV_IRQHandler; 134DCD I2C2_ER_IRQHandler; 135DCD SPI1_IRQHandler; 136DCD SPI2_IRQHandler; 137DCD USART1_IRQHandler; 138DCD USART2_IRQHandler; 139DCD USART3_IRQHandler; 140DCD EXTI15_10_IRQHandler; 141DCD RTCAlarm_IRQHandler; 142DCD USBWakeUp_IRQHandler; 143DCD TIM8_BRK_IRQHandler; 144DCD TIM8_UP_IRQHandler; 145DCD TIM8_TRG_COM_IRQHandler; 146DCD TIM8_CC_IRQHandler; 147DCD ADC3_IRQHandler; 148DCD FSMC_IRQHandler; 149DCD SDIO_IRQHandler; 150DCD TIM5_IRQHandler; 151DCD SPI3_IRQHandler; 152DCD UART4_IRQHandler; 153DCD UART5_IRQHandler; 154DCD TIM6_IRQHandler; 155DCD TIM7_IRQHandler; 156DCD DMA2_Channel1_IRQHandler; 157DCD DMA2_Channel2_IRQHandler; 158DCD DMA2_Channel3_IRQHandler; 159DCD DMA2_Channel4_5_IRQHandler; 160AREA | .text |, CODE, READONLY; 161Reset_Handler PROC; 162EXPORT Reset_Handler; 163IF DATA_IN_ExtSRAM == 1; 164LDR R0,= 0x00000114; 165LDR R1,= 0x40021014; 166STR R0, [R1]; 167LDR R0, = 0x000001E0; 168LDR R1, = 0x40021018; 169STR R0, [R1]; 170LDR R0, = 0x44BB44BB; 171LDR R1, = 0x40011400; 172STR R0, [R1]; 173LDR R0, = 0xBBBBBBBB; 174LDR R1, = 0x40011404; 175STR R0, [R1]; 176LDR R0, = 0xB44444BB; 177LDR R1, = 0x40011800; 178STR R0, [R1]; 179LDR R0, = 0xBBBBBBBB; 180LDR R1, = 0x40011804; 181STR R0, [R1]; 182LDR R0, = 0x44BBBBBB; 183LDR R1, = 0x40011C00; 184STR R0, [R1]; 185LDR R0, = 0xBBBB4444; 186LDR R1, = 0x40011C04; 187STR R0, [R1]; 188LDR R0, = 0x44BBBBBB; 189LDR R1, = 0x40012000; 190STR R0, [R1]; 191LDR R0, = 0x44444B44; 192LDR R1, = 0x40012004; 193STR R0, [R1]; 194LDR R0, = 0x00001011; 195LDR R1, = 0xA0000010; 196STR R0, [R1]; 197LDR R0, = 0x00000200; 198LDR R1, = 0xA0000014; 199STR R0, [R1]; 200ENDIF; 201IMPORT __main; 202LDR R0, = __main; 203BX R0; 204ENDP; 205ALIGN; 206IF: DEF: __mICROLIB; 207EXPORT __initial_sp; 208EXPORT __heap_base; 209EXPORT __heap_limit; 210ELSE; 211IMPORT __use_two_region_memory; 212EXPORT __user_initial_stackheap; 213__user_initial_stackheap; 214LDR R0, = Heap_Mem; 215LDR R1, = (Stack_Mem + Stack_Size); 216LDR R2, = (Heap_Mem + Heap_Size); 217LDR R3, = Stack_Mem; 218BX LR; 219ALIGN; 220ENDIF; 221END; 222ENDIF; 223END; 224;

As shown in Listing 1, the STM32 startup code is a total of 224 lines, written in assembly language, the main reason of which will be explained below. Now analyze from the first line:

• Line 1: Define whether to use external SRAM, use 1 for 1 and 0 for use. If the language is expressed in C, it is equivalent to: #define DATA_IN_ExtSRAM 0

• Line 2: Define the stack space size to be 0x00000400 bytes, which is 1Kbyte. This line is also equivalent to: #define Stack_Size 0x00000400

• Line 3: directive AREA, represents

• Line 4: Open up a memory space of size Stack_Size as a stack.

• Line 5: The label __initial_sp indicates the top address of the stack space.

• Line 6: Define the heap size to be 0x00000400 bytes, also 1Kbyte.

• Line 7: The pseudo-instruction AREA indicates

• Line 8: Label __heap_base, indicating the start address of the heap space.

• Line 9: Open up a memory space of size Heap_Size as a heap.

• Line 10: Label __heap_limit for the end of the heap space.

• Line 11: Tell the compiler to use the THUMB instruction set.

• Line 12: Tell the compiler to align with 8 bytes.

• Lines 13-81: The IMPORT instruction indicates that subsequent symbols are defined in an external file (similar to global variable declarations in C), which may be used below.

• Line 82: read-only data segment defined, actually CODE region

Fiber Optic Adapter / Fiber Optic Coupler

Fiber To Ethernet Converter,Optical To Ethernet Converter,Optical Fiber To Ethernet Converter,Fiber Optic To Ethernet Converter Price

Ningbo Fengwei Communication Technology Co., Ltd , https://www.fengweicommunication.com

This entry was posted in on