官方下载地址Freertos内核
最基础的freertos只需要包含list.c、queue.c、task.c、heap_x.c和平台相关的移植文件。本文的freertos内核只包含基础的内核。
有关于内核的讲解,我觉得研究是为了理解该博主写的很好。
下载源码
freertos官网链接:FreeRTOS™ - FreeRTOS™
点击下载,选择一个版本下载。笔者选择了202212.01版本。
解压后在FreeRTOSv202212.01\FreeRTOS\Demo\MSP430X_MSP430F5438_IAR目录下有官方的msp430f5438的移植例程。但该例程是某个项目的代码,比较大,不能直接拿来使用,所以参考官方例程,搞个精简版本的。
下载msp430驱动库
官方的例程使用的是寄存器进行操作,msp430官方提供了驱动库,使用起来更加方便。
在examples下有各种模块的驱动例程。
移植流程
1.创建1个空的IAR工程
2.在工作空间下创建1个Freerots-core文件夹,复制FreeRTOSv202212.01\FreeRTOS\Source下的list.c、tasks.c、queue.c和include文件夹到Freerots-core文件夹。还有平台相关的移植层,FreeRTOSv202212.01\FreeRTOS\Source\portable\IAR\MSP430X下的所有文件到Freerots-core/Port文件夹。FreeRTOSv202212.01\FreeRTOS\Source\portable\MemMang下的heap_1.c文件复制到Freerots-core/Port文件夹下。如下图。
3.把固件库msp430_driverlib_2_91_13_01\driverlib\MSP430F5xx_6xx复制到IAR的工作空间。
4.在IAR工作空间下创建User目录,存放用户相关代码,在User目录下创建hardware目录存放外设驱动代码。把官方freertos的msp430f5的IAR例程中的main.c和FreeRTOSConfig.h复制到User目录下。
在hardware目录下,是关于msp430外设驱动的,如下图我写的驱动。其中比较重要的是时钟的初始化文件system_clock.c。
5.把工作目录下的相关文件添加进工程。
6.修改freeRTOSConsig.h文件,把定时部分功能删除了,最后修改成如下:(过程具体修改了哪里,有点忘了)
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( 25000000UL )
#define configLFXT_CLOCK_HZ ( 32768L )
#define configTICK_RATE_HZ ( ( TickType_t ) 100)
#define configMAX_PRIORITIES ( 5 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 10 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 10 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 5
#define configGENERATE_RUN_TIME_STATS 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_RECURSIVE_MUTEXES 0
#define configUSE_MALLOC_FAILED_HOOK 1
#define configUSE_APPLICATION_TASK_TAG 0
#if __DATA_MODEL__ == __DATA_MODEL_SMALL__
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 110 )
#else
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 )
#endif
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 0
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
/* This demo makes use of one or more example stats formatting functions. These
format the raw data provided by the uxTaskGetSystemState() function in to human
readable ASCII form. See the notes in the implementation of vTaskList() within
FreeRTOS/Source/tasks.c for limitations. */
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
/* The MSP430X port uses a callback function to configure its tick interrupt.
This allows the application to choose the tick interrupt source.
configTICK_VECTOR must also be set in FreeRTOSConfig.h to the correct
interrupt vector for the chosen tick interrupt source. This implementation of
vApplicationSetupTimerInterrupt() generates the tick from timer A0, so in this
case configTICK__VECTOR is set to TIMER0_A0_VECTOR. */
#define configTICK_VECTOR TIMER0_A0_VECTOR
7.修改main.c文件。
vApplicationSetupTimerInterrupt函数很重要,当启动调度器时,会调用该函数初始化系统时钟即开启时钟中断。
#include "msp430.h"
#include "driverlib.h"
#include "system_clock.h"
#include "timeA_drv.h"
#include "FreeRTOS.h"
#include "task.h"
volatile uint16_t data=0;
// 任务句柄
TaskHandle_t xTask1Handle = NULL;
TaskHandle_t xTask2Handle = NULL;
// 任务函数
void vTask1(void *pvParameters) {
for (;;) {
// 执行任务1的代码
// 例如,切换LED状态或打印信息
data=100;
}
}
void vTask2(void *pvParameters) {
for (;;) {
// 执行任务2的代码
// 例如,发送数据或打印信息
data=2;
}
}
void main( void )
{
// Stop watchdog timer to prevent time out reset
WDT_A_hold(WDT_A_BASE); // 关闭看门狗
system_clock_init();
// 创建任务1
xTaskCreate(vTask1, "Task1", 256, NULL,
tskIDLE_PRIORITY + 1, &xTask1Handle);
// 创建任务2
xTaskCreate(vTask2, "Task2", 256, NULL,
tskIDLE_PRIORITY + 1, &xTask2Handle);
// 启动调度器
vTaskStartScheduler();
for (;;);
}
/* The MSP430X port uses this callback function to configure its tick interrupt.
This allows the application to choose the tick interrupt source.
configTICK_VECTOR must also be set in FreeRTOSConfig.h to the correct
interrupt vector for the chosen tick interrupt source. This implementation of
vApplicationSetupTimerInterrupt() generates the tick from timer A0, so in this
case configTICK_VECTOR is set to TIMER0_A0_VECTOR. */
void vApplicationSetupTimerInterrupt( void )
{
timeA0_init((uint16_t)configTICK_RATE_HZ);
}
/*-----------------------------------------------------------*/
void vApplicationIdleHook( void )
{
/* Called on each iteration of the idle task. In this case the idle task
just enters a low power mode. */
//__bis_SR_register( LPM3_bits + GIE );
}
/*-----------------------------------------------------------*/
void vApplicationMallocFailedHook( void )
{
/* Called if a call to pvPortMalloc() fails because there is insufficient
free memory available in the FreeRTOS heap. pvPortMalloc() is called
internally by FreeRTOS API functions that create tasks, queues or
semaphores. */
taskDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
{
( void ) pxTask;
( void ) pcTaskName;
/* Run time stack overflow checking is performed if
configconfigCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook
function is called if a stack overflow is detected. */
taskDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
}
8. 添加cstartup.s43文件进工程,并进行修改。
在第7步的时候,我尝试编译并运行程序。由于在cstartup.s43文件中进行初始化的时间大于看门狗复位的时间,没有及时运行到main函数中关闭看门狗,导致看门狗使程序循环复位。
所以,需要在汇编启动文件前,关闭看门狗。
我的cstartup.s43文件在C:\Program Files\IAR Systems\Embedded Workbench 9.1\430\src\lib\430
把该文件添加进工程,取消看门狗的注释,即可关闭看门狗。如下图:
代码
本文的代码存储在