目录
6.1.3需要添加以下函数,并在main函数中调用创建log任务
1.添加FreeRTOS相关文件到工程
1.1新建工程分组FreeRTOS,并添加相关文件
添加\external\freertos\source目录下的所有.c文件
接着,依次添加以下文件:
\external\freertos\source\portable\MemMang\heap_1.c
\external\freertos\portable\ARM\nrf52\port.c
\external\freertos\portable\CMSIS\nrf52\port_cmsis.c
\external\freertos\portable\CMSIS\nrf52\port_cmsis_systick.c
1.2 添加其他分组文件
向 nRF_Libraries 中添加
\components\libraries\timer\app_timer_freertos.c
\components\libraries\hardfault\nrf52\handler\hardfault_handler_keil.c
向 nRF_SoftDevice 中添加
\components\softdevice\common\nrf_sdh_freertos.c
2.移除工程分组nRF_Libraries中文件
app_scheduler.c
app_timer2.c
drv_rtc.c
nrf_sortlist.c
3.添加头文件路径
..\..\..\external\freertos\source\include
..\..\..\external\freertos\config
..\..\..\external\freertos\portable\ARM\nrf52
..\..\..\external\freertos\portable\CMSIS\nrf52
4.修改文件
4.1修改sdk_config.h
将宏NRF_SDH_DISPATCH_MODEL 由0改为2
4.2修改freeRTOSConfig.h
configUSE_TIMERS 宏由 0 改为 1
4.3 在工程配置里面添加宏 FREERTOS
4.4修改蓝牙广播初始化
将 advertising_start 函数替换成 nrf_sdh_freertos_init() 函数,并将advertising_start 作为参数,否则无法连接蓝牙。
5.编写代码测试
5.1编写测试代码
编写以下代码,并在 main 函数中调用 freertos_demo();
#include "FreeRTOS.h"
#include "task.h"
/******************************************************************************************************/
/*FreeRTOS配置*/
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 /* 任务优先级 */
#define START_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t StartTask_Handler; /* 任务句柄 */
void start_task(void *pvParameters); /* 任务函数 */
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2 /* 任务优先级 */
#define TASK1_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task1Task_Handler; /* 任务句柄 */
void task1(void *pvParameters); /* 任务函数 */
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3 /* 任务优先级 */
#define TASK2_STK_SIZE 128 /* 任务堆栈大小 */
TaskHandle_t Task2Task_Handler; /* 任务句柄 */
void task2(void *pvParameters); /* 任务函数 */
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t )start_task, /* 任务函数 */
(const char* )"start_task", /* 任务名称 */
(uint16_t )START_STK_SIZE, /* 任务堆栈大小 */
(void* )NULL, /* 传入给任务函数的参数 */
(UBaseType_t )START_TASK_PRIO, /* 任务优先级 */
(TaskHandle_t* )&StartTask_Handler); /* 任务句柄 */
vTaskStartScheduler();
}
/**
* @brief start_task
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
/**
* @brief task1
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task1(void *pvParameters)
{
uint32_t task1_num = 0;
while(1)
{
task1_num++;
printf("task1_num: %d\n", task1_num);
vTaskDelay(1000); /* 延时1000ticks */
}
}
/**
* @brief task2
* @param pvParameters : 传入参数(未用到)
* @retval 无
*/
void task2(void *pvParameters)
{
float task2_num = 0.0;
while(1)
{
task2_num += 0.01f; /* 更新数值 */
printf("task2_num : %0.4f\r\n", task2_num); /* 打印数值 */
vTaskDelay(1000); /* 延时1000ticks */
}
}
5.2测试效果
可见 任务1 和 任务2 依次运行
6.注意事项
6.1开启LOG打印功能
6.1.1修改sdk_config.h
开启以下宏定义:
#define NRF_LOG_BACKEND_RTT_ENABLED 1
#define NRF_LOG_ENABLED 1
#define NRF_LOG_DEFERRED 1
注意:必须将宏定义 NRF_LOG_DEFERRED 置1,开启延迟日志记录,否则会卡死。
6.1.2修改FreeRTOSConfig.h
将 configUSE_IDLE_HOOK 置1,使能空闲任务钩子函数。
6.1.3需要添加以下函数,并在main函数中调用创建log任务
#if NRF_LOG_ENABLED
static TaskHandle_t m_logger_thread; /**< Definition of Logger thread. */
/**@brief Thread for handling the logger.
*
* @details This thread is responsible for processing log entries if logs are deferred.
* Thread flushes all log entries and suspends. It is resumed by idle task hook.
*
* @param[in] arg Pointer used for passing some arbitrary information (context) from the
* osThreadCreate() call to the thread.
*/
static void logger_thread(void * arg)
{
UNUSED_PARAMETER(arg);
while (1)
{
NRF_LOG_FLUSH();
vTaskSuspend(NULL); // Suspend myself
}
}
#endif //NRF_LOG_ENABLED
#if NRF_LOG_ENABLED && NRF_LOG_DEFERRED
//修改空闲任务钩子函数:
void vApplicationIdleHook()
{
vTaskResume(m_logger_thread);
}
#endif
//以下代码放在初始化中
#if NRF_LOG_ENABLED
// Start execution.
if (pdPASS != xTaskCreate(logger_thread, "LOGGER", 256, NULL, 1, &m_logger_thread))
{
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
#endif
6.1.4LOG打印效果演示
6.2内存不足
检查FreeRTOSConf.h中任务总堆栈大小 configTOTAL_HEAP_SIZE 和 最大优先级数量 configMAX_PRIORITIES 的值是否足够。
7.源码下载
通过网盘分享的文件:实验15:蓝牙串口透传-移植FreeRTOS.rar
链接: 百度网盘 请输入提取码