网站首页 安卓软件下载 安卓游戏下载 电脑软件下载 mac软件下载 翻译软件 电影下载 电视剧下载 教程攻略
| 软件 | FreeRTOS stm32 完整移植包 | 
| 分类 | 电脑软件-开发工具-网站源码 | 
| 语言 | 简体中文 | 
| 大小 | 8.41 MB | 
| 版本 | 免费软件 | 
| 下载 |  | 
| 介绍 | FreeRTOS stm32 完整移植包软件特性
                            介绍freertos在stm32上的移植说明,每一步都很详细,让你学会在stm32+freeRTOS的平台上开发应用程序一、各文件关键部分的实现:1、PORTMACRO.H 宏定义部分 1)定义编译器相关的各种数据类型 define portCHAR char define portFLOAT float define portDOUBLE double define portLONG long define portSHORT short define portSTACK_TYPE unsigned portLONG define portBASE_TYPE long 2)架构相关的定义 Cortex-M3的堆栈增长方向为高地址向低地址增长 define portSTACK_GROWTH ( -1 ) 每毫秒的心跳次数 define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) 访问SRAM的字节对齐 define portBYTE_ALIGNMENT 8 3)定义用户主动引起内核调度的2个函数 强制上下文切换,用在任务环境中调用 define portYIELD() vPortYieldFromISR() 强制上下文切换,用在中断处理环境中调用 define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYieldFromISR() 4)定义临界区的管理函数 中断允许和关闭 define portDISABLE_INTERRUPTS() vPortSetInterruptMask() define portENABLE_INTERRUPTS() vPortClearInterruptMask() 临界区进入和退出 define portENTER_CRITICAL() vPortEnterCritical() define portEXIT_CRITICAL() vPortExitCritical() 用于在中断环境的中断允许和关闭 define portSET_INTERRUPT_MASK_FROM_ISR() 0;vPortSetInterruptMask() define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask();(void)x 2、PORT.C C接口部分 1)堆栈初始化 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ) {  *pxTopOfStack = portINITIAL_XPSR; /* 程序状态寄存器 */  pxTopOfStack--;  *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* 任务的入口点 */  pxTopOfStack--;  *pxTopOfStack = 0; /* LR */  pxTopOfStack -= 5; /* R12, R3, R2 and R1. */  *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* 任务的参数 */  pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ return pxTopOfStack; } 2)启动任务调度 portBASE_TYPE xPortStartScheduler( void ) {  让任务切换中断和心跳中断位于最低的优先级,使更高优先级可以抢占mcu  *(portNVIC_SYSPRI2) |= portNVIC_PENDSV_PRI;  *(portNVIC_SYSPRI2) |= portNVIC_SYSTICK_PRI;  设置并启动系统的心跳时钟  prvSetupTimerInterrupt();  初始化临界区的嵌套的个数  uxCriticalNesting = 0;  启动第一个任务  vPortStartFirstTask();  执行到vPortStartFirstTask函数,内核已经开始正常的调度  return 0; } 3)主动释放mcu使用权 void vPortYieldFromISR( void ) {  触发PendSV系统服务中断,中断到来时由汇编函数xPortPendSVHandler()处理  *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET; } 进入临界区时,首先关闭中断;当退出所以嵌套的临界区后再使能中断 void vPortEnterCritical( void ) {  portDISABLE_INTERRUPTS();  uxCriticalNesting++; } void vPortExitCritical( void ) {  uxCriticalNesting--; if( uxCriticalNesting == 0 )  {  portENABLE_INTERRUPTS();  } } 4)心跳时钟处理函数 void xPortSysTickHandler( void ) { unsigned portLONG ulDummy;  如果是抢占式调度,首先看一下有没有需要调度的任务  if configUSE_PREEMPTION == 1  *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET;  endif  ulDummy = portSET_INTERRUPT_MASK_FROM_ISR();  { 通过task.c的心跳处理函数vTaskIncrementTick(),进行时钟计数和延时任务的处理  vTaskIncrementTick();  }  portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } 3、PORTASM.S 汇编处理部分 1)请求切换任务 xPortPendSVHandler:  保存当前任务的上下文到其任务控制块  mrs r0, psp  ldr r3, =pxCurrentTCB 获取当前任务的任务控制块指针  ldr r2, [r3]  stmdb r0!, {r4-r11} 保存R4-R11到该任务的堆栈  str r0, [r2] 将最后的堆栈指针保存到任务控制块的pxTopOfStack  stmdb sp!, {r3, r14} 关闭中断  mov r0, configMAX_SYSCALL_INTERRUPT_PRIORITY  msr basepri, r0 切换任务的上下文,pxCurrentTCB已指向新的任务 bl vTaskSwitchContext  mov r0, 0  msr basepri, r0  ldmia sp!, {r3, r14}  恢复新任务的上下文到各寄存器  ldr r1, [r3]  ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */  ldmia r0!, {r4-r11} /* Pop the registers. */  msr psp, r0  bx r14 2.)中断允许和关闭的实现,通过BASEPRI屏蔽相应优先级的中断源 vPortSetInterruptMask:  push { r0 }  mov R0, configMAX_SYSCALL_INTERRUPT_PRIORITY  msr BASEPRI, R0  pop { R0 }  bx r14 vPortClearInterruptMask:  PUSH { r0 }  MOV R0, 0  MSR BASEPRI, R0  POP { R0 }  bx r14 3)直接切换任务,用于vPortStartFirstTask第一次启动任务时初始化堆栈和各寄存器 vPortSVCHandler;  ldr r3, =pxCurrentTCB  ldr r1, [r3]  ldr r0, [r1]  ldmia r0!, {r4-r11}  msr psp, r0  mov r0, 0  msr basepri, r0  orr r14, r14, 13  bx r14 4)启动第一个任务的汇编实现 vPortStartFirstTask  通过中断向量表的定位堆栈的地址  ldr r0, =0xE000ED08 向量表偏移量寄存器 (VTOR)  ldr r0, [r0]  ldr r0, [r0]  msr msp, r0 将堆栈地址保存到主堆栈指针msp中  触发SVC软中断,由vPortSVCHandler()完成第一个任务的具体切换工作  svc 0 FreeRTOS内核调度器启动的流程如下: 以上3个文件实现了FreeRTOS内核调度所需的底层接口,相关代码十分精简。 二、创建测试任务:下面创建第一个测试任务,LED测试 int main( void ) {  设置系统时钟,中断向量表和LED使用的GPIO  使用stm32的固件包提供的初始化函数,具体说明见相关手册  prvSetupHardware();  通过xTaskCreate()创建4个LED任务vLEDFlashTask(), 每个任务根据各自的频率闪烁,分别对应开发板上的4个LED  vStartLEDFlashTasks( mainFLASH_TASK_PRIORITY ); ? 创建一个IDLE任务后,通过xPortStartScheduler启动调度器  vTaskStartScheduler();  调度器工作不正常时返回  return 0; } portTASK_FUNCTION()是FreeRTOS定义的函数声明,没特殊作用 static portTASK_FUNCTION( vLEDFlashTask, pvParameters ) { ……省略……,具体为计算各LED的闪烁频率  for(;;)  {  vTaskDelayUntil( &xLastFlashTime, xFlashRate );  vParTestToggleLED( uxLED );  vTaskDelayUntil()的延时时间xFlashRate,是从上一次的延时时间xLastFlashTime算起的,  相对vTaskDelay()的直接延时更为精准。  vTaskDelayUntil( &xLastFlashTime, xFlashRate );  vParTestToggleLED( uxLED );  } } FreeRTOS的任务创建与UC/OSII差异不大,主要参数为任务函数,堆栈大小和任务的优先级。如: xTaskCreate( vLEDFlashTask, ( signed portCHAR * ) "LEDx", ledSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); 下面再创建一个LCD显示任务,以最低优先级运行: xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); void vLCDTask( void *pvParameters ) {  ……省略……  for( ;; )  {  vTaskDelay(1000);  printf("%c ", usDisplayChar);  } } 该任务很简单,每隔1000个ticks(就是1000ms),从LCD上刷新一个数字。 至此,FreeRTOS在STM32上的移植基本完成。与UC/OSII相比,FreeRTOS精简的实现更适合用来学习实时操作系统的工作原理,对其进行剖析也相对容易。 接下来,我们将会移植CAN,RS485,SD卡和USB等接口到FreeRTOS,使其在STM32平台上更加完善。                         | 
| 截图 | |
| 随便看 | 
 | 
电脑软件下载频道提供pc端必备的网络软件、杀毒软件、聊天工具、媒体播放等各类电脑软件的下载,找免费的安全的绿色的电脑软件就来天天下载平台!