• [问题求助] STM32L431RCT6+BC35—G 用liteOS的tickless机制 低功耗配置求助
    因项目需要,需要在题目所述平台上开启低功耗功能,所以尝试使用tickless机制,但是在程序运行时,发现内核初始化函数LOS_KernelInit()会自动创建一个IDLEtask,IDLETASK指向了一个入口函数,如下所示:LITE_OS_SEC_TEXT WEAK VOID osIdleTask(VOID){    while (1)    {        #if (LOSCFG_KERNEL_TICKLESS == YES)//LOSCFG_KERNEL_TICKLESS 触发睡眠                        osTicklessHandler(); //Tickless模式执行        #else                #if (LOSCFG_KERNEL_RUNSTOP == YES) //                        osEnterSleep();                #endif        #endif    }}在LOSCFG_KERNEL_TICKLESS宏定义开启的情况下,该函数指向了osTicklessHandler():VOID osTicklessHandler(VOID){#if (LOSCFG_KERNEL_TICKLESS == YES)    if (g_bTickIrqFlag) //任务计数器    {        g_bTickIrqFlag = 0;         osTicklessStart();    }    osEnterSleep();#else    if (g_bTickIrqFlag)    {        UINTPTR uvIntSave;        uvIntSave = LOS_IntLock();        LOS_TaskLock();        g_bTickIrqFlag = 0;        osTicklessStart();                    osEnterSleep();        LOS_IntRestore(uvIntSave);        /*         * Here: Handling interrupts. However, because the task scheduler is locked,         * there will be no task switching, after the interrupt exit, the CPU returns         * here to continue excuting the following code.         */        uvIntSave = LOS_IntLock();        osUpdateKernelTickCount(0);  /* param: 0 - invalid */        LOS_TaskUnlock();        LOS_IntRestore(uvIntSave);    }    else    {        /* Waiting for g_bTickIrqFlag setup, at most one tick time, sleep directly */        osEnterSleep();    }#endif}最后应该是执行osEnterSleep()函数,原本这个函数里面写的是三条汇编指令LITE_OS_SEC_TEXT_INIT VOID osEnterSleep(VOID){   __DSB();    __WFI();    __ISB();}自己修改这个后配置MCU进入stop2模式,RTC定时唤醒,代码如下:LITE_OS_SEC_TEXT_INIT VOID osEnterSleep(VOID){       MX_RTC_Init();        printf("goto STOP2 MODE\r\n");        /* 失能所有的串口 */        __HAL_RCC_GPIOA_CLK_ENABLE();        __HAL_RCC_GPIOB_CLK_ENABLE();        __HAL_RCC_GPIOC_CLK_ENABLE();        __HAL_RCC_GPIOH_CLK_ENABLE();        SystemPower_Pre_STOP();//把所有的GPIO设置成模拟输入        HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);//重置RTC服务        HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 60, RTC_WAKEUPCLOCK_RTCCLK_DIV16);//开启RTC唤醒中断,60S唤醒一次        HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);//进入STOP2模式        /*  退出低功耗模式,硬件初始化 */                        SystemClock_Config();        MX_GPIO_Init();        HAL_UART_MspInit(&huart1);        LCD_Init();                printf("exit STOP2\r\n");}程序执行时一直循环执行osEnterSleep()函数,无法继续完成liteos初始化以及开启系统,求助这种依靠与tickless的低功耗方式该如何设计
  • [问题求助] 【BearPi-IOT产品】【编译功能】编译了提供的人体感应项目源码,但出现如下错误
    【截图信息】
  • [知识分享] 一起玩转玩转LiteOS组件:Opus
    >摘要:Opus编码器是一个开源的有损声音编码格式,适用于网络实时声音传输,标准格式为RFC 6716,相对于其他编码格式来说,保真性更好。本文分享自华为云社区《[LiteOS组件尝鲜—玩转Opus](https://bbs.huaweicloud.com/blogs/327072?utm_source=csdn&utm_medium=bbs-ex&utm_campaign=iot&utm_content=content)》,作者: Lionlace。 Opus编码器是一个开源的有损声音编码格式,适用于网络实时声音传输,标准格式为RFC 6716,相对于其他编码格式来说,保真性更好。 # Opus接口介绍 本文档介绍一些Opus的常用接口,更多详细接口介绍请参考components/media/opus/opus-1.3.1/include/opus.h文件。 Opus解码的过程是将opus格式转换为pcm格式,编码的过程是将pcm格式转换为opus格式。 # 解码 ## 创建解码器 OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create( opus_int32 Fs, int channels, int *error ); 解码器配置 OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1); 解码 OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode( OpusDecoder *st, const unsigned char *data, opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4); 删除解码器 `OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);` ## 编码 创建编码器 OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create( opus_int32 Fs, int channels, int application, int *error ); 编码器配置 OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1); 编码 OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode( OpusEncoder *st, const opus_int16 *pcm, int frame_size, unsigned char *data, opus_int32 max_data_bytes ) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4); 删除编码器 `OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);` ## Opus编解码中常用参数 sampling rate采样率,在opus中只能取值为8000,12000,16000,24000,48000,单位为赫兹(HZ)。 channel声道,channel = 1为单声道,channel = 2为立体声。 frame size帧大小,在opus中每帧的时间取值为2.5,5,10,20,40,60,80,100,120。单位毫秒(ms)。单通道的帧大小 = 采样率 * 帧时间(单位为秒)。 其他详情参考音频编码:https://gitee.com/linktarget=https%3A%2F%2Fbaike.baidu.com%2Fitem%2F%25E9%259F%25B3%25E9%25A2%2591%25E7%25BC%2596%25E7%25A0%2581%2F1729208%3Ffr%3Daladdin。 # Opus Demo解析 LiteOS社区提供了OpusDemoTask示例程序来演示如何使用opus,该Demo可以运行在LiteOS所支持的多块开发板上。本Demo以解码为例,其中inputBuf为采用opus格式编码的一段数据,对该数据进行解码处理,并将解码后数据以pcm格式保存到outputBuf。 ## 使能Opus Demo 在LiteOS源码根目录下根据实际使用的开发板,拷贝tools/build/config/目录下的默认配置文件${platform}.config到根目录,并重命名为.config。 继续在LiteOS源码根目录下执行make menuconfig命令,按如下菜单路径使能Opus Demo。 Demos ---> Media Demo ---> [*] Enable Opus Demo 使能Opus Demo后会自动使能Opus组件。 保存退出后,LiteOS会从github上自动下载opus源代码,并从gitee上下载适配于LiteOS系统的patch包,并打入patch。关于组件下载的详细流程请参考:LiteOS_Components: Huawei LiteOS组件仓库,主要存放组件的补丁及相关的sha256校验文件。 **注**:要成功下载相关资源,需要Linux主机可访问互联网,并安装git工具。 ## 编译运行Opus Demo 使能Opus Demo后,在LiteOS源码根目录下执行make clean; make -j命令编译LiteOS工程,编译成功后会在out/{platform}/lib路径下生成libopus.a和libopus_demo.a文件,系统镜像文件为Huawei_LiteOS.bin。 以realview-pbx-a9为例,运行OpusDemoTask。 其他开发板操作请参考快速入门:https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Quick_Start.md。。 执行结果如下: ********Hello Huawei LiteOS******** LiteOS Kernel Version : 5.0.0 Processor : Cortex-A9 * 4 Run Mode : SMP GIC Rev : GICv1 build time : Dec 25 2021 22:52:50 ********************************** main core booting up... osAppInit releasing 3 secondary cores cpu 0 entering scheduler cpu 2 entering scheduler cpu 3 entering scheduler cpu 1 entering scheduler app init! Hello, welcome to liteos demo! Opus demo task start to run. Opus demo input data: 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x00 0xe0 Opus demo output data: 0x0000 0xfffd 0xfff4 0xffda 0xffaa 0xff88 0xff55 0xff03 0xff14 0xff83 0xffb4 0x001f 0x0070 0x01bb 0x024b 0x0274 0x02be 0x032a 0x0299 0x02a8 0x039c 0x05ef 0x0605 0x04fa 0x03d9 0x02b6 0x01d1 0x0113 0x0079 0xffd8 0x001d 0x000d 0xffdf 0xffbb 0xffac 0xffa0 0xff64 0xffc4 0xfff5 0xffee 0xffeb 0x006c 0x005e 0x0044 0x0045 0x02dc 0x0472 0x00db 0xff85 0x0347 0xfdc4 0xf957 0xf7c1 0xf62b 0xf3aa 0xf817 0xfb18 0xfcee 0x01b1 0x079e 0x059d 0x0aa0 0x0608 0x01c6 0xfdaf 0xfdda 0xfa18 0xf6d6 0xf701 0xfc43 0x0186 0x0387 0x0975 0xbb78 0xd771 0xd143 0xbc64 0xbcb9 0xe7f9 0xfd99 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 0x0000 Opus demo decode seccussfully. Opus demo task finished. Huawei LiteOS # # 结语 未来我们还会持续新增更多组件、开发板、架构、特性等。 感谢您的阅读,有任何问题、建议,都可以留言给我们,让我们一起进步:https://gitee.com/LiteOS/LiteOS/issues 为了更容易找到“LiteOS”代码仓,建议访问https://gitee.com/LiteOS/LiteOS,关注“ Watch”、点赞“Star”、并“Fork”到自己账号下,如下图。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/20222/25/1645755496861467052.png) https://gitee.com/LiteOS/LiteOS/blob/master/doc/LiteOS_Quick_Start.md。
  • [问题求助] Liteos文件系统支持的开发板
    【功能模块】文件系统【操作步骤&问题现象】1、目前Liteos的文件系统支持的开发板是否有变化和扩充呢?2、不支持的原因主要是什么呢?是硬件没有提供对应驱动还是别的什么原因吗?【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [问题求助] 请问liteOS怎么实现重启系统啊
    在实际过程中会需要到配置系统相关参数,需要重启
  • [技术干货] 小熊派实现鸿蒙开机界面(LiteOS+LVGL)
    小熊派实现鸿蒙开机界面(LiteOS+LVGL) 一、文章前言 二、编写代码 三、实验现象 四、项目源码 小熊派实现鸿蒙开机界面(LiteOS+LVGL)一、文章前言之前使用小熊派实现了鸿蒙动画的开机界面,具体使用的技术栈为 STM32 + LiteOS + LVGL + FATFS +DMA 方式实现,刷新效率非常高,预览视频如下:关于这个的实现过程我会写一系列的教程分享出来,主要分为下面几个部分,本节为第四部分,在前三节的移植之后• 小熊派移植华为 LiteOS-M(基于MDK):链接 ;• 小熊派基于 LiteOS 移植 LVGL 显示接口:链接 ;• 小熊派基于 LiteOS 移植 LVGL 文件系统:链接 ;• 小熊派实现鸿蒙开机界面(LiteOS+LVGL):链接 ;二、编写代码实现 LVGL 和 LiteOS 的底层移植之后,下一步就是编写显示代码,显示的原理就是依次读取图片 bin 文件的数据,将数据打印到屏幕上,这里使用的图片大小是 150*60 ,因为小熊派的内存有限,无法准备太大的 RAM 空间,所以我只显示一小部分关键视频信息,这里的视频 bin 文件先使用导出软件将视频导出每一张图片,然后用 lvgl 的转化工具转化为 bin 文件,将 bin 文件按顺序合并成一个 bin 文件,然后放到 SD 卡中,这里的 bin 文件我已经上传到 Github 的项目工程里面然后我么编写逻辑代码,主要在 Lcd_Task 任务中编写代码:先在开头定义一个图像文件参数:lv_img_dsc_t testimg1 = {.header.always_zero = 0,.header.w = 150,.header.h = 60,.data_size = 150 * 60 * 2,.header.cf = LV_IMG_CF_TRUE_COLOR,};然后在任务内进行变量定义和初始化:lv_fs_res_t fs_res=LV_FS_RES_NOT_IMP;lv_fs_file_t lv_file;int offset;LCD_Init();lv_init();lv_port_disp_init();//lvgl 显示接口初始化,放在 lv_init()的后面lv_port_fs_init();然后创建 LVGL 对象:分别是样式结构体、背景对象以及图片对象lv_style_t style1;lv_style_init(&style1);lv_style_set_bg_color(&style1, LV_STATE_DEFAULT,LV_COLOR_BLACK);lv_style_set_border_width(&style1,LV_STATE_DEFAULT, 0);lv_style_set_radius(&style1,LV_STATE_DEFAULT,0);lv_obj_t* bkg = lv_obj_create(lv_scr_act(),NULL);lv_obj_set_pos(bkg,0,0);lv_obj_set_size(bkg,240,240);lv_obj_add_style(bkg,LV_OBJ_PART_MAIN,&style1);lv_obj_t* homonoryimg = lv_img_create(lv_scr_act(), NULL);后面在函数主循环内申请动态内存,打开读取 SD 卡图片 bin 文件uint8_t* framebuffer1 = (uint8_t*)lv_mem_alloc(sizeof(uint8_t)*18000);fs_res = lv_fs_open(&lv_file, "S:/os.bin", LV_FS_MODE_RD| LV_FS_MODE_WR);if ( fs_res != LV_FS_RES_OK )printf( "LVGL FS open error. (%d)\r\n", fs_res );定位文件,因为生成的 bin 文件开头有4个字节的非图片数据,跳过它offset = 0;offset += 4; //从offset=4lv_fs_seek(&lv_file, offset);然后因为这个 bin 文件有 401 张图片 ,所以我循环往后读 401 次,把读取的图片依次显示在 homonoryimg 图片对象上//计算bin文件里一共包含多少张图片,然后不断的给tft进行显示for(int i = 0 ; i < 401 ; i++){fs_res = lv_fs_read(&lv_file, (uint8_t *)framebuffer1, 18000,NULL);testimg1.data = (const uint8_t *)framebuffer1;lv_img_set_src(homonoryimg, &testimg1);lv_obj_align(homonoryimg, NULL, LV_ALIGN_CENTER, 0, 0);lv_task_handler();offset += 18004;fs_res = lv_fs_seek(&lv_file, offset);osDelay(20);}执行完一次 for 循环后,回收资源,延时 1s 继续播放动画:lv_mem_free(framebuffer1);framebuffer1 = NULL;lv_fs_close(&lv_file);osDelay(1000);逻辑代码编写完成,编译下载:三、实验现象显示如开头的动画四、项目源码1. Github 下载源码:链接
  • [技术干货] 小熊派LiteOS移植LVGL
    小熊派LiteOS移植LVGL 一、移植前言 二、配置 TFT 三、LVGL 源码获取 四、显示接口移植 五、Demo 代码 六、实验现象 小熊派LiteOS移植LVGL一、移植前言之前使用小熊派实现了鸿蒙动画的开机界面,具体使用的技术栈为 STM32 + LiteOS + LVGL + FATFS +DMA 方式实现,刷新效率非常高,预览视频如下:关于这个的实现过程我会写一系列的教程分享出来,主要分为下面几个部分,本节为第二部分,基于 LiteOS 移植 LVGL 显示接口• 小熊派移植华为 LiteOS-M(基于MDK):链接 ;• 小熊派基于 LiteOS 移植 LVGL 显示接口:链接 ;• 小熊派基于 LiteOS 移植 LVGL 文件系统:链接 ;• 小熊派实现鸿蒙开机界面(LiteOS+LVGL):链接 ;本节的教程就是先通过 STM32CubeMX 来配置 小熊派的 TFT 初始化代码,开启 DMA 加速(不开启会卡出翔),配置完成后获取 LVGL 的代码,移植到工程里面,然后将 TFT 驱动接口和 LVGL 接口对接,在运行 Demo 代码 二、配置 TFT我们在上一节移植好 LiteOS 工程的基础上使用 CubeMX 配置 TFT 的 SPI 接口,具体 SPI 驱动接口可以参考这篇文章:小熊派 FreeRTOS+SPI+DMA 驱动 TFT-LCD SPI 配置完成如下:开启 DMA,并且在 NVIC 里面使能中断除了上面的 SPI 引脚还需要,配置 TFT 的其他控制引脚,关于引脚在参考文章中有写出来,配置完成如下:在 MDK 工程根目录下创建 Hardware/LCD 文件夹用来存放驱动代码,驱动文件命名为 lcd.c 和 lcd.h拷贝下面的代码进去lcd.c #include "lcd.h"#include "gpio.h"#include "spi.h"#include "cmsis_os.h"extern osSemaphoreId_t DMA_SemaphoreHandle;/* USER CODE BEGIN 1 *//*** @brief SPI 发送字节函数* @param TxData 要发送的数据* @param size 发送数据的字节大小* @return 0:写入成功,其他:写入失败*/uint8_t SPI_WriteByte(uint8_t *TxData,uint16_t size){osStatus_t result;//获取信号,如果上一个DMA传输完成//信号就能获取到,没有传输完成任务就挂起//等到传输完成再恢复result = osSemaphoreAcquire(DMA_SemaphoreHandle,0xFFFF);if(result == osOK){//获取成功return HAL_SPI_Transmit_DMA(&hspi2,TxData,size);}else{//获取失败return 1;}}//DMA 传输完成后会调用 SPI传输完成回调函数//在该函数中我们释放信号void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi){if(hspi->Instance == hspi2.Instance)osSemaphoreRelease(DMA_SemaphoreHandle);}/*** @brief 写命令到LCD* @param cmd —— 需要发送的命令* @return none*/static void LCD_Write_Cmd(uint8_t cmd){LCD_WR_RS(0);SPI_WriteByte(&cmd, 1);}/*** @brief 写数据到LCD* @param dat —— 需要发送的数据* @return none*/static void LCD_Write_Data(uint8_t dat){LCD_WR_RS(1);SPI_WriteByte(&dat, 1);}/*** @breif 打开LCD显示背光* @param none* @return none*/void LCD_DisplayOn(void){LCD_PWR(1);}/*** @brief 关闭LCD显示背光* @param none* @return none*/void LCD_DisplayOff(void){LCD_PWR(0);}/*** @brief 设置数据写入LCD显存区域* @param x1,y1 —— 起点坐标* @param x2,y2 —— 终点坐标* @return none*/void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2){/* 指定X方向操作区域 */LCD_Write_Cmd(0x2a);LCD_Write_Data(x1 >> 8);LCD_Write_Data(x1);LCD_Write_Data(x2 >> 8);LCD_Write_Data(x2);/* 指定Y方向操作区域 */LCD_Write_Cmd(0x2b);LCD_Write_Data(y1 >> 8);LCD_Write_Data(y1);LCD_Write_Data(y2 >> 8);LCD_Write_Data(y2);/* 发送该命令,LCD开始等待接收显存数据 */LCD_Write_Cmd(0x2C);}/*** @brief 以一种颜色清空LCD屏* @param color —— 清屏颜色(16bit)* @return none*/void LCD_Clear(uint16_t color){uint16_t i;uint8_t data[2] = {0}; //color是16bit的,每个像素点需要两个字节的显存/* 将16bit的color值分开为两个单独的字节 */data[0] = color >> 8;data[1] = color;LCD_Address_Set(0, 0, LCD_Width - 1, LCD_Height - 1);LCD_WR_RS(1);for(i=0;i<((LCD_Width)*(LCD_Height));i++){SPI_WriteByte(data, 2);}}/*** @brief LCD初始化* @param none* @return none*/void LCD_Init(void){/* 复位LCD */LCD_PWR(0);LCD_RST(0);osDelay(100);LCD_RST(1);osDelay(120);/* 关闭睡眠模式 */LCD_Write_Cmd(0x11);osDelay(120);/* 开始设置显存扫描模式,数据格式等 */LCD_Write_Cmd(0x36);LCD_Write_Data(0x00);/* RGB 5-6-5-bit格式 */LCD_Write_Cmd(0x3A);LCD_Write_Data(0x65);/* porch 设置 */LCD_Write_Cmd(0xB2);LCD_Write_Data(0x0C);LCD_Write_Data(0x0C);LCD_Write_Data(0x00);LCD_Write_Data(0x33);LCD_Write_Data(0x33);/* VGH设置 */LCD_Write_Cmd(0xB7);LCD_Write_Data(0x72);/* VCOM 设置 */LCD_Write_Cmd(0xBB);LCD_Write_Data(0x3D);/* LCM 设置 */LCD_Write_Cmd(0xC0);LCD_Write_Data(0x2C);/* VDV and VRH 设置 */LCD_Write_Cmd(0xC2);LCD_Write_Data(0x01);/* VRH 设置 */LCD_Write_Cmd(0xC3);LCD_Write_Data(0x19);/* VDV 设置 */LCD_Write_Cmd(0xC4);LCD_Write_Data(0x20);/* 普通模式下显存速率设置 60Mhz */LCD_Write_Cmd(0xC6);LCD_Write_Data(0x0F);/* 电源控制 */LCD_Write_Cmd(0xD0);LCD_Write_Data(0xA4);LCD_Write_Data(0xA1);/* 电压设置 */LCD_Write_Cmd(0xE0);LCD_Write_Data(0xD0);LCD_Write_Data(0x04);LCD_Write_Data(0x0D);LCD_Write_Data(0x11);LCD_Write_Data(0x13);LCD_Write_Data(0x2B);LCD_Write_Data(0x3F);LCD_Write_Data(0x54);LCD_Write_Data(0x4C);LCD_Write_Data(0x18);LCD_Write_Data(0x0D);LCD_Write_Data(0x0B);LCD_Write_Data(0x1F);LCD_Write_Data(0x23);/* 电压设置 */LCD_Write_Cmd(0xE1);LCD_Write_Data(0xD0);LCD_Write_Data(0x04);LCD_Write_Data(0x0C);LCD_Write_Data(0x11);LCD_Write_Data(0x13);LCD_Write_Data(0x2C);LCD_Write_Data(0x3F);LCD_Write_Data(0x44);LCD_Write_Data(0x51);LCD_Write_Data(0x2F);LCD_Write_Data(0x1F);LCD_Write_Data(0x1F);LCD_Write_Data(0x20);LCD_Write_Data(0x23);/* 显示开 */LCD_Write_Cmd(0x21);LCD_Write_Cmd(0x29);/*打开显示*/LCD_PWR(1);}lcd.h#include "main.h"#define LCD_PWR(n) (n?\HAL_GPIO_WritePin(LCD_PWR_GPIO_Port,LCD_PWR_Pin,GPIO_PIN_SET):\HAL_GPIO_WritePin(LCD_PWR_GPIO_Port,LCD_PWR_Pin,GPIO_PIN_RESET))#define LCD_WR_RS(n) (n?\HAL_GPIO_WritePin(LCD_WR_RS_GPIO_Port,LCD_WR_RS_Pin,GPIO_PIN_SET):\HAL_GPIO_WritePin(LCD_WR_RS_GPIO_Port,LCD_WR_RS_Pin,GPIO_PIN_RESET))#define LCD_RST(n) (n?\HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin,GPIO_PIN_SET):\HAL_GPIO_WritePin(LCD_RST_GPIO_Port,LCD_RST_Pin,GPIO_PIN_RESET))//LCD屏幕分辨率定义#define LCD_Width 240#define LCD_Height 240//颜色定义#define WHITE 0xFFFF //白色#define YELLOW 0xFFE0 //黄色#define BRRED 0XFC07 //棕红色#define PINK 0XF81F //粉色#define RED 0xF800 //红色#define BROWN 0XBC40 //棕色#define GRAY 0X8430 //灰色#define GBLUE 0X07FF //兰色#define GREEN 0x07E0 //绿色#define BLUE 0x001F //蓝色#define BLACK 0x0000 //黑色uint8_t SPI_WriteByte(uint8_t *TxData,uint16_t size);static void LCD_Write_Cmd(uint8_t cmd);static void LCD_Write_Data(uint8_t dat);void LCD_DisplayOn(void);void LCD_DisplayOff(void);void LCD_Address_Set(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);void LCD_Clear(uint16_t color);void LCD_Init(void);代码和文件添加完成后不要忘记添加文件路径,然后我们在主函数中创建一个用于 lcd 显示的任务,初始化 LCD 同时将屏幕初始化为蓝色osThreadId_t lcd_taskHandle;const osThreadAttr_t lcd_task_attributes = {.name = "lcd_task",.stack_size = 512 * 4,.priority = (osPriority_t) osPriorityNormal1,};void Lcd_Task(void *argument);void Lcd_Task(void *argument){LCD_Init();LCD_Clear(BLUE);while(1){osDelay(1000);}}添加 DMA 信号量osSemaphoreId_t DMA_SemaphoreHandle;const osSemaphoreAttr_t DMA_Semaphore_attributes = {.name = "DMA_Semaphore"};初始化信号和 LiteOS:/* USER CODE BEGIN 2 */osKernelInitialize();/* creation of uart_task */DMA_SemaphoreHandle = osSemaphoreNew(1, 1, &DMA_Semaphore_attributes);led_taskHandle = osThreadNew(Led_Task, NULL, &led_task_attributes);lcd_taskHandle = osThreadNew(Lcd_Task, NULL, &lcd_task_attributes);osKernelStart();/* USER CODE END 2 */编译烧写程序,观察现象,屏幕清屏为蓝色,驱动程序跑通了,可以进行下一步:三、LVGL 源码获取获取 lvgl 7.0 版本的源码git clone -b release/v7 https://github.com/lvgl/lvgl.git拉取后代码下面我们在 MDK 工程目录按照下面的格式建立文件夹APP 文件夹用来存放我们编写的 lvgl 应用代码,LVGL 文件夹用来存放 lvgl 的源码,以及接口代码然后我们将刚刚 github 下载的源码拷贝到 LVGL 中,然后把里面 lvgl\examples\porting 文件夹复制到同一目录下,改名为 lvgl_port 文件夹,同时将 lvgl\lv_conf_template.h 也复制到同一目录,并且改名为 lv_conf.h,修改结果如下:然后将 lvgl_port 下面的文件也修改名称为下面的格式:这6个文件是 lvgl 的接口文件,disp 是显示接口、fs 是文件系统接口、indev 是输入接口,下面我们在 MDK 工程里面添加文件和文件路径,添加路径如下:..\Middlewares\LVGL\APP..\Middlewares\LVGL\LVGL\lvgl_port..\Middlewares\LVGL\LVGL\lvgl\src添加文件如下:src 放的文件是下面文件夹的所有 c 文件config 放的是 lvgl 配置头文件:port 放的是 lvgl 的硬件接口文件文件添加完成后我们先配置 lvgl 下的 lv_conf.h 文件,做一些配置,不然直接编译的话会有一堆报错lv_conf.h 文件修改:修改屏幕尺寸适配小熊派:/* Maximal horizontal and vertical resolution to support by the library.*/#define LV_HOR_RES_MAX (240)#define LV_VER_RES_MAX (240)设置屏幕颜色深度,以及颜色存放格式(适配 ST7789芯片):/* Color depth:* - 1: 1 byte per pixel* - 8: RGB332* - 16: RGB565* - 32: ARGB8888*/#define LV_COLOR_DEPTH 16/* Swap the 2 bytes of RGB565 color.* Useful if the display has a 8 bit interface (e.g. SPI)*/#define LV_COLOR_16_SWAP 1设置调节界面缩放比例:/* Dot Per Inch: used to initialize default sizes.* E.g. a button with width = LV_DPI / 2 -> half inch wide* (Not so important, you can adjust it to modify default sizes and spaces)*/#define LV_DPI 60 /*[px]*/设置动态内存大小:/* Size of the memory used by `lv_mem_alloc` in bytes (>= 2kB)*/# define LV_MEM_SIZE (16U * 1024U)关闭使用 GPU:/* 1: Enable GPU interface*/#define LV_USE_GPU 0 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */#define LV_USE_GPU_STM32_DMA2D 0暂时先关闭文件系统:/* 1: Enable file system (might be required for images */#define LV_USE_FILESYSTEM 0编译一下,有一些警告..\Middlewares\LVGL\LVGL\lvgl\src\lv_draw\lv_draw_mask.c(350): warning: #111-D: statement is unreachable这些警告没有任何影响,可以把警告给屏蔽掉,切换到 C/C++选项卡,在 Misc Controls 中填入--diag_suppress=111 把它屏蔽掉如下图所示:编译后改报错就不显示了四、显示接口移植编译通过后,我们下一步就是修改显示接口了,打开 lv_port_disp.c 文件,将开头使能,包括头文件也使能:/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/#if 1修改显示接口,主要关注 void lv_port_disp_init(void) 函数void lv_port_disp_init(void){/*-------------------------* Initialize your display* -----------------------*/disp_init();/*-----------------------------* Create a buffer for drawing*----------------------------*//* LVGL requires a buffer where it internally draws the widgets.* Later this buffer will passed your display drivers `flush_cb` to copy its content to your display.* The buffer has to be greater than 1 display row** There are three buffering configurations:* 1. Create ONE buffer with some rows:* LVGL will draw the display's content here and writes it to your display** 2. Create TWO buffer with some rows:* LVGL will draw the display's content to a buffer and writes it your display.* You should use DMA to write the buffer's content to the display.* It will enable LVGL to draw the next part of the screen to the other buffer while* the data is being sent form the first buffer. It makes rendering and flushing parallel.** 3. Create TWO screen-sized buffer:* Similar to 2) but the buffer have to be screen sized. When LVGL is ready it will give the* whole frame to display. This way you only need to change the frame buffer's address instead of* copying the pixels.* *//* Example for 1) */static lv_disp_buf_t draw_buf_dsc_1;static lv_color_t draw_buf_1[LV_HOR_RES_MAX * 10]; /*A buffer for 10 rows*/lv_disp_buf_init(&draw_buf_dsc_1, draw_buf_1, NULL, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*//* Example for 2) */static lv_disp_buf_t draw_buf_dsc_2;static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10]; /*A buffer for 10 rows*/static lv_color_t draw_buf_2_2[LV_HOR_RES_MAX * 10]; /*An other buffer for 10 rows*/lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_2, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*//* Example for 3) */static lv_disp_buf_t draw_buf_dsc_3;static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*A screen sized buffer*/static lv_color_t draw_buf_3_2[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*An other screen sized buffer*/lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*//*-----------------------------------* Register the display in LVGL*----------------------------------*/lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/lv_disp_drv_init(&disp_drv); /*Basic initialization*//*Set up the functions to access to your display*//*Set the resolution of the display*/disp_drv.hor_res = 480;disp_drv.ver_res = 320;/*Used to copy the buffer's content to the display*/disp_drv.flush_cb = disp_flush;/*Set a display buffer*/disp_drv.buffer = &draw_buf_dsc_1;#if LV_USE_GPU/*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*//*Blend two color array using opacity*/disp_drv.gpu_blend_cb = gpu_blend;/*Fill a memory array with a color*/disp_drv.gpu_fill_cb = gpu_fill;#endif/*Finally register the driver*/lv_disp_drv_register(&disp_drv);}disp_init() 用来初始化显示屏外设,这里我们在hal初始化中已经初始化完成了,所以删除他下面的代码就是创建一个缓存 buffer,这里 LVGL 提供了三种方式创建缓存:第一种只创建一个缓存区,长度是横轴像素长度的 10 倍,第二种创建两个缓存区,长度都是 横轴的 10 倍,第三种则是创建两个,大小是横轴乘以纵轴,相当于整个屏幕大小,第一种情况,如果我们在写入数据时不能修改,第二种我们在写入一个 buffer 时还可以希尔另外一个 buffer ,可以结合 DMA 加快写入速度,这里我使用第一种下面的代码注册显示驱动,配置其参数:主要就是配置屏幕参数,设置刷新函数,配置缓存区指针,最后注册驱动,这里我们要修改一下刷新屏幕函数static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)修改如下:/* Flush the content of the internal buffer the specific area on the display* You can use DMA or any hardware acceleration to do this operation in the background but* 'lv_disp_flush_ready()' has to be called when finished. */static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p){/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/int32_t y;LCD_Address_Set(area->x1,area->y1,area->x2,area->y2);LCD_WR_RS(1);//一行一行 DMAfor(y = area->y1; y <= area->y2; y++) {if(osSemaphoreAcquire(DMA_SemaphoreHandle,0xFFFF) == osOK)HAL_SPI_Transmit_DMA(&hspi2,(uint8_t *)color_p,(uint16_t)(area->x2-area->x1+1)*2);color_p += (area->x2-area->x1+1);}/* IMPORTANT!!!* Inform the graphics library that you are ready with the flushing*/lv_disp_flush_ready(disp_drv);}修改代码后,要添加头文件和 dma 信号量声明/********************** INCLUDES*********************/#include "lv_port_disp.h"#include "lcd.h"#include "spi.h"#include "cmsis_os.h"/********************** DEFINES*********************/extern osSemaphoreId_t DMA_SemaphoreHandle;五、Demo 代码在定时器 1 中断中添加 lvgl 的时基更新代码void TIM1_UP_TIM16_IRQHandler(void){/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 0 *//* USER CODE END TIM1_UP_TIM16_IRQn 0 */HAL_TIM_IRQHandler(&htim1);/* USER CODE BEGIN TIM1_UP_TIM16_IRQn 1 */lv_tick_inc(1);/* USER CODE END TIM1_UP_TIM16_IRQn 1 */}在 main.c 的 lcd 任务中添加创建 label 测试的代码这里的测试代码是画两个对角位置的方块,边框颜色都不一样,一个设置的是蓝色,一个是绿色void Lcd_Task(void *argument){LCD_Init();lv_init();lv_port_disp_init();//lvgl 显示接口初始化,放在 lv_init()的后面lv_style_t style1;lv_style_init(&style1);lv_style_set_bg_color(&style1, LV_STATE_DEFAULT,LV_COLOR_BLACK);lv_style_set_border_width(&style1,LV_STATE_DEFAULT, 5);lv_style_set_border_color(&style1,LV_STATE_DEFAULT, LV_COLOR_BLUE);lv_style_t style2;lv_style_init(&style2);lv_style_set_bg_color(&style2, LV_STATE_DEFAULT,LV_COLOR_BLACK);lv_style_set_border_width(&style2,LV_STATE_DEFAULT, 5);lv_style_set_border_color(&style2,LV_STATE_DEFAULT, LV_COLOR_GREEN);lv_obj_t* bgk1 = lv_obj_create(lv_scr_act(), NULL);//创建对象lv_obj_set_pos(bgk1,0,0);lv_obj_set_size(bgk1, 120, 120);//设置覆盖大小lv_obj_add_style(bgk1,LV_STATE_DEFAULT, &style1);lv_obj_t* bgk2 = lv_obj_create(lv_scr_act(), NULL);//创建对象lv_obj_set_pos(bgk2,120,120);lv_obj_set_size(bgk2, 120, 120);//设置覆盖大小 lv_obj_add_style(bgk2,LV_STATE_DEFAULT, &style2);while(1){lv_task_handler();osDelay(1000);}}/* USER CODE END 0 */记得添加相关头文件:/* USER CODE BEGIN Includes */#include "cmsis_os.h"#include "lcd.h"#include "lv_port_disp.h"/* USER CODE END Includes */编译下载代码六、实验现象两个对角小方块,边框一个蓝色一个绿色
  • [技术干货] 小熊派移植 LiteOS-M(MDK)
    小熊派移植鸿蒙 LiteOS-M(MDK)一、软硬件介绍1.1 小熊派开发板开发板外貌:小熊派参数如下:1.2 LiteOS介绍LiteOS 是华为面向物联网领域开发的一个基于实时内核的轻量级操作系统。属于华为物联网操作系统 Huawei LiteOS 源码,鸿蒙体系的内核之一,本质上就是一个 RTOS,现有基础内核支持任务管理、内存管理、时间管理、通信机制、中断管理、队列管理、事件管理、定时器等操作系统基础组件,更好地支持低功耗场景,支持tickless机制,支持定时器对齐同时 LiteOS 提供端云协同能力,集成了 LwM2M、CoAP、mbedtls、LwIP 全套 IoT 互联协议栈,且在 LwM2M 的基础上,提供了 AgentTiny 模块,用户只需关注自身的应用,而不必关注 LwM2M 实现细节,直接使用 AgentTiny 封装的接口即可简单快速实现与云平台安全可靠的连接1.3 移植前言LiteOS 软件开发框架按照下面的框架来进行,其中 LiteOS调度内核我们移植官方提供的代码即可,而 BSP 外设软件库我们则通过 STM32CubeMX 来配置生成 HAL 库,当这两方面准备好之后,我们只需要在任务层进行开发即可,开发效率极高LiteOS 的移植一般也分为两种移植方法,一种移植的时候将芯片的中断也关联到 LiteOS 方便调用,另外一种则不关联中断,使用单片机自己的中断管理,这里 STM32 的 NVIC 中断管理很棒,我们不需要接管中断二、CubeMX 配置我们通过 STM32CubeMX 来配置小熊派的一些基本接口,比如配置时钟树,开启 SystemTick定时器,方便移植 LiteOS 配置时钟树:设置 HAL库定时器为TIM1,防止和 LiteOS 使用的 Systemtick 冲突配置 LED 的 GPIO 口,方便我们点灯操作配置工程名称,选择生成 MDK配置代码生成选项生成代码代码生成后打开工程,下一步进入移植操作三、获取源码LiteOS 的老版本有对 MDK 的支持,新版本暂时还没有更新,所以这里我使用老版本的代码,仓库地址如下:Github 仓库 我们把老版本的仓库 Down 到本地,Git 指令如下:git clone -b develop https://github.com/LiteOS/LiteOS.git代码拉取后如下:没有 Git 工具的话可以上 GitHub 网页把 ZIP Downloade 下来再解压也可以下面就是代码移植阶段四、源码移植在 MDK 工程目录下新建 LiteOS 移植目录,按如下新建文件夹这几个文件夹的作用如下:• ARCH:编译器启动文件• CMSIS:存放 CMSIS-RTOS 接口文件• Config:存放内核配置文件,用于配置和裁剪内核• Kernel:存放 LiteOS 内核源码下面我们从源码文件夹拷贝代码到移植目录下面4.1 ARCH移植 文件路径\LiteOS\arch\arm 架构文件夹到 ARCH 下,arm 下文件包含了各个 arm 架构的支持文件M 架构下面的文件主要有三个 GCC、IAR、KEIL 三个,适配不同集成开发环境的编译器,因为小熊派是 M4 内核,所以我们主要关注的就是 cortex-m4 下面的 keil 文件夹下的启动文件,这里我把所有的都复制进去了至于 include 和 src 文件夹,则是存放了 LiteOS 的一些内核接口代码,比如中断接口、Systemtick 定时器接口函数等等4.2 CMSIS移植 文件路径\LiteOS\LiteOS-M-Develop\LiteOS\osdepends\liteos\cmsis CMSIS 系统接口文件夹到 CMSIS 下,CMSIS 文件夹下存放的是 CMSIS-RTOS 接口文件夹,RTOS内核支持的操作就那么些,CMSIS-RTOS 对这些操作提供了统一的 RTOS 接口,连接系统底层与 RTOS层,方便我们移植不同的 RTOS:4.3 ConfigConfig 文件夹下存放系统的配置文件,这个配置文件我们从示例工程下面拷过来,示例工程目录位置 目录\LiteOS\targets\STM32F103VET6_NB_GCC\OS_CONFIG,目录下文件如下:其中 los_builddef.h 用于设置构建的定义,los_printf.h 用于设置串口打印配置,target_config.h 可以用于裁剪系统内核,设置系统运行参数等等4.4 Kernelkernel 文件夹用于存放内核源码,源码位置在 目录\LiteOS\kernel 下面base 是系统的基础内核源码• core 是核心源码,包括队列、task调度、软timer、时间片计算等功能,全部复制• OM 是与错误处理相关的文件,全部复制• include 是 LiteOS内 核内部使用的头文件,全部复制• ipc 是 LiteOS 中 task 间通讯的相关接口,包括事件、信号量、消息队列、互斥锁等,全部复制• mem 是LiteOS中的内核内存管理的相关代码,我们只需要复制其中一部分就行,内存分配方式选择适合小内存的分配方式(bestfit_little)• misc 是内存对齐功能以及毫秒级休眠sleep功能,全部复制extended 是系统扩展内核的代码,目前里面有个支持低功耗的内核,我们顺便也复制进去include 存放内核的调用头文件,我们全部复制进去kernel 下面还有一个 los_init.c 文件,存放初始化代码,也复制进去复制完成的文件夹如下:五、MDK 配置代码移植完成了,下面就是配置一下 MDK5.1 文件导入进入 MDK 进行文件管理,配置文件夹,导入文件:• config 导入 Config 下面 所有 .h 文件• kernel 导入 Kernel 下面 所有 .c 文件• cmsis 导入 CMSIS 下 cmsis_liteos.c 文件• arch 导入 ARCH\arm\arm-m\cortex-m4\keil 下 los_dispatch_keil.S文件,以及 ARCH\arm\arm-m\src 下 所有 .c 文件5.2 路径导入文件导入后下一步就是路径导入,在 C/C++ 配置中依次添加头文件路径添加的路径如下,这里我的工程目录是 BearPi_LiteOS:BearPi_LiteOS\Middlewares\LiteOS\ConfigBearPi_LiteOS\Middlewares\LiteOS\Kernel\base\includeBearPi_LiteOS\Middlewares\LiteOS\Kernel\extended\includeBearPi_LiteOS\Middlewares\LiteOS\Kernel\includeBearPi_LiteOS\Middlewares\LiteOS\ARCH\arm\arm-m\includeBearPi_LiteOS\Middlewares\LiteOS\CMSIS\cmsis到这基本差不多了,下面就是编译工程5.3 编译工程先编译一下工程,发现报错,缺少 #include "stm32f1xx.h" 文件,是因为我的小熊派开发板是 stm32l431 的芯片,修改这个工程头文件为 #include "stm32l4xx.h"修改完再编译,当然还会有报错,因为 STM32CubeMX 生成的代码里面有 void PendSV_Handler(void)void SysTick_Handler(void)两个中断,这两个中断在 LiteOS 的内核源码里面有定义,一个用作系统时钟,一个用作上下文切换,所以我们要把 STM32CubeMX 生成的这部分中断处理代码注释掉注释完后编译,编译通过:到此系统移植基本完成了,下一步写个代码测试系统有没有移植成功六、点灯实验头文件包含 cmsis 接口/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes */#include "cmsis_os.h"/* USER CODE END Includes */创建一个任务句柄,以及任务实体和初始化函数osThreadId_t led_taskHandle;const osThreadAttr_t led_task_attributes = {.name = "led_task",.stack_size = 512 * 4,.priority = (osPriority_t) osPriorityNormal,};void Led_Task(void *argument);void Led_Task(void *argument){while(1){HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);osDelay(1000);}}在系统初始化的代码添加系统初始化代码,同时创建任务,创建完成后启动系统/* USER CODE BEGIN 2 */osKernelInitialize();/* creation of uart_task */led_taskHandle = osThreadNew(Led_Task, NULL, &led_task_attributes);osKernelStart();/* USER CODE END 2 */编译下载程序,观察现象:
  • [技术干货] 关于liteOS串口通信问题
    今天使用liteOS进行串口数据通信,主要是通过UART2连接外部设备进行数据通信发现以下问题,uart1在liteos中是默认就初始化的,且不能为之配置中断回调函数,亲测一向uart发送数据程序就会卡死,并且使用Transmit之类的函数,也不会打印数据,只能使用printf坑啊uart2串口就很uart1不同了,我一上午都在抓头发苦想uart2为啥接收不到数据,直到晚上,发现在初始化的时候liteos并没有初始化uart2坑啊uart2可以使用HAL库中的函数进行数据通信,不受影响我的发送数据的函数是这个,直接操纵寄存器即,当然也可以使用HAL_UART_Trainsmit来发送数据//串口发送一个字节static void MYUSART_SendData(uint8_t data){    while((USART2->ISR&0X40)==0);     USART2->TDR = data;}接收数据使用这个,没有写在中断函数里面HAL_UART_Receive(&huart2,(uint8_t *)USART2_RX_BUF,USART2_MAX_RECV_LEN,500);//接收数据我的开发方式比较特殊,发送数据之后立马读取数据,所以没写在中断,虽然我配置了中断,也写了中断回调函数但是我把回调函数注释了,发现还可以运行,奇怪的知识又增加了!!!if (huart->Instance == USART2)// {// // HAL_UART_Receive_IT(&huart2, USART2_RX_BUF, sizeof(USART2_RX_BUF)); //????????// }这是中断回调函数甚至,我不配置中断,也可以运行,真是离谱他妈给离谱开门。。。总结在liteOS中,尽量不要为串口添加中断中断配置文件里都有了,在代码里使能串口就了发送数据可正常使用HAL库或标准库接收数据如果不是太多或者不及时处理的,尽量不要用中断接收最后讲讲我的开发开发环境:iot studio +mdk v5+STM32L431RCT6小熊派开发板+AS608指纹识别模块+liteOS目前已成功修改as608驱动代码,实现了与指纹模块的握手通信,使用的是HAL库如果有类似我这种开发问题的,可以在帖子下留言,问题+需求+邮箱,源代码等我会通过邮箱发送也可以私信我邮箱Njthdsj@163.com,描述您的问题需求,我会尽可能帮助您
  • [知识分享] 一起玩转LiteOS组件:Pixman
    摘要:本文将以Pixman Demo为例,详细说明Pixman的功能。本文分享自华为云社区《LiteOS组件尝鲜—玩转Pixman》,作者:Lionlace。基本介绍Pixman是由三星工程师开发的像素操作库,广泛应用于矢量图形Cario和X服务器等。它能够提供低级像素处理能力,同时具备图像合成、图形变化以及光栅化等功能。本文将以Pixman Demo为例,详细说明Pixman的功能。该Demo实现功能的步骤:新建一个宽高为20*20的像素图片,将目标图片划分为4个10*10的区域。第一个区域填充蓝色,第二个区域填充蓝粉渐变色,第三个区域填充径向渐变色,第四个区域填充圆形渐变色,最后输出图形到pixman.png即可。下面将介绍详细步骤。Demo实现的环境要求Demo需要FATFS文件系统和LIBPNG支持,可在已支持该文件系统的开发板上运行,目前已适配STM32F769IDISCOVERY开发板。使能Pixman Demo拷贝并重命名配置文件在LiteOS源码根目录下根据实际使用的开发板,拷贝tools/build/config/目录下的默认配置文件${platform}.config到根目录,并重命名为.config。以Linux系统和STM32F769IDISCOVERY开发板为例,在LiteOS源码目录下,执行如下命令完成配置文件的拷贝和重命名:cp tools/build/config/STM32F769IDISCOVERY.config .config使能Pixman Demo在LiteOS源码根目录下运行make menuconfig命令,按如下菜单路径使能Pixman Demo:Demos ---> Media Demo ---> [*] Enable Pixman Demo (NEW)使能Pixman Demo后,会自动使能其依赖的Pixman组件、Libpng组件及FATFS文件系统并设置SD卡模式。本Demo中的文件就保存在SD卡中。保存退出menuconfig后,LiteOS会从github上自动下载Pixman源代码,并从gitee的LiteOS组件仓库LiteOS_Components下载对应的patch包,并打入patch。关于组件下载的详细流程请参考:https://gitee.com/LiteOS/LiteOS_Components#%E5%9C%A8%E7%BA%BF%E7%BB%84%E4%BB%B6%E4%B8%8B%E8%BD%BD%E6%B5%81%E7%A8%8B注:下载需要Linux主机可以访问互联网,并安装git工具。如果使用LiteOS Studio使能该Demo,需要在组件配置中手动设置FATFS文件系统为SD卡模式。编译运行Pixman Demo操作步骤如下:将SD卡插入开发板的卡槽内;参照上述步骤使能Pixman Demo;在LiteOS源码目录下执行make clean ; make -j命令编译LiteOS工程,编译成功后将在out/${platform}/lib目录下生成Pixman的库文件libpixman.a,Libpng的库文件libpng.a和本Demo的库文件libpixman_demo.a,系统镜像文件为Huawei_LiteOS.bin。以STM32F769IDISCOVERY开发板为例,其目录就是out/STM32F769IDISCOVERY;烧录系统镜像文件到开发板,复位后可以看到串口输出Demo运行结果如下所示。********Hello Huawei LiteOS******** LiteOS Kernel Version : 5.0.0 build data : May 14 2021 16:05:30 ********************************** osAppInit cpu 0 entering scheduler app init! Hello, welcome to liteos demo! File system mount success. Pixman demo task start to run. Pixman demo task finished. Huawei LiteOS #查看SD卡根目录,可以看到生成的图片文件为pixman.png。至此,该Demo实现功能就完成了。想了解更多LiteOS组件可点击话题"LiteOS组件介绍”查看。结语未来我们还会持续新增更多组件、开发板、架构、特性等。感谢您的阅读,有任何问题、建议,都可以留言给我们,让我们一起进步:https://gitee.com/LiteOS/LiteOS/issues。为了更容易找到“LiteOS”代码仓,建议访问https://gitee.com/LiteOS/LiteOS,关注“ Watch”、点赞“Star”、并“Fork”到自己账号下,如图所示。- end –
  • [技术干货] 关于liteOS接管外接中断
    开发环境:开发环境比较古老此版本有很多例子可以供我们魔改,我主要是看重此版本例程中集成了AT框架,可以驱动ESP8266wifi模块由于需要使用到AT框架,所以我不得不使用LiteOS,那我就根据例程魔改言归正传,咱们来谈谈中断接管,关于中断接管相信搜索到本教程的都已经了解了,我们来谈谈如何实相关图片在本文末尾:1.我的sdk比较古老IoT_LINK_1.0.0,没法谁让人家有AT指令架构呢,不过版本不是本文重点2.想要使用中断接管,那就要在OS_CONFIG/target_config.h文件夹中设置一个宏定义#define LOSCFG_PLATFORM_HWI          YES3.接下来就可以开开心心的去写自己的代码啦   以用外部中断检测按键按键为例,在lite OS里面其实非常好实现
  • [问题求助] LIte OS使用外部中断接管,求教程
    求LIteOS中断接管的详细教程,越详细越好,在mdk中使用了STM32的中断,移植到LiteOS不知道咋弄,网上教程也少,跪求论坛各位大神了!
  • [问题求助] STM32移植 LiteOS中断配置为不接管中断编译失败
    【功能模块】使用STM32cube+MDK+小熊派开发板型号问STM32L431RC【操作步骤&问题现象】1、在MDK上使用STM32的外部中断,成功使用中断检测外部引脚电平变化2、想移植到LIteOS上,所以用iot_studio使用模板创建了个例程3、将代码移植到IOT—studio上发现中断运行不了,查找资料猜测是啥配置问题4、好不容易说配置为不接管中断,但配置之后编译失败麻烦大佬帮看看啊,跪求了!【截图信息】【日志信息】(可选,上传日志内容或者附件)
  • [技术干货] 完全在Linux下LiteOS开发方法
    前言:最近在学习liteos开发,首先按照官方的文档在windows系统的进行了开发环境的搭建工作,官方的开发环境实际上是用开源的VSCODE代码+一些自己开发的插件做的一个开发环境,其中的JLINK调试也是一个开源的插件。刚才始用着感觉还不错,不过后面就出现了很多问题,感觉不是很稳定。首先软件的Project Config这个界面经常不知道是什么原因,启动不成功。二是Board中没有自己的开发板,如果在里面加了自己的板子,编译时还不能自动更新.config文件。三是编译好的文件进入debug后,发现有的项目不能进入c文件的main函数,只能在汇编文件中仿真。在gitee上提了issul后,官方推荐在linux环境上进行开发。然后按照官方提供的方法在linux上进行了编译环境的搭建,然后再通过SUMBA的方式与windows电脑连接,在windows上通过vscode进行仿真和烧写。按照官方的方法,在linux上进行编译非常顺利,通过menuconfig进行板子配置也很成功,编译也没有问题,但是把编译好的文件导到windows电脑上进行仿真就出了很多问题。于是提出了想完全在linux上开发,仿真的想法。我采用的开发板是GD32F450I-EVAL,开发环境是ubuntu20.04,目前已经完成了liteos移植与lwip的适配。现在把我的一点经验分享给大家。一、环境搭建:Linux下编译环境搭建参考官方提供的方法。安装编译器&构建器1.1下载编译器。对于32位芯片架构,官方下载地址为:GNU Arm Embedded Toolchain编译器,建议使用2019-q4-major及以上版本。对于64位芯片架构,官方下载地址为:64位GNU Arm Embedded Toolchain编译器,建议使用最新版本的aarch64-linux-gnu编译器。1.2解压编译器。可以参考如下命令完成解压,将压缩包名替换为实际下载的软件包名:tar -xvf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2解压后可以得到文件夹gcc-arm-none-eabi-9-2019-q4-major。1.3添加编译器的执行路径到环境变量。以第二步解压的编译器为例,将gcc-arm-none-eabi-9-2019-q4-major/bin目录添加到环境变量中,可以编辑~/.bashrc文件,参考如下方法设置PATH环境变量:export PATH=$PATH:YOUR_PATH/gcc-arm-none-eabi-9-2019-q4-major/bin/然后执行以下命令使新设置的环境变量立即生效:source ~/.bashrc注意:因为的用的不是bash,我用的是oh-my-zsh,所的在修改环境变量时,我修改的文件是 ".zshrc",如果大家有类似情况,请注意2.升级GNU Make构建器到最新版。2.1因为ubuntu20.04的make版本是4.3,所有我没有升级,或者其它的版本也不升级应该也可以用。2.2安装python,pip,kconfiglib等都参考官方文档就可以。2.3编译环境搭建完成后就可以从gitee上clone代码,进行编译了,如果能编译成功,就说明没有问题,可以进行后面的工作了。3.仿真环境搭建3.1首先安装segger的jlink在segger官网https://www.segger.com/downloads/jlink/下载J-Link的linux版软件,我下载的版本是JLink_Linux_V760c_i386.deb,下载完后进行安装就可以。3.2测试JLINK在Linux上的使用:3.3烧写bin文件:打开terminal,并指定到要烧写的文件的位置,然后执行以下命令就可以完成烧写工作相关命令:JFlashExe Huawei_LiteOS.bin 0x8000000 烧写xxx.bin到指定位置,就可以烧写的板子中去。4.采用JlinkGDBServer进行仿真在terminal中输入JLinkGDBServer 启动JLinkGDBServer,此时会要求指定器件型号,按要求指定就可以。此时jlinkgdbserver就会启动。然后启动arm-none-eabi-gdb -tui(-tui是启动gui界面)target remote localhost:2331 (通过gdb连接jlinkgdbserver, jlinkgdbserver的端口号是2331),连接成功后就可以通过以下命令进行操作:monitor reset   对设备进行reset。file xxx.elf 进行仿真文件指定。load   烧写相应文件到设备。接下来就可以用gdb的一些命令进行仿真了。gdb的一些命令大家可以在网上找。就结束了么。???显然很多人对gdb的调试是很抗拒的,很多人用习惯了windows下方便的IDE,已经不愿意用这种功能强大但是比较费心的gdb进行调试了。下面介绍如何在linux下进行优雅的开发。5.安装clion,网址:https://www.jetbrains.com/clion/5.1 先介绍一下clion, CLion 2021一款适用于C和C ++的跨平台IDE,功能强大的智能编码辅助和代码分析软件,使用 CLion能够通过即时导航和可靠的重构来提升你的工作效率,强大的智能代码辅助,让你省时省力又省心,拥有只能编辑器来分析上下文,通过导航和搜索功能快速找到你需要的内容,非常实用的是能够实时现实出代码中存在的错误和可能出现风险的地方,方便大家快速修复,避免后期不必要的损失。5.2 之所以想到clion,是因为clion不像visual studio, IAR, MDK那样,需要严格的去建工程,它编译实际上是执行的cmake或make命令,只要我们的工程中有Makefile或CmakeList.txt文件,它就可以直接进行编译。也就是说我们从liteos上下载的代码,不用做任何修改,就可以直接用clion打开文件,进行编译。点那个小锤子就可以直接编译。当然也可以直接用clion下面的那个terminal输入命令进行编译。(我是习惯直接在下面输入命令进行编译,这里可以直接用make menuconfig, make -j12 ,maek clean等命令)5.2 仿真设置:clion中 run->Edit Configurations...,新建一个embedded gdb server.点左上角的加号,选择新建一个embedded gdb server,然后选中新建的项目,在右侧输入Name,Execulable(通过路径,指定要仿真的文件),target remote args:指定端口,按截图填写就行。GDB Server:指定gdb server执行文件所在的位置。一般安装好后在/bin下就有。GDB Server args:-select USB -device GD32F450IK -if SWD -speed 4000 -noir 指定连接方式,器件型号,速度等。设置好的,点ok,就完成。这时可以在clion的小锤子旁边,可以选择Huaei_LiteOS.elf了,这时设置好断点,点那个小虫子,就可以下载,并debug了。这里面可以方便的设置断点,运行,下一步,进入函数里面执行,跳出函数执行等功能,也可以方便查看变量,内存。其它的一些设置可以再自己摸索。注意:用clion进行仿真,软件并没有下烧写到0X8000000,而是往后面移动了一点,所以硬件断电后软件不能正常启动,这点我还没有去找解决的办法,现在简单想到的就是用JFlash命令支烧写软件就可以了。结束语:1.现在的问题是选择了huawi_liteos.elf后,就不能点编译的图标了,这是因为一些这个选项的命令没设置对,如果习惯用鼠标点,只要再选回之前的那个"all",就可以编译了。我现在习惯上是直接用clion自带的terinal进行编译,直接那里输入make -j12,或make menuconfig就可以。所以就没有再细抠这个问题。2.LiteOS目前感觉出的教程,书还是比较少,买了两本书,发现也没有对我的产生很实际的帮助,还是得靠自己去肯代码,希望今天分享这个能让大家更方便的使用liteos,也让更多有人用起来。
  • [问题求助] liteos-m如何查看系统内存占用情况(类似于linux下free等命令)
    【功能模块】  liteos-m如何查看系统内存占用情况(类似于linux下free等命令)【操作步骤&问题现象】1、liteos-m有办法获取自身运行时的内存占用状态吗?2、【截图信息】【日志信息】(可选,上传日志内容或者附件)
总条数:623 到第
上滑加载中