金牌会员
- 积分
- 2095
- 金钱
- 2095
- 注册时间
- 2017-2-11
- 在线时间
- 306 小时
|
楼主 |
发表于 2020-12-2 16:45:19
|
显示全部楼层
本帖最后由 jiangyy 于 2020-12-9 10:06 编辑
废了九牛二虎之力(花了两天时间研究IAP),终于搞定了IDE软件如何IAP跳转。具体细节如下:
一、准备bootloader程序
因为STM32CUBEIDE软件生成的hex文件比较大,所以要给足够大的空间给bootloader(具体要看你生成的bin文件大小),我自己没加什么东西,就有32kb了,在这里我只是简单的做个演示,所以我给了它48kb。
下面几个步骤很关键,如下:
1.修改内部flash链接文件(STM32F407ZGTX_FLASH.ld)
- /* Memories definition */
- MEMORY
- {
- CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
- RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
- FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 48K
- }
复制代码 2.编写一个IAP跳转函数 你可以自己建立一个文件,也可以在main.c文件编写这个函数。
- #define ApplicationAddress 0x800C000 //应用程序起始地址(存放在FLASH)
- typedef void ( * pFunction ) ( void ); //定义一个函数类型的参数.
- void iap_load_app(uint32_t appAddr);
- //ulAddr_App:用户代码起始地址.
- void iap_load_app(uint32_t appAddr)
- {
- pFunction jump2app;
- printf("first word : 0x%x\r\n",(*(uint32_t*)appAddr));
- if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20020000)
- {
- printf("IAP load APP!\r\n");
- HAL_RCC_DeInit();
- jump2app = (void (*)())*(__IO uint32_t*) (appAddr + 4);
- __set_MSP(*(__IO uint32_t*) appAddr);
- jump2app();
- }
- }
复制代码
特别注意,HAL_RCC_DeInit();这个一定要加上,否则无法跳转!!!!这个坑我挖了好长时间终于找到是这个地方缺少了导致无法跳转,我也不清楚为啥一定要初始化复位RCC寄存器。还有一个坑是地址校验,不知道有没有小伙伴注意到,就是if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20020000)。红色的地方要修改,否则无法跳转!!!别问我为什么,你用STM32CubeProgrammer读取芯片flash的内容就知道首地址的值是多少就知道了,下面是我一个截图:
3.main函数添加IAP跳转函数
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- /* 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 */
- MX_GPIO_Init();
- MX_RTC_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- HAL_GPIO_TogglePin(GPIOF,LED0_Pin);
- HAL_Delay(500);
- iap_load_app(ApplicationAddress);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
复制代码
此工作完成了一个简单的bootloader程序,下面就是要做一个APP程序了。
二、准备APP程序
1.修改内部flash链接文件(STM32F407ZGTX_FLASH.ld)
- MEMORY
- {
- CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
- RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
- FLASH (rx) : ORIGIN = 0x800C000, LENGTH = 976K
- }
复制代码
在这里有人有点小疑问,为啥ORIGIN = 0x800C000?因为bootloader分配了0xC000字节大小,也就是48kb;起先默认FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K,所以在这里就应该修改ORIGIN = 0x800C000,LENGTH = 1024K-48K = 976K,不懂可以看一下芯片手册。
2.修改中断偏移量地址
这个很关键,不然APP是无法启动的。具体修改的地方是在文件夹Core - > Src文件夹 -> system_stm32f4xx.c文件,其中有个宏定义 VECT_TAB_OFFSET,这个值默认是 0x00,修改为:
- /*!< Uncomment the following line if you need to relocate your vector Table in
- Internal SRAM. */
- /* #define VECT_TAB_SRAM */
- #define VECT_TAB_OFFSET 0xC000 /*!< Vector Table base offset field.
- This value must be a multiple of 0x200. */
复制代码
3.main函数写个简单的应用,如下:
- int main(void)
- {
- /* USER CODE BEGIN 1 */
- uint8_t i = 0;
- /* 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 */
- MX_GPIO_Init();
- MX_RTC_Init();
- MX_USART1_UART_Init();
- /* USER CODE BEGIN 2 */
- __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
- /* USER CODE END 2 */
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- HAL_GPIO_WritePin(GPIOF,BEEP_Pin,GPIO_PIN_SET);
- HAL_Delay(500);
- HAL_GPIO_WritePin(GPIOF,BEEP_Pin,GPIO_PIN_RESET);
- while (1)
- {
- HAL_GPIO_TogglePin(GPIOF,LED1_Pin);
- HAL_Delay(200);
- i++;
- printf("i = %d\r\n",i);
- /* USER CODE END WHILE */
- /* USER CODE BEGIN 3 */
- }
- /* USER CODE END 3 */
- }
复制代码
好了,一切准备就绪,开始准备烧录bootloader。使用STM32CubeProgrammer全片擦除falsh,然后烧录bootloader和APP程序,串口打印显示如下:
可以正常运行了,哎,心累啊!!!不过终于解决了这个问题,希望对使用STM32CubeIDE编程的小伙伴有帮助,也希望点个赞告慰一下我坚持不懈的找BUG。3QY
|
|