K210 FreeRTOS SDK启动分析

2024-04-03 14:32
文章标签 分析 sdk 启动 freertos k210

本文主要是介绍K210 FreeRTOS SDK启动分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、目的

最近在开始使用K210 FreeRTOS SDK进行应用开发,但是在使用过程发现程序的行为和预期不一致,怀疑这个官方提供的FreeRTOS SDK适配的不是很完整,故本着学习的目的跟着代码分析一下启动过程。

二、必备知识

对freertos有一些基本了解,了解滴答时钟(tick)、任务、任务优先级、空闲任务等基本概念;知道如何配置freertos一些选项,通过修改FreeRTOSConfig.h进行配置。

diff --git a/lib/freertos/conf/FreeRTOSConfig.h b/lib/freertos/conf/FreeRTOSConfig.h
index dac0af6..14fd619 100755
--- a/lib/freertos/conf/FreeRTOSConfig.h
+++ b/lib/freertos/conf/FreeRTOSConfig.h
@@ -59,14 +59,14 @@/* clock */#define configCPU_CLOCK_HZ                                     uxPortGetCPUClock()#define configTICK_CLOCK_HZ                                    ( configCPU_CLOCK_HZ / 50 )
-#define configTICK_RATE_HZ                                     ( ( TickType_t ) 100 )
+#define configTICK_RATE_HZ                                     ( ( TickType_t ) 1000 )/* multithreading */#define configUSE_NEWLIB_REENTRANT                             1#define configUSE_PREEMPTION                                   1#define configUSE_PORT_OPTIMISED_TASK_SELECTION        0
-#define configMAX_PRIORITIES                                   ( 5 )
+#define configMAX_PRIORITIES                                   ( 16 )#define configMAX_TASK_NAME_LEN                                        ( 16 )#define configUSE_TRACE_FACILITY                               1#define configUSE_16_BIT_TICKS                                 0
@@ -108,9 +108,9 @@ enum#define configMAX_CO_ROUTINE_PRIORITIES                        ( 2 )/* Software timer definitions. */
-#define configUSE_TIMERS                                               0
-#define configTIMER_TASK_PRIORITY                              ( 0 )
-#define configTIMER_QUEUE_LENGTH                               2
+#define configUSE_TIMERS                                               1
+#define configTIMER_TASK_PRIORITY                              ( configMAX_PRIORITIES - 1 )
+#define configTIMER_QUEUE_LENGTH                               8#define configTIMER_TASK_STACK_DEPTH                   ( configMINIMAL_STACK_SIZE )

 其中configTICK_RATE_HZ设置tick频率,此处修改为1000Hz,即1ms;configMAX_PRIORITIES设置系统支持的最多优先级,值越大,优先级越高,创建任务时可以配置的最大优先级为configMAX_PRIORITIES -1;configUSE_TIMERS配置系统软件定时器,即rtos实现的软件定时器,一般情况下其优先级需要设置为最大,即configMAX_PRIORITIES -1;

三、启动分析

根据教程,我们是从src/hello_world/main.c程序开始熟悉sdk的调用。

#include <stdio.h>                                                              int main() {                                                                    printf("Hello K210!!!\n");                                                  while (1);                                                                  
}   

此处有个疑问,谁调用了main?rtos是否已经启动了?

针对以上疑问,我们做了这样一个尝试。

#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"static void task_0(void *args) {while (1) {printf("task 0 is polling\n");vTaskDelay(1000 / portTICK_PERIOD_MS);}vTaskDelete(NULL);
}static void task_1(void *args) {while (1) {printf("task 1 is polling\n");vTaskDelay(1000 / portTICK_PERIOD_MS);}vTaskDelete(NULL);
}int main() {printf("Hello K210!!!\n");xTaskCreateAtProcessor(0, task_0, "task0", 1024, NULL, 5, NULL);xTaskCreateAtProcessor(0, task_1, "task1", 1024, NULL, 5, NULL);while (1) {printf("main is polling\n");vTaskDelay(2000 / portTICK_PERIOD_MS);}
}

我们在core 0上面创建了两个任务,并且在mian函数里面也有循环打印。通过编译烧写验证后,确认rtos已经正常工作。

我们知道freertos是通过vTaskStartScheduler接口调用开启多任务调度的,我们跟踪源码lib/freertos/os_entry.c

/* Copyright 2018 Canaan Inc.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
#include "FreeRTOS.h"
#include "core_sync.h"
#include "kernel/device_priv.h"
#include "task.h"
#include <clint.h>
#include <encoding.h>
#include <fpioa.h>
#include <stdio.h>
#include <stdlib.h>typedef struct
{int (*user_main)(int, char **);int ret;
} main_thunk_param_t;extern void __libc_init_array(void);
extern void __libc_fini_array(void);static StaticTask_t s_idle_task[portNUM_PROCESSORS];
static StackType_t s_idle_task_stack[portNUM_PROCESSORS][configMINIMAL_STACK_SIZE];
static StaticTask_t s_timer_task[portNUM_PROCESSORS];
static StackType_t s_timer_task_stack[portNUM_PROCESSORS][configMINIMAL_STACK_SIZE];void start_scheduler(int core_id);int __attribute__((weak)) configure_fpioa()
{return 0;
}static void main_thunk(void *p)
{/* Register finalization function */atexit(__libc_fini_array);/* Init libc array for C++ */__libc_init_array();install_hal();install_drivers();configure_fpioa();main_thunk_param_t *param = (main_thunk_param_t *)p;param->ret = param->user_main(0, 0);
}static void os_entry_core1()
{clear_csr(mie, MIP_MTIP);clint_ipi_enable();set_csr(mstatus, MSTATUS_MIE);vTaskStartScheduler();
}int os_entry(int (*user_main)(int, char **))
{clear_csr(mie, MIP_MTIP);clint_ipi_enable();set_csr(mstatus, MSTATUS_MIE);TaskHandle_t mainTask;main_thunk_param_t param = {};param.user_main = user_main;if (xTaskCreate(main_thunk, "Core 0 Main", configMAIN_TASK_STACK_SIZE, &param, configMAIN_TASK_PRIORITY, &mainTask) != pdPASS){return -1;}core_sync_awaken((uintptr_t)os_entry_core1);vTaskStartScheduler();return param.ret;
}void vApplicationIdleHook(void)
{
}void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize)
{UBaseType_t uxPsrId = uxPortGetProcessorId();/* Pass out a pointer to the StaticTask_t structure in which the Idle task'sstate will be stored. */*ppxIdleTaskTCBBuffer = &s_idle_task[uxPsrId];/* Pass out the array that will be used as the Idle task's stack. */*ppxIdleTaskStackBuffer = s_idle_task_stack[uxPsrId];/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.Note that, as the array is necessarily of type StackType_t,configMINIMAL_STACK_SIZE is specified in words, not bytes. */*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize)
{UBaseType_t uxPsrId = uxPortGetProcessorId();/* Pass out a pointer to the StaticTask_t structure in which the Idle task'sstate will be stored. */*ppxTimerTaskTCBBuffer = &s_timer_task[uxPsrId];/* Pass out the array that will be used as the Idle task's stack. */*ppxTimerTaskStackBuffer = s_timer_task_stack[uxPsrId];/* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer.Note that, as the array is necessarily of type StackType_t,configMINIMAL_STACK_SIZE is specified in words, not bytes. */*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
{configASSERT(!"Stackoverflow !");
}

我们看到os_entry这个函数里面调用了vTaskStartScheduler,并且在调用之前,创建了一个main_thunk任务并且同时调用core_sync_awaken((uintptr_t)os_entry_core1);这个os_entry_core1内部又调用了vTaskStartScheduler,开启了core 1的多任务调度。main_thunk任务内部执行了一些系统初始化操作(hal/drivers/fpioa),然后执行user_main函数,这个函数就是os_entry函数的入参,我们继续跟踪,发现lib/bsp/entry_user.c这个里面的_init_bsp调用了os_entry(main),此处的main即src/hello_world/main.c里面main函数,另外通过汇编代码跟踪,我们发现lib/bsp/crt.S这个里面调用了_init_bsp。

至此我们完成了整个系统rtos的启动过程。

这篇关于K210 FreeRTOS SDK启动分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/873167

相关文章

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

springboot3打包成war包,用tomcat8启动

1、在pom中,将打包类型改为war <packaging>war</packaging> 2、pom中排除SpringBoot内置的Tomcat容器并添加Tomcat依赖,用于编译和测试,         *依赖时一定设置 scope 为 provided (相当于 tomcat 依赖只在本地运行和测试的时候有效,         打包的时候会排除这个依赖)<scope>provided

内核启动时减少log的方式

内核引导选项 内核引导选项大体上可以分为两类:一类与设备无关、另一类与设备有关。与设备有关的引导选项多如牛毛,需要你自己阅读内核中的相应驱动程序源码以获取其能够接受的引导选项。比如,如果你想知道可以向 AHA1542 SCSI 驱动程序传递哪些引导选项,那么就查看 drivers/scsi/aha1542.c 文件,一般在前面 100 行注释里就可以找到所接受的引导选项说明。大多数选项是通过"_

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

SpringBoot项目是如何启动

启动步骤 概念 运行main方法,初始化SpringApplication 从spring.factories读取listener ApplicationContentInitializer运行run方法读取环境变量,配置信息创建SpringApplication上下文预初始化上下文,将启动类作为配置类进行读取调用 refresh 加载 IOC容器,加载所有的自动配置类,创建容器在这个过程