-
LiteOS给提供了多种内存动态匹配算法默认使用BestFit (最佳适应算法),其他算法还包括DLINK算法。为啥答案时AD。 242040 LiteOS给提供了多种内存动态匹配算法默认使用BestFit (最佳适应算法),其他算法还包括DLINK算法。为啥答案是AD
-
LiteOS给提供了多种内存动态匹配算法默认使用BestFit (最佳适应算法),其他算法还包括DLINK算法。为啥答案时AD。 242033
-
LiteOS有什么方法解决通常物联网开发遇到的开发语言编程效率低、上手难度大的问题?
-
LiteOS会增加插件让树莓派,Atlas200DK,等ARM开发板简单调用LiteOS的功能吗?
-
LiteOS如果要将数据转存到本地MySQL及云端MySQL上(每次40个字符,MQTT),对通信负载影响多大?
-
现在开发应用都向快捷高效靠拢,LiteOS什么时候推出图像编程工具,减少开发时间?
-
我就知道好像0是最高优先级
-
LiteOS有相关雾计算的能力吗?需要硬件搭配?
-
LiteOS开发板与昇腾Atlas200DK在同一项目时,有能相互调用API使用对方资源的内置函数吗?
-
LiteOS Studio为什么要加入C++?Arduino为什么要使用C++?
-
通常在基于系统的应用程序开发时,通信程序和显示程序会不同的线程中来运行,以避免由于通信程序的问题而导致界面程序也一同挂掉的现象。基于LiteOS这种轻量级的系统上的应用开发也会遇到类似的情况。本文使用小熊派开发板,参考IoT Link中的Demo程序,基于LiteOS系统之上,使用LiteOS的多任务管理功能,编写实现了两个任务之间串行通信的Demo程序,并在每个任务中将收发相关的信息使用LCD显示出来。1. 硬件设计本文使用了小熊派智慧农业的开发主板。在这个开发主板上,以STM32L431RTC6为主控制器。开发板上连接E53的接口中有UART3的连接端子,如下图中的18和19两个引脚。其中18引脚对应的是STM32L431RTC6的PC4引脚,即UART3_Tx; 19引脚对应的是STM32L431RTC6的PC5引脚,即UART3_Rx。在其P5端子排中预留了UART2的连接端子,如下图中的5和6引脚。其中5引脚对应的是STM32L431RTC6的PA2引脚,即UART2_Tx;6引脚对应的是STM32L431RTC6的PA3引脚,即UART2_Rx。Demo程序使用UART2发送数据,UART3接收数据。因此将5引脚和19引脚连接,6引脚和18引脚连接。注意这里的引脚编号是指小熊派开发主板上的相关编号。连接好的硬件如下图所示。2. Demo程序设计2.1 Demo程序的工程创建基于IoT Link Studio进行设计开发。在VS Code中,使用IoT Link Studio,创建基于STM32L431_BearPi_OS_Func的硬件平台的示例工程osal_task_demo。如下图所示。2.2 程序设计思路2.2.1 两个任务的创建在程序中创建两个任务,分别称为任务1和任务2.在任务1中使用UART2发送数据,并将发送的数据显示在LCD上。在任务2中使用UART3接收数据,并将接收的数据显示在LCD上。如下图是创建两个任务的函数。在这个函数中调用了初始化uart2_3_init()函数。//demo_main函数 //初始化UART2和UART3,并创建了两个任务。这样两个任务就会被LiteOS系统自动调用。 int standard_app_demo_main() { //printf("user task 1 exit!\r\n"); uart2_3_init(); user_task1_id = osal_task_create("user_task1",user_task1_entry,NULL,0x400,NULL,USER_TASK1_PRI); user_task2_id = osal_task_create("user_task2",user_task2_entry,NULL,0x400,NULL,USER_TASK2_PRI); return 0; }2.2.2 UART2 和 UART3的初始化及相关中断的创建为了使用UART2和UART3,自定义了初始化UART2和UART3的函数,即UART2_3_init(void)。如下图所示的代码。//小熊派主板上的UART2和UART3的初始化以及相关中断的创建 //UART2是PA2_Tx,PA3_Rx; UART3是PC4_Tx,PC5_Rx void uart2_3_init(void) { MX_USART2_UART_Init(); //初始化串口 PC4 PC5 波特率9600 MX_USART3_UART_Init(); //初始化串口 PA2 PA3 波特率为9600 LOS_HwiCreate(USART2_IRQn, 6,0,USART2_IRQHandler,NULL); //创建中断 LOS_HwiCreate(USART3_IRQn, 7,0,USART3_IRQHandler,NULL); //创建中断 LiteOS默认的最小的中断优先级数值是7 }在这个函数中首先调用usart.c中的两个初始化函数,来进行UART2和UART3的初始化。串行口在通信时两端的波特率、停止位、奇偶校验位等参数设置需要相同。在初始化两个UART时,要注意修改usart.c中的代码确保两个串行口的相关参数是相同的,这样可以避免一些问题产生。如下是usart.c中初始化UART2和UART3的函数代码。/* USART2 init function */ void MX_USART2_UART_Init(void) { huart2.Instance = USART2; huart2.Init.BaudRate = 9600; huart2.Init.WordLength = UART_WORDLENGTH_8B; huart2.Init.StopBits = UART_STOPBITS_1; huart2.Init.Parity = UART_PARITY_NONE; huart2.Init.Mode = UART_MODE_TX_RX; huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart2.Init.OverSampling = UART_OVERSAMPLING_16; huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart2) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } } /* USART3 init function */ void MX_USART3_UART_Init(void) { huart3.Instance = USART3; huart3.Init.BaudRate = 9600; //115200 huart3.Init.WordLength = UART_WORDLENGTH_8B; huart3.Init.StopBits = UART_STOPBITS_1; huart3.Init.Parity = UART_PARITY_NONE; huart3.Init.Mode = UART_MODE_TX_RX; huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart3.Init.OverSampling = UART_OVERSAMPLING_16; huart3.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart3.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart3) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } }然后调用LOS_HwiCreate(USART2_IRQn, 6,0,USART2_IRQHandler,NULL); //创建中断 LOS_HwiCreate(USART3_IRQn, 7,0,USART3_IRQHandler,NULL); //创建中断 LiteOS默认的最小的中断优先级数值是7创建UART2的全局中断USART2_IRQn,并将全局中断处理函数USART2_IRQHandler与这个中断挂接。创建UART3的全局中断USART3_IRQn,并将全局中断处理函数USART3_IRQHandler与这个中断挂接。上述两个中断处理函数都在stm32l4xx_it.c文件中,代码如下。/** * @brief This function handles USART2 global interrupt. */ void USART2_IRQHandler(void) { /* USER CODE BEGIN USART2_IRQn 0 */ /* USER CODE END USART2_IRQn 0 */ HAL_UART_IRQHandler(&huart2); /* USER CODE BEGIN USART2_IRQn 1 */ /* USER CODE END USART2_IRQn 1 */ } /** * @brief This function handles USART3 global interrupt. */ void USART3_IRQHandler(void) { /* USER CODE BEGIN USART3_IRQn 0 */ /* USER CODE END USART3_IRQn 0 */ HAL_UART_IRQHandler(&huart3); /* USER CODE BEGIN USART3_IRQn 1 */ /* USER CODE END USART3_IRQn 1 */ }这两个中断服务主要调用了STM32L4xx_HAL_Driver(STM32L4系列的硬件驱动库)中的函数,在文件stm32l4xx_hal_uart.c中有它们的实现代码。这相当于最终使用了STM32L4库函数中的中断服务函数。在创建上述的中断时,要留意,中断优先级最好不要大于7,因为LiteOS中默认配置的中断优先级的最小数值是7。有了中断后,两个串口之间的通信就可以采用非阻塞的方式进行了。2.2.3 采用非阻塞方式通信主要定义了使用UART2发送数据的函数和使用UART3接收数据的函数。分别接收如下。发送函数uart2_send,代码如下static ssize_t uart2_send(const char *buf,size_t len, unsigned int timeout) { HAL_UART_Transmit(&huart2,(unsigned char *)buf,len,timeout); //HAL_UART_Transmit(&huart3, "$CCMSG,GGA,1,0,*19\r\n", 20, 200); HAL_Delay(200); return len; }这个函数其实主要是调用HAL_UART_Transmit函数来通过UART2发送数据。这个HAL_UART_Transmit函数也属于STM32L4xx系列的硬件驱动库函数,也在文件stm32l4xx_hal_uart.c文件中。由于使用的是UART2发送数据,所以在调用这个函数的时候,第一个参数需要传递&huart2. huart2包含了UART2的很多配置信息,是在usart.c中定义的一个全局变量,可以在这里使用。接收数据的函数uart3_receive,代码如下//使用UART3接收数据的函数 void uart3_receive(void) { HAL_StatusTypeDef ret; ret=HAL_UART_Receive_IT(&huart3,g_revBuf,UART_INFO_MAX_LEN); }这个函数其实主要是调用HAL_UART_Receive_IT函数来通过UART3接收数据。这个HAL_UART_Receive_IT函数也属于STM32L4xx系列的硬件驱动库函数,也在文件stm32l4xx_hal_uart.c文件中。由于使用的是UART3接收数据,所以在调用这个函数的时候,第一个参数需要传递&huart3. huart3包含了UART3的很多配置信息,是在usart.c中定义的一个全局变量,可以在这里使用。上述两个函数的使用,可以在stm32l4xx_hal_uart.c文件中的说明部分能看到如下使用提示信息2.2.4 两个任务的入口函数LiteOS系统中,创建任务时,需要指定任务的入口函数。任务运行的时候,是从入口函数开始执行的。两个任务的入口函数分别说明如下。任务1的入口函数user_task1_entry()//任务1的入口函数 //任务1主要是通过UART2不断的发送数据,并将发送的数据在LCD上显示 static int user_task1_entry() { int i=1; while(i>0) { LCD_Clear(WHITE); POINT_COLOR = BLUE; switch(i) { case 1: uart2_send("abcdefg",UART_INFO_MAX_LEN,200); LCD_ShowString(10, 10, 240, 24, 16, "UART2_Sent Info:"); LCD_ShowString(10, 30, 240, 24, 16, "abcdefg"); break; case 2: uart2_send("0123456789",UART_INFO_MAX_LEN,200); LCD_ShowString(10, 10, 240, 24, 16, "UART2_Sent Info:"); LCD_ShowString(10, 30, 240, 24, 16, "0123456789"); break; case 3: uart2_send("ABCDEFG",UART_INFO_MAX_LEN,200); LCD_ShowString(10, 10, 240, 24, 16, "UART2_Sent Info:"); LCD_ShowString(10, 30, 240, 24, 16, "ABCDEFG"); break; case 4: uart2_send("I love China.",UART_INFO_MAX_LEN,200); LCD_ShowString(10, 10, 240, 24, 16, "UART2_Sent Info:"); LCD_ShowString(10, 30, 240, 24, 16, "I love China."); break; case 5: uart2_send("I like IOT.",UART_INFO_MAX_LEN,200); LCD_ShowString(10, 10, 240, 24, 16, "UART2_Sent Info:"); LCD_ShowString(10, 30, 240, 24, 16, "I like IOT."); break; } osal_task_sleep(2*500); i++; if(i>5) i=1; printf("task1-%ld: Send task is working.\r\n", user_task1_id); } printf("user task 1 exit!\r\n"); return 0; }任务1入口函数主要是不断调用发送数据的函数发送一些示例的信息,同时将发送的信息显示在LCD上。逻辑比较简单,就不多做说明了。任务2的入口函数user_task2_entry()/任务2的入口函数 //任务2主要是通过UART3不断接收数据,并将接收到的数据显示在LCD上 static int user_task2_entry() { int i=5; while (1) { LCD_Clear(WHITE); POINT_COLOR = RED; uart3_receive(); LCD_ShowString(10, 50, 240, 24, 16, "UART3_Received Info:"); if(g_revBuf[0] != 0 ) { LCD_ShowString(10, 70, 240, 24, 16, g_revBuf); } printf("task 2-%ld: LCD show task is working.\r\n", user_task2_id); osal_task_sleep(2*600); } printf("user task 2 exit!\r\n"); return 0; }任务2的入口函数主要是不断调用接收函数,接收数据,并将接收到的数据信息显示在LCD上。同样,逻辑比较简单,就不多做说明了。2.2.5 头文件及一些全局变量程序中使用的头文件及一些全局变量如下#include <osal.h> #include <usart.h> #include <stm32l431xx.h> #include "gpio.h" #include "lcd.h" #include <stm32l4xx_it.h> #define USER_TASK1_PRI 12 #define USER_TASK2_PRI 11 #define UART_INFO_MAX_LEN 20 uint32_t user_task1_id = 0; uint32_t user_task2_id = 0; unsigned char g_revBuf[UART_INFO_MAX_LEN]={0};注意在编译程序的时候,把相关的头文件包括在头文件路径中。3. 编译运行验证在IoT Link Studio中编译程序,编译成功后的结果如下编译成功后,下载程序到开发板,运行验证,一些效果图片如下。 4. 总结通过这个Demo程序,在LiteOS系统基础上,实现了多任务的串行数据收发及显示功能。总结Demo程序,可以看出,LiteOS提供了很好的任务管理功能。每个任务的具体功能的编写时,除了使用LiteOS的一些API函数外,还可以使用很多STM32的库函数。本文的Demo可以说是需要综合应用了LiteOS的一些API和STM32的库函数,实现了串行口的收发和信息显示功能。个人的思路难免存在疏漏,有不正确或者不合适的地方,欢迎大家提出讨论,共同学习共同进步。
-
随着5G和智能化的来临,物联网(IoT)的发展也变得更加快速。当前的物联网领域已经形成了庞大的生态系统,市场上的微控制器(MCU)供应商和嵌入式操作系统(一般也是实时操作系统)也多达几十个,开发者面对的嵌入式软件工程越发复杂。为减少开发工作量并降低产品存在缺陷的风险,软件重用变得越来越重要。因此各标准组织和相关利益厂商,都在积极制定和推动软件接口标准。和操作系统(OS)相关的一个重要标准是POSIX(Portable Operating System Interface of UNIX),表示可移植操作系统接口。虽然POSIX中的X代表的是UNIX,但其实POSIX并不局限于UNIX,许多其它的OS也可以符合POSIX标准。POSIX是IEEE为在各种OS上运行的软件而定义的一组API接口标准,目标是获得源代码级别的软件可移植性。也就是说,在一个符合POSIX标准的OS上开发的应用程序,在其它的POSIX操作系统上无需修改也可以直接编译运行。LiteOS作为一款嵌入式操作系统,必须要考虑软件的可移植性,有效降低开发者的开发难度。当前LiteOS已经支持100+个POSIX标准接口,涵盖了一些常用的基本接口,包括线程操作(比如线程同步、线程调度、管理线程属性等)、消息队列操作、软件定时器操作、socket通信操作、文件系统类操作等等。感兴趣的话,可以去源码lib/huawei_libc下面查看。除了POSIX标准,在物联网领域还有一个CMSIS(Cortex Microcontroller Software Interface Standard)标准,它是ARM同各个微控制器供应商、工具供应商和软件解决方案一起开发的Cortex微控制器软件接口标准。它使得微控制器和软件供应商可以使用一致的软件结构来开发Cortex微控制器的软件。CMSIS-RTOS是CMSIS的一部分,它本身是一种API规范,各厂商可以基于CMSIS-RTOS构建自己的实时操作系统(RTOS)。由于基于CMSIS-RTOS的API是标准化的,所以基于这些API开发的应用软件,不需要进行额外的移植开发工作,就可跑在任何支持CMSIS-RTOS的OS上。随着基于CMSIS-RTOS的中间件越来越多,支持CMSIS-RTOS后的OS也会因此获得更多的中间件。LiteOS基于CMSIS-RTOS API v1和v2,对自己的API进行了封装,可以在源码目录compat/cmsis下看到对CMSIS-RTOS API v1和v2的支持。
-
移植了一天满脸的懵逼,用旧版的源码移植挺顺利的. 最新版的似乎改动挺大的..
-
我参考这个教程移植liteos时发现liteos源码里没有examples文件夹教程如下https://support.huaweicloud.com/bestpractice-LiteOS/zh-cn_topic_0145350109.html
-
另外,弱弱问一下,liteOS的版本号体现在哪?历史变动的描述又在哪个文档? --才接触,还没有仔细看相关文档。 手头有一个以前版本的lite os,移植到STM32也是ok的。想着要改OS,就用最新的版本。 但是新版本结构似乎变动很大,h文件也到处关联,有些c文件也比较分散,都不知道到底加哪些路径的include才ok,不知道加哪些c文件才算移植完整。比如那边los_hwi_m.c(\LiteOS-LiteOS-master\LiteOS\arch\arm\cortex-m\src),在另外一个路径下又有一个以前用的los_hwi.c(\LiteOS-LiteOS-master\LiteOS\arch\common)。
上滑加载中
推荐直播
-
openEuler Summit 2024
2024/11/16 周六 09:30-12:00
华为讲师团
2024年11月15日-16日,我们将在北京中关村国际创新中心举办 操作系统大会&openEuler Summit 2024,本次大会旨在汇聚全球产业发展力量,邀请思想引领者、商业精英、技术专家、合作伙伴以及全球开源基金会等业界同仁,共同探讨操作系统产业发展方向和未来机遇,联合伙伴展示最新合作成果,分享数字化转型实践,以技术驱动创新不断激发新质生产力。
正在直播 -
华为云AI入门课:AI发展趋势与华为愿景
2024/11/18 周一 18:20-20:20
Alex 华为云学堂技术讲师
本期直播旨在帮助开发者熟悉理解AI技术概念,AI发展趋势,AI实用化前景,了解熟悉未来主要技术栈,当前发展瓶颈等行业化知识。帮助开发者在AI领域快速构建知识体系,构建职业竞争力。
去报名 -
华为云软件开发生产线(CodeArts)10月新特性解读
2024/11/19 周二 19:00-20:00
苏柏亚培 华为云高级产品经理
不知道产品的最新特性?没法和产品团队建立直接的沟通?本期直播产品经理将为您解读华为云软件开发生产线10月发布的新特性,并在直播过程中为您答疑解惑。
去报名
热门标签