工作中总会遇到嵌入式程序的可移植性问题,因为代码量的庞大和编写代码人的不统一性,尤其是遇到开发人员离职的问题。在代码的几年维护和需求变更等等各种修改工作后,代码便变得难以维护。那么如何保持代码的可持续维护性?如何让代码在平台变更,各类不同硬件架构的产品之中游刃有余?ARM为我们提出了一个方案:CMSIS 和HAL库。以下是ARM官网关于CMSIS的架构图,由于理解尚不够深入,而且本人能力有限,不予详细说明。
本次学习基于Keil MDK 5.24a,基于STM32F407VG芯片,使用Software Pack方式和Keil提供的RTX 5源代码进行学习。
首先创建工程,在新工程的Software Pack相关选项中勾上CMSIS项下CORE DSP RTOS(API)中的Keil RTX5 RTOS2(API)中的KEIL RTX5的Source Device中勾选Startup STM32CUBE中的Classic方式 HAL库中勾选需要的驱动
如果使用STM32CUBE软件作为辅助开发,可以更快的上手相关开发,图形和列表化的配置能够把复杂的时钟系统和外设配置的井井有条。但是本次目的以学习为主,不采用软件辅助的方式进行开发。
创建完成后,工程里应有的部分为RTX相关源码,DSP相关LIB库文件,CMSIS相关文件,CM4核心的中断配置启动文件,单片机启动代码,HAL驱动库,和诸多其余配置文件。
首先在源代码组中添加main代码文件模板
- /*----------------------------------------------------------------------------
- * CMSIS-RTOS 'main' function template
- *---------------------------------------------------------------------------*/
-
- #include "RTE_Components.h"
- #include CMSIS_device_header
- #include "cmsis_os2.h"
-
- #ifdef RTE_Compiler_EventRecorder
- #include "EventRecorder.h"
- #endif
-
- /*----------------------------------------------------------------------------
- * Application main thread
- *---------------------------------------------------------------------------*/
- void app_main (void *argument) {
-
- // ...
- for (;;) {}
- }
-
- int main (void) {
- // System Initialization
- #ifdef RTE_Compiler_EventRecorder
- // Initialize and start Event Recorder
- EventRecorderInitialize(EventRecordError, 1U);
- #endif
- // ...
-
- osKernelInitialize(); // Initialize CMSIS-RTOS
- osThreadNew(app_main, NULL, NULL); // Create application main thread
- osKernelStart(); // Start thread execution
- for (;;) {}
- }
其中已经有了很清晰的思路,在main中调用os初始化函数,初始化app_main线程后Start OS首先,需要对手上的开发板编写BSP相关驱动
- void bsp_init(void)
- {
- bsp_CoreClkInit();
- SystemCoreClockUpdate();
- bsp_LedInit();
-
- }
初始化函数思路为,首先初始化核心的CLK和外设总线相关CLK。板上晶振为8M,配置为PLL晶振输入,倍频到144MHz。到144MHz的原因是为了后续使用USB,SDIO相关功能,因为恰好可以三分频提供48MHz的时钟
- static void bsp_CoreClkInit(void)
- {
- uint32_t plln,pllm,pllq,pllp,ppre1,ppre2;
- plln = 144;
- pllp = 1;
- pllm = 8; //Configure PLL Output as 144Mhz
- pllq = 3; //Configure f(USB;OTG FS;SDIO;RNG OUT) as 48Mhz
- ppre1 = 4; //Configure APB1 CLK as 36MHz
- ppre2 = 2; //Configure APB2 CLK as 72MHz
-
- RCC->CR &= 0xFEFFFFFF; //Disable PLL
- RCC->CR |= 0x00010000; //Enable HSE
- while((RCC->CR & 0x00020000) == 0); //Wait for HSE Ready
-
- RCC->PLLCFGR |= 0x00400000; //Configure PLLSRC as HSE
-
- RCC->PLLCFGR &= (0xFFFFFFC0);
- RCC->PLLCFGR |= (pllm << 0); //Configure PLLM
-
- RCC->PLLCFGR &= (0xFFFF803F);
- RCC->PLLCFGR |= (plln << 6); //Configure PLLN
-
- RCC->PLLCFGR &= (0xFFFCFFFF);
- RCC->PLLCFGR |= (pllp << 16); //Configure PLLP
-
- RCC->PLLCFGR &= (0xF0FFFFFF);
- RCC->PLLCFGR |= (pllq << 24); //Configure PLLQ
-
- RCC->CR |= (0x01000000); //Enable PLL
- while((RCC->CR & 0x02000000) == 0); //Wait for PLL Ready
-
- RCC->CFGR &= (0xFFFFE3FF);
- RCC->CFGR |= (ppre1 << 10); //Configure PPRE1
-
- RCC->CFGR &= (0xFFFF1FFF);
- RCC->CFGR |= (ppre2 << 10); //Configure PPRE2
-
- RCC->CFGR |= (0x00000002); //Select PLL as Core CLK Source
- }
之后调用HAL库中的SystemCoreClockUpdate()函数。其目的主要是为了更新SystemCoreClock全局变量,实现软件计算和获取时钟的目的。之后在system_stm32f4xx.c文件中定义HSE_VALUE为对应的值,这里使用8000000即8M
之后在app_main中填入写好的点灯函数,即可成功实现LED灯的点亮
本文介绍使用STM32F407VG芯片结合CMSIS进行嵌入式开发的过程,包括环境搭建、时钟配置、驱动编写等内容,并实现了LED灯的点亮。
2151

被折叠的 条评论
为什么被折叠?



