CMSIS标准及HAL库学习记录(1)

    工作中总会遇到嵌入式程序的可移植性问题,因为代码量的庞大和编写代码人的不统一性,尤其是遇到开发人员离职的问题。在代码的几年维护和需求变更等等各种修改工作后,代码便变得难以维护。那么如何保持代码的可持续维护性?如何让代码在平台变更,各类不同硬件架构的产品之中游刃有余?ARM为我们提出了一个方案:CMSIS 和HAL库。以下是ARM官网关于CMSIS的架构图,由于理解尚不够深入,而且本人能力有限,不予详细说明。CMSIS标准及HAL库学习记录(1)_第1张图片

本次学习基于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灯的点亮



你可能感兴趣的:(CMSIS标准及HAL库学习记录(1))