每年七八月份是智能车大赛的比赛时间,前段时间,学校车队的学弟问我嵌入式系统的问题,于是笔者拿起多年未碰的K60/K64芯片,搭建了一个FreeRTOS+USB的系统框架。文章结尾提供源码。
1.官网下载最新SDK
我们先从nxp官网下载对应芯片的SDK NXP Sign In | Register
笔者下载的版本是2_10_0,解压SDK,拷贝如图文件用于新建工程中。现在的库是nxp提供的fsl库,用这库有什么好处呢?用上这个官方库,今后我们再采用nxp其他芯片(rt系列,lpc等等)也很容易上手(建议别采用寄存器写代码,开发效率会很低下,可移植性也很差)。
2.搭建工程(基于Keil)
查看最新的startup文件,这里的汇编标准(GNU ARM 汇编)正好对应Keil的AC6版本(关于AC6的好处有哪些,可以去搜索了解下,后面很多新出的芯片提供的Demo,基本都是采用的AC6版本。AC5版本逐渐也会被淘汰掉)
ARM 官网有如下一段话:
General update releases on the last branch, version 5.06, ended in H2 2017 with 5.06u6. After this, further support and maintenance will be available through Arm Compiler Long Term Maintenance releases with maintenance continuing until at least summer 2020. Arm Compiler 5.06 for Certification and Arm Compiler 5.06 Long Term Maintenance releases will each be supported by an Arm Compiler Qualification Kit.
3.移植FreeRTOS
这里笔者采用的是比较新的版本 V10.3.0. 具体移植内容如图,启动代码跟以往版本有区别,这里port.c文件引用路径需要特别注意。
基本裁剪由 FreeRTOSConfig.h 统一管理,如下:
#define configUSE_PREEMPTION 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ (SystemCoreClock)
#define configTICK_RATE_HZ ((TickType_t)1000)
#define configMAX_PRIORITIES 5
#define configMINIMAL_STACK_SIZE ((unsigned short)90)
#define configMAX_TASK_NAME_LEN 20
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_TASK_NOTIFICATIONS 1
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 1
#define configUSE_ALTERNATIVE_API 0 /* Deprecated! */
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_QUEUE_SETS 0
#define configUSE_TIME_SLICING 0
#define configUSE_NEWLIB_REENTRANT 0
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 5/* Used memory allocation (heap_x.c) */
#define configFRTOS_MEMORY_SCHEME 4
/* Tasks.c additions (e.g. Thread Aware Debug capability) */
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1/* Memory allocation related definitions. */
#define configSUPPORT_STATIC_ALLOCATION 0
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configTOTAL_HEAP_SIZE ((size_t)(32 * 1024))
#define configAPPLICATION_ALLOCATED_HEAP 0/* Hook function related definitions. */
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_DAEMON_TASK_STARTUP_HOOK 0/* Run time and task stats gathering related definitions. */
#define configGENERATE_RUN_TIME_STATS 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 0/* Task aware debugging. */
#define configRECORD_STACK_HIGH_ADDRESS 1/* Co-routine related definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES 2/* Software timer related definitions. */
#define configUSE_TIMERS 1
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#define configTIMER_QUEUE_LENGTH 10
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE * 2)/* Define to trap errors during development. */
#define configASSERT(x) if(( x) == 0) {taskDISABLE_INTERRUPTS(); for (;;);}/* Optional functions - most linkers will remove unused functions anyway. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_uxTaskGetStackHighWaterMark 0
#define INCLUDE_xTaskGetIdleTaskHandle 0
#define INCLUDE_eTaskGetState 0
#define INCLUDE_xEventGroupSetBitFromISR 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskAbortDelay 0
#define INCLUDE_xTaskGetHandle 0
#define INCLUDE_xTaskResumeFromISR 1/* Override the default implementation of sbSEND_COMPLETED so the macro creates
an interrupt in the M4 core. See the comments at the top of main.c. */
//#define sbSEND_COMPLETED( pxStreamBuffer ) vGenerateSecondaryToPrimaryInterrupt( pxStreamBuffer )#if defined(__ICCARM__)||defined(__CC_ARM)||defined(__GNUC__)/* in Kinetis SDK, this contains the system core clock frequency */#include <stdint.h>extern uint32_t SystemCoreClock;
#endif/* Interrupt nesting behaviour configuration. Cortex-M specific. */
#ifdef __NVIC_PRIO_BITS
/* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
#define configPRIO_BITS __NVIC_PRIO_BITS
#else
#define configPRIO_BITS 4 /* 15 priority levels */
#endif/* The lowest interrupt priority that can be used in a call to a "set priority"
function. */
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1U << (configPRIO_BITS)) - 1)/* The highest interrupt priority that can be used by any interrupt service
routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL
INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 2/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY (configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
//#define xPortSysTickHandler SysTick_Handler
调度时钟修改如下:
void SysTick_Handler(void)
{if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED){xPortSysTickHandler();}
}
4.USB组件移植
usb组件,官方SDK也有提供于是我们直接拷贝到新的工程中。需要注意osa在SDK其他地方(以往老版本是放在usb子文件夹里的),笔者统一放到一起。
这里笔者直接使用官方的一个 usb hid demo.关联文件如图:
5.完善系统,大功告成
创建开始任务,开启系统调度
int main(void)
{xBSP_Config();/*Create Start Task*/ if(xTaskCreate(xTask_Start, "Task_Start", TASK_STACK_SIZE_StartTask, NULL, TASK_PRIORITY_StartTask, &Handle_StartTask) != pdPASS){_Error_Handler(__FILE__, __LINE__);} vTaskStartScheduler(); //开始系统调度while(1){/* 如果系统正常启动是不会运行到这里的,运行到这里极有可能是空闲任务heap空间不足造成创建失败 */}
}
初始化周边外设,创建显示任务(就一个点灯程序)
static void xTask_Start(void *pvParameters)
{xBSP_GPIO_Init();USB_DeviceApplicationInit();//这里就是LED 显示逻辑相关if(xTaskCreate(xAPP_GuiMainTask, "xAPP_GuiMainTask", TASK_STACK_SIZE_GuiMainTask, NULL, TASK_PRIORITY_GuiMainTask, NULL) != pdPASS){_Error_Handler(__FILE__, __LINE__);}/*删除开始任务*/ vTaskDelete(NULL);
}void xAPP_GuiMainTask(void *pvParameters)
{for(;;){AUDIOLED_TOGGLE(); vTaskDelay(100);}
}
测试:灯正常闪烁,插入USB设备正常枚举
下载地址:MK64_RTOS_USB飞思卡尔智能车-OS文档类资源-CSDN下载