RT-Thread&ART-PIBSP制作过程
Posted Rb菌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RT-Thread&ART-PIBSP制作过程相关的知识,希望对你有一定的参考价值。
ART-Pi 除了配备一颗 W25Q64JV 用于存放程序外,同时配备了另一颗 W25Q128JV 用于存放 WIFI 固件,蓝牙固件,等其它数据.官方建议这颗 W25Q128JV 的空间划分如下:
分区名 | 起始地址 | 分区大小 | 用途说明 |
---|---|---|---|
wifi_image | 0 | 512KB | 保存 wifi 固件 |
bt_image | 512 * 1024 | 512KB | 保存 bt 固件 |
download | 1 * 1024 * 1024 | 2048KB | 固件下载分区 |
easyflash | 3 * 1024 * 1024 | 1024KB | easyflash 参数保存区 |
filesystem | 4 * 1024 * 1024 | 12MB | 文件系统分区 |
一、修改MDK中链接脚本
因为ART-PI的程序是运行在片外flash中的,原本的BSP中的连接脚本是运行在片内flash中,这样会覆盖本身的bootloader,所以我们需要修改其程序运行地址。
点击mdk中的魔术棒,选择Linker,点击Edit进入该脚本编辑模式
LR_IROM1 0x90000000 0x00800000 ; load region size_region
ER_IROM1 0x90000000 0x00800000 ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
RW_IRAM1 0x24000000 0x00080000 ; AXI SRAM 512K
.ANY (+RW +ZI)
其中load region size_region为装载区域。
LR_IROM1, 名字,可以理解为一块存储器的名字。
0x90000000:起始地址。
0x00800000:代表size,(download+easyflash+filesystem=8M)也就是存储器的最大空间。
RW_IRAM1:RW data,初始化了的可读写变量的大小。
二、添加时钟配置
打开board.c,添加以下内容
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
RCC_OscInitTypeDef RCC_OscInitStruct = 0;
RCC_ClkInitTypeDef RCC_ClkInitStruct = 0;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = 0;
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY))
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 5;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
Error_Handler();
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
Error_Handler();
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC|RCC_PERIPHCLK_USART3
|RCC_PERIPHCLK_UART4|RCC_PERIPHCLK_SPI4
|RCC_PERIPHCLK_SPI1|RCC_PERIPHCLK_SDMMC
|RCC_PERIPHCLK_ADC|RCC_PERIPHCLK_USB
|RCC_PERIPHCLK_LPTIM1|RCC_PERIPHCLK_FMC;
PeriphClkInitStruct.PLL2.PLL2M = 2;
PeriphClkInitStruct.PLL2.PLL2N = 64;
PeriphClkInitStruct.PLL2.PLL2P = 2;
PeriphClkInitStruct.PLL2.PLL2Q = 2;
PeriphClkInitStruct.PLL2.PLL2R = 4;
PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_3;
PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
PeriphClkInitStruct.PLL3.PLL3M = 5;
PeriphClkInitStruct.PLL3.PLL3N = 160;
PeriphClkInitStruct.PLL3.PLL3P = 8;
PeriphClkInitStruct.PLL3.PLL3Q = 8;
PeriphClkInitStruct.PLL3.PLL3R = 24;
PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
PeriphClkInitStruct.FmcClockSelection = RCC_FMCCLKSOURCE_PLL2;
PeriphClkInitStruct.SdmmcClockSelection = RCC_SDMMCCLKSOURCE_PLL2;
PeriphClkInitStruct.Spi123ClockSelection = RCC_SPI123CLKSOURCE_PLL2;
PeriphClkInitStruct.Spi45ClockSelection = RCC_SPI45CLKSOURCE_PLL3;
PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
PeriphClkInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
Error_Handler();
/** Enable USB Voltage detector
*/
HAL_PWREx_EnableUSBVoltageDetector();
以上主要是对系统的时钟进行初始化配置。
三、修改board.h中的配置选项
之前board.h中的配置如下:
#define STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)
#define STM32_FLASH_SIZE (128 * 1024)
#define STM32_FLASH_END_ADDRESS ((uint32_t)(STM32_FLASH_START_ADRESS + STM32_FLASH_SIZE))
#define STM32_SRAM_SIZE (128)
#define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024)
因为ATP-PI的外扩QSPI FLASH的开始地址为0x90000000,外扩的SPI FLASH的总大小为16M,之前的配置明显是不正确的,故我们修改如下:
/*-------------------------- CHIP CONFIG BEGIN --------------------------*/
#define CHIP_FAMILY_STM32
#define CHIP_SERIES_STM32H7
#define CHIP_NAME_STM32H750XBHX
/*-------------------------- CHIP CONFIG END --------------------------*/
/*-------------------------- ROM/RAM CONFIG BEGIN --------------------------*/
#define ROM_START ((uint32_t)0x90000000)
#define ROM_SIZE (16384)
#define ROM_END ((uint32_t)(ROM_START + ROM_SIZE * 1024))
#define RAM_START (0x24000000)
#define RAM_SIZE (512)
#define RAM_END (RAM_START + RAM_SIZE * 1024)
/*-------------------------- ROM/RAM CONFIG END --------------------------*/
/*-------------------------- CLOCK CONFIG BEGIN --------------------------*/
#define BSP_CLOCK_SOURCE ("HSE")
#define BSP_CLOCK_SOURCE_FREQ_MHZ ((int32_t)0)
#define BSP_CLOCK_SYSTEM_FREQ_MHZ ((int32_t)480)
/*-------------------------- CLOCK CONFIG END --------------------------*/
/*-------------------------- UART CONFIG BEGIN --------------------------*/
/** After configuring corresponding UART or UART DMA, you can use it.
*
* STEP 1, define macro define related to the serial port opening based on the serial port number
* such as #define BSP_USING_UATR1
*
* STEP 2, according to the corresponding pin of serial port, define the related serial port information macro
* such as #define BSP_UART1_TX_PIN "PA9"
* #define BSP_UART1_RX_PIN "PA10"
*
* STEP 3, if you want using SERIAL DMA, you must open it in the RT-Thread Settings.
* RT-Thread Setting -> Components -> Device Drivers -> Serial Device Drivers -> Enable Serial DMA Mode
*
* STEP 4, according to serial port number to define serial port tx/rx DMA function in the board.h file
* such as #define BSP_UART1_RX_USING_DMA
*
*/
#ifdef BSP_USING_UART1
#define BSP_UART1_TX_PIN "PA9"
#define BSP_UART1_RX_PIN "PA10"
#endif
#ifdef BSP_USING_UART4
#define BSP_UART4_TX_PIN "PA0"
#define BSP_UART4_RX_PIN "PI9"
#endif
#ifdef BSP_USING_UART6
#define BSP_UART6_TX_PIN "PC6"
#define BSP_UART6_RX_PIN "PC7"
#endif
#define STM32_FLASH_START_ADRESS ROM_START
#define STM32_FLASH_SIZE ROM_SIZE
#define STM32_FLASH_END_ADDRESS ROM_END
#define RAM_START (0x24000000)
#define RAM_SIZE (512)
#define RAM_END (RAM_START + RAM_SIZE * 1024)
#define STM32_SRAM1_SIZE RAM_SIZE
#define STM32_SRAM1_START RAM_START
#define STM32_SRAM1_END RAM_END
四、在main.c中添加QSPI地址映射
VTOR寄存器存放的是中断向量表的起始地址。所以我们可以在main函数添加如下代码实现中断向量表的起始地址的重设:
对于这个0x90000000地址怎么来的,打开参考手册,可以看到QSPI的起始地址为0x90000000。
添加如下代码,使得设备初始化时进行中断向量表的起始地址的重设。
通过片外的QSPI存储我们的程序,片内的flash是用于存储bootloader,从而STM32_FLASH_START_ADRESS ((uint32_t)0x08000000)的地址则是用于bootloader来跳转到0x90000000地址来运行我们用户的APP代码。
#include "stm32h7xx.h"
static int vtor_config(void)
/* Vector Table Relocation in Internal QSPI_FLASH */
SCB->VTOR = QSPI_BASE;
return 0;
INIT_BOARD_EXPORT(vtor_config);
五、配置MDK中的下载选项
打开mdk中的魔术棒,点击Debug选项
ART-Pi_W25Q64.FLM下载算法在 "sdk-bsp-stm32h750-realthread-artpi\\debug\\flm\\ART-Pi_W25Q64.FLM"这个目录下,把ART-Pi_W25Q64.FLM拷贝替换到MDK安装目录Keil_v5\\ARM\\Flash下,RAM for Algorithm 需要调整成 0x4000。STM32H750 执行片外 QSPI FLASH 上的程序需要有一个 bootloader 来跳转过去,出厂前已经默认烧录了 bootloader,可以运行,如果不小心擦除了,可以重新烧录 bootloader。
至此一个ART-PI的MDK BSP模板工程就做好了,接下来将使用该模板工程进行外设的配置与验证
以上是关于RT-Thread&ART-PIBSP制作过程的主要内容,如果未能解决你的问题,请参考以下文章
RT-Thread&BearPi 开发笔记 -- 为小熊派开发板制作 RT-Thread BSP 包
国产MCU移植手把手教你使用RT-Thread制作GD32F103系列BSP
国产MCU移植手把手教你使用RT-Thread制作GD32系列BSP