• [技术干货] 0x01 LiteOS_Lab仓库组件详解--AT(上)
    摘要:本节以解析UART.c文件中的代码为主,为了后面讲解AT框架及Driver框架做铺垫。关于串口的背景知识:https://bbs.huaweicloud.com/forum/thread-53612-1-1.html由于该文件中设计到了ring_buffer也就是环形数据结构的操作,你可以先阅读该篇文章,理解环形数据结构:https://bbs.huaweicloud.com/forum/thread-55254-1-1.html本节的代码摘自该文件:https://github.com/LiteOS/LiteOS_Lab/blob/iot_link/targets/STM32L431_BearPi/uart_at/uart_at.c下图中红框的地方是本节讲解的重点:auti_cb结构体struct atio_cb {     unsigned short        w_next;    //the next position to be write     osal_semp_t           rcvsync;   //if a frame has been written to the ring, then active it     tag_ring_buffer_t     rcvring; /*tag_ring_buffer_t结构体 typedef struct     {     unsigned char   *buf;      ///< which means the buffer     int              buflen;   ///< which means the buffer limit     int              datalen;  ///< which means how many data in the buffer     int              dataoff;  ///< which means the valid data offset in the buffer     }tag_ring_buffer_t;     */     unsigned char         rcvbuf[CONFIG_UARTAT_RCVMAX];     unsigned char         rcvringmem[CN_RCVMEM_LEN];     //for the debug here     unsigned int          rframeover; //how many times the frame has been over the max length     unsigned int          rframedrop; //how many frame has been droped for memmory     unsigned int          sndlen;     //how many bytes has been sent     unsigned int          rcvlen;     //how many bytes has been received    用于在中断中存储接收到了多少字节的数据     unsigned int          sndframe;   //how many frame has been sent     unsigned int          rcvframe;   //how many frame has been received     unsigned int          rcvringrst; //how many times the receive ring has been reset }; static struct atio_cb   g_atio_cb;初始化串口/******************************************************************************* function     :use this function to initialize the uart parameters   : instruction  : *******************************************************************************/ bool_t uart_at_init(void *pri) {     //initialize the at controller     (void) memset(&g_atio_cb,0,sizeof(g_atio_cb));    //为g_atio_cb结构体分配内存     if(false == osal_semp_create(&g_atio_cb.rcvsync,CN_RCVMEM_LEN,0))    //创建一个信号量     {         printf("%s:semp create error\n\r",__FUNCTION__);            //如果创建失败直接退出该函数并打印报错信息         goto EXIT_SEMP;     }     ring_buffer_init(&g_atio_cb.rcvring,g_atio_cb.rcvringmem,CN_RCVMEM_LEN,0,0);      /* ring_buffer_init(&g_atio_cb.rcvring,g_atio_cb.rcvringmem,CN_RCVMEM_LEN,0,0);函数的定义 int ring_buffer_init(tag_ring_buffer_t *ring,unsigned char *buf, int buflen,int offset,int datalen)     {         int ret = -1;         if((NULL == ring))         {         return ret;         }         ring->buf     = buf;    //将rcvringmem的地址与tag_ring_buffer_t类型的rcvring结构体中的buf指针进行绑定     ring->buflen  = buflen; //设置长度为用户定义的CN_RCVMEM_LEN        ring->datalen = datalen;//设置为0         ring->dataoff = offset; //设置为0       ret = 0;         return ret;     }     */ /* 初始化串口硬件相关,波特率、数据位、停止位以及校验位 */     uart_at.Instance = s_pUSART;     uart_at.Init.BaudRate = CONFIG_UARTAT_BAUDRATE;     uart_at.Init.WordLength = UART_WORDLENGTH_8B;     uart_at.Init.StopBits = UART_STOPBITS_1;     uart_at.Init.Parity = UART_PARITY_NONE;     uart_at.Init.HwFlowCtl = UART_HWCONTROL_NONE;     uart_at.Init.Mode = UART_MODE_TX_RX;     uart_at.Init.OverSampling = UART_OVERSAMPLING_16;     if(HAL_UART_Init(&uart_at) != HAL_OK)     {         _Error_Handler(__FILE__, __LINE__);     }     __HAL_UART_CLEAR_FLAG(&uart_at,UART_FLAG_TC);    //清除标志位     LOS_HwiCreate(s_uwIRQn, 3, 0, atio_irq, 0);  //通过LiteOS接管中断的方式创建中断,发生相应中断跳转到atio_irq函数处理     __HAL_UART_ENABLE_IT(&uart_at, UART_IT_IDLE);   //开启空闲中断:可以用该中断判断是否收到一帧数据(注意这里是一帧,不是一字节)     __HAL_UART_ENABLE_IT(&uart_at, UART_IT_RXNE);   //开启接收中断     return true; EXIT_SEMP:     return false; } void uart_at_deinit(void *pri) {     __HAL_UART_DISABLE(&uart_at);     __HAL_UART_DISABLE_IT(&uart_at, UART_IT_IDLE);     __HAL_UART_DISABLE_IT(&uart_at, UART_IT_RXNE); }串口中断处理函数/******************************************************************************* function     :use this function to deal the uart interrupt parameters   : instruction  :we cached the data in the temp buffer,when the idle interrupt reached,               then we write the data and the length to the ring if the ring has enough               space *******************************************************************************/ /* 当产生串口中断就跳转到该函数进行处理 */ static void atio_irq(void) {     unsigned char  value;     unsigned short ringspace;     if(__HAL_UART_GET_FLAG(&uart_at, UART_FLAG_RXNE) != RESET)    //如果是接收中断,代表收到了一字节数据     {        value = (uint8_t)(uart_at.Instance->RDR & 0x00FF);    //将数据从寄存器中读到value变量中        g_atio_cb.rcvlen++;                                        //结构体中的接收长度+1        if(g_atio_cb.w_next < CONFIG_UARTAT_RCVMAX)            //w_next如果小于最大接收长度则正常,反之说明溢出        {            g_atio_cb.rcvbuf[g_atio_cb.w_next] = value;            g_atio_cb.w_next++;                            //w_next变量用于记录下一次收到一个字节的数据该写到rcvbuf数组中的哪个位置        }        else                                                    //溢出数据统计        {             g_atio_cb.rframeover++;                                }     }     else if (__HAL_UART_GET_FLAG(&uart_at,UART_FLAG_IDLE) != RESET)    //如果是空闲中断,代表一帧数据全部收到     {         __HAL_UART_CLEAR_IDLEFLAG(&uart_at);         ringspace = CN_RCVMEM_LEN - ring_buffer_datalen(&g_atio_cb.rcvring);    //计算环形结构体中的空闲空间大小         if(ringspace < g_atio_cb.w_next)  //not enough mem    //如果这帧数据的大小大于环形结构体中的空闲空间大小,丢弃数据         {             g_atio_cb.rframedrop++;         }         else                        //正常         {             //write data to the ring buffer:len+data format             ringspace = g_atio_cb.w_next;            //将存储这帧的数组“大小”(这是一个下标)写到ringspace变量中                          /* 先把这帧数据的大小写到结构体中,再把数据写到结构体中,最终格式|len|data| */             ring_buffer_write(&g_atio_cb.rcvring,(unsigned char *)&ringspace,sizeof(ringspace));             ring_buffer_write(&g_atio_cb.rcvring,g_atio_cb.rcvbuf,ringspace);                          (void) osal_semp_post(g_atio_cb.rcvsync);             g_atio_cb.rcvframe++;    //接收到的帧数+1         }         g_atio_cb.w_next=0; //write from the head    清空接收缓存区大小     }     else ///< clear the flags     {         __HAL_UART_CLEAR_PEFLAG(&uart_at);         __HAL_UART_CLEAR_FEFLAG(&uart_at);         __HAL_UART_CLEAR_NEFLAG(&uart_at);         __HAL_UART_CLEAR_OREFLAG(&uart_at);     } }串口发送函数/******************************************************************************* function     :use this function to send a frame to the uart parameters   : instruction  : *******************************************************************************/ static ssize_t uart_at_send(const char  *buf, size_t len,uint32_t timeout) {     HAL_UART_Transmit(&uart_at,(unsigned char *)buf,len,timeout);    //直接调用HAL库函数即可发送数据     g_atio_cb.sndlen += len;     g_atio_cb.sndframe ++;     return len; }串口接收函数/******************************************************************************* function     :use this function to read a frame from the uart parameters   : instruction  : *******************************************************************************/ /* 该函数本质上是去接收结构体(g_atio_cb.rcvsync)中读取数据 */ static ssize_t uart_at_receive(void *buf,size_t len,uint32_t timeout) {     unsigned short cpylen;     unsigned short framelen;     unsigned short readlen;     int32_t ret = 0;     unsigned int lock;     if(osal_semp_pend(g_atio_cb.rcvsync,timeout))     {         lock = LOS_IntLock();         readlen = sizeof(framelen);         cpylen = ring_buffer_read(&g_atio_cb.rcvring,(unsigned char *)&framelen,readlen);    //从g_atio_cb.rcvring结构体中读取“长度“数据         if(cpylen != readlen)    //说明结构体中的数据长度小于需要读取的数据长度,结构体中的数据有问题         {             ring_buffer_reset(&g_atio_cb.rcvring);  //bad ring format here 清空该结构体中的数据             g_atio_cb.rcvringrst++;         }         else         {             if(framelen > len)    //清空该结构体中的数据             {                 ring_buffer_reset(&g_atio_cb.rcvring);  //bad ring format here                 g_atio_cb.rcvringrst++;             }             else             {                 readlen = framelen;                 cpylen = ring_buffer_read(&g_atio_cb.rcvring,(unsigned char *)buf,readlen);//从g_atio_cb.rcvring结构体中读取“数据“数据                 if(cpylen != framelen)                 {                     ring_buffer_reset(&g_atio_cb.rcvring);  //bad ring format here                     g_atio_cb.rcvringrst++;                 }                 else                 {                     ret = cpylen;    //读取成功返回实际读到的数据大小                 }             }         }         LOS_IntRestore(lock);     }     return ret; }用于先driver层注册的函数/*  通过driver层屏蔽uatr层的底层差异,让driver层之上的层觉得无论什么单片机都是一样的方法操作,使用init、deinit 、read、write即可  *  */ //make it as the at device here static ssize_t  __at_read  (void *pri,size_t offset,void *buf,size_t len, uint32_t timeout) {     return uart_at_receive(buf,len, timeout); } static ssize_t  __at_write (void *pri, size_t offset,const void *buf,size_t len,uint32_t timeout) {     return uart_at_send(buf, len, timeout); } static const los_driv_op_t s_at_op = {         .init = uart_at_init,         .deinit = uart_at_deinit,         .read = __at_read,         .write = __at_write, }; OSDRIV_EXPORT(uart_at_driv,CONFIG_UARTAT_DEVNAME,(los_driv_op_t *)&s_at_op,NULL,O_RDWR);
  • [问题求助] LiteOS_Lab移植关于SystemInit和main的错误
    arm-none-eabi-gcc  build/iot_link/link_misc/link_string.o build/iot_link/link_misc/link_random.o build/iot_link/link_misc/link_ring_buffer.o build/iot_link/link_log/link_log.o build/iot_link/os/osal/osal.o build/iot_link/os/liteos/arch/arm/arm-m/armv6-m/los_exc.o build/iot_link/os/liteos/arch/arm/arm-m/armv6-m/gcc/los_dispatch.o build/iot_link/os/liteos/arch/arm/arm-m/src/los_hw_tick.o build/iot_link/os/liteos/arch/arm/arm-m/src/los_hwi.o build/iot_link/os/liteos/arch/arm/arm-m/src/los_svc.o build/iot_link/os/liteos/arch/arm/arm-m/src/los_mpu.o build/iot_link/os/liteos/arch/arm/arm-m/src/los_hw.o build/iot_link/os/liteos/cmsis/cmsis_liteos.o build/iot_link/os/liteos/utils/rbtree.o build/iot_link/os/liteos/liteos_errno.o build/iot_link/os/liteos/newlib_stub.o build/iot_link/os/liteos/liteos_imp.o build/iot_link/os/liteos/malloc.o build/iot_link/os/liteos/los_init.o build/iot_link/os/liteos/base/core/los_tick.o build/iot_link/os/liteos/base/core/los_sys.o build/iot_link/os/liteos/base/core/los_timeslice.o build/iot_link/os/liteos/base/core/los_task.o build/iot_link/os/liteos/base/core/los_priqueue.o build/iot_link/os/liteos/base/core/los_swtmr.o build/iot_link/os/liteos/base/ipc/los_queue.o build/iot_link/os/liteos/base/ipc/los_event.o build/iot_link/os/liteos/base/ipc/los_sem.o build/iot_link/os/liteos/base/ipc/los_rwlock.o build/iot_link/os/liteos/base/ipc/los_mux.o build/iot_link/os/liteos/base/mem/heap/los_memory.o build/iot_link/os/liteos/base/mem/heap/los_heap.o build/iot_link/os/liteos/base/mem/membox/los_membox.o build/iot_link/os/liteos/base/mem/common/los_slab.o build/iot_link/os/liteos/base/mem/common/los_slabmem.o build/iot_link/os/liteos/base/mem/common/los_memcheck.o build/iot_link/os/liteos/base/misc/los_misc.o build/iot_link/os/liteos/base/om/los_err.o build/iot_link/os/liteos/extended/tickless/los_tickless.o build/iot_link/shell/shell_cmd.o build/iot_link/shell/shell_main.o build/iot_link/shell/shell_test.o build/iot_link/stimer/stimer.o build/iot_link/queue/queue.o build/iot_link/driver/driver.o build/iot_link/at/at.o build/iot_link/cJSON/cJSON.o build/iot_link/crc/crc32.o build/iot_link/crc/crc8.o build/iot_link/crc/crc16.o build/iot_link/oc/oc_lwm2m/oc_lwm2m_al/oc_lwm2m_al.o build/iot_link/oc/oc_lwm2m/boudica150_oc/boudica150_oc.o build/iot_link/storage/storage.o build/iot_link/storage/partition.o build/iot_link/demos/app_demo_main.o build/iot_link/link_main.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_tim_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_gpio.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ramfunc.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_cortex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_tim.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_spi.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c_ex.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_iwdg.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_dma.o build/drivers/third_party/ST/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rng.o build/Src/usart.o build/Src/uart_debug.o build/Src/dwt.o build/Src/i2c.o build/Src/spi.o build/Src/gpio.o build/Src/Huawei_IoT_QR_Code.o build/Demos/hello_world_demo/hello_world_demo.o  build/iot_link/os/liteos/arch/arm/arm-m/armv6-m/gcc/los_startup.o    -u _printf_float -mcpu=cortex-m0 -mthumb   -specs=nano.specs -Tf:/L072/L7/GCC/os.ld  -Lf:/L072/L7/Lib  -lc -lm -lnosys -Wl,-Map=build/Huawei_LiteOS.map,--cref -Wl,--gc-sections -u _printf_float -o build/Huawei_LiteOS.elfbuild/iot_link/os/liteos/arch/arm/arm-m/armv6-m/gcc/los_startup.o: In function `Reset_Handler':C:/Users/Administrator/.iotlink/sdk/IoT_LINK/iot_link/os/liteos/arch/arm/arm-m/armv6-m/gcc/los_startup.S:84: undefined reference to `SystemInit'C:/Users/Administrator/.iotlink/sdk/IoT_LINK/iot_link/os/liteos/arch/arm/arm-m/armv6-m/gcc/los_startup.S:86: undefined reference to `main'collect2.exe: error: ld returned 1 exit statusmake: *** [Makefile:148: build/Huawei_LiteOS.elf] Error 1exit code=2[2020/5/9 11:40:57] 编译失败。按照模板创建的工程修改完毕,移植到最后出现了undefined reference to `SystemInit和undefined reference to `main'的错误,求解答。
  • [问题求助] LiteOS移植到GD32F303,启动后任务调度一次就挂了?
    在GD32F303CGT6上移植LiteOS,使用KEIL开发环境移植的系统已经正常运行。目前在往ubuntu18.04LTS上使用gcc环境,源码和keil工程一样,只更换了启动文件和链接脚本文件。进入 LOS_Start(); 任务只能切换一次,就失败了,LOS_Start();未能正常执行完,有没有人提供下排查思路?
  • [技术干货] 求助liteos_lab的代码目录结构说明
    请问一下有没有liteos_lab的代码目录结构说明,liteos的代码目录结构说明找到了,但是不知道有没有liteos_lab的
  • [技术干货] LiteOS和LiteOS_Lab的差异
    摘要:相信在使用LiteOS的同学都发现了华为Gihub仓库中有两个仓库分别是LiteOS和LiteOS_Lab,我们在开发中究竟该选择哪一个呢?LiteOS和LiteOS_Lab的仓库地址LiteOS_Lab:https://github.com/LiteOS/LiteOS_LabLiteOS:https://github.com/LiteOS/LiteOS大家可以自己点进去看看,能更好的了解它们。LiteOS和LiteOS_Lab的差异--维护更新方面大家可以看到LiteOS_Lab一直在维护更新,LiteOS最近很少在维护更新。LiteOS和LiteOS_Lab的差异--基于的开源协议它俩都是基于BSD-3开源协议的,点击这里查看详细介绍https://support.huaweicloud.com/productdesc-LiteOS/zh-cn_topic_0145347224.htmlLiteOS和LiteOS_Lab的差异--组件丰富度上图为LiteOS的组件,下图为LiteOS_Lab的组件,LiteOS_Lab的组件比较丰富。LiteOS和LiteOS_Lab的差异--对IoT Studio的支持在旧版或者新版的IoT Studio中的SDK都是直接引用LiteOS_Lab的某个分支或者版本,暂时并未对LiteOS进行支持LiteOS和LiteOS_Lab的差异--整体架构LiteOS是以一个内核为中心并且无法替换,向四周拓展各种组件,例如文件系统、AT框架、OTA等LiteOS_Lab是一个由多个模块组成的系统,所以模块均可替换为自己写的或者华为提供的,包括操作系统也能在UCOSII、FreeRTOS甚至是自己实现的操作系统进行切换,分层设计的思想较佳,可维护性较强。PS:相信到这里大家应该明白需要选择哪个系统了。
  • [问题求助] 【求助】GCC构建LiteOS工程无法启动
    求助,本人使用GCC编译器编译LiteOS以后,LiteOS可以初始化,但是当其尝试跳转到主任务的时候就会跳转失败。本人使用的是GD32F303CE的芯片,芯片里面代码分两段,一段引导启动,一段启动起来执行LiteOS。第二段代码执行后,初始化均正常,在执行LOS_StartToRun函数中的BX R6的时候,发现R6是0,跳转就失败了。相同的工程使用IAR编译就正常,所以我怀疑我在写Makefile使用的ld文件有问题,ld文件是使用的别人发给我的demo。请各位大神帮我看看吧,我也不知道是哪里出了问题MEMORY{  FLASH (rx)      : ORIGIN = 0x08008000, LENGTH = 0x80000  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 0xFFFF}/* Define output sections */SECTIONS{  __stack_size = DEFINED(__stack_size) ? __stack_size : 0x1000;  __heap_size = DEFINED(__heap_size) ? __heap_size : 0x4000;    /* The startup code goes first into FLASH */  .isr_vector :  {    . = ALIGN(4);    KEEP(*(.isr_vector)) /* Startup code */    . = ALIGN(4);  } >FLASH  /* The program code and other data goes into FLASH */  .text :  {    . = ALIGN(4);    *(.text)           /* .text sections (code) */    *(.text*)          /* .text* sections (code) */    *(.rodata)         /* .rodata sections (constants, strings, etc.) */    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */    *(.glue_7)         /* glue arm to thumb code */    *(.glue_7t)        /* glue thumb to arm code */    KEEP (*(.init))    KEEP (*(.fini))    . = ALIGN(4);    _etext = .;        /* define a global symbols at end of code */  } >FLASH   .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH    .ARM : {    __exidx_start = .;      *(.ARM.exidx*)      __exidx_end = .;    } >FLASH  .ARM.attributes : { *(.ARM.attributes) } > FLASH  .preinit_array     :  {    PROVIDE_HIDDEN (__preinit_array_start = .);    KEEP (*(.preinit_array*))    PROVIDE_HIDDEN (__preinit_array_end = .);  } >FLASH  .init_array :  {    PROVIDE_HIDDEN (__init_array_start = .);    KEEP (*(SORT(.init_array.*)))    KEEP (*(.init_array*))    PROVIDE_HIDDEN (__init_array_end = .);  } >FLASH  .fini_array :  {    PROVIDE_HIDDEN (__fini_array_start = .);    KEEP (*(.fini_array*))    KEEP (*(SORT(.fini_array.*)))    PROVIDE_HIDDEN (__fini_array_end = .);  } >FLASH  /* used by the startup to initialize data */  _sidata = .;  /* Initialized data sections goes into RAM, load LMA copy after code */  .data : AT ( _sidata )  {    . = ALIGN(4);    _sdata = .;        /* create a global symbol at data start */    *(.data)           /* .data sections */    *(.data*)          /* .data* sections */    . = ALIGN(4);    _edata = .;        /* define a global symbol at data end */  } >RAM  /* Uninitialized data section */  . = ALIGN(4);  .bss :  {    /* This is used by the startup in order to initialize the .bss secion */    _sbss = .;         /* define a global symbol at bss start */    __bss_start__ = _sbss;    *(.bss)    *(.bss*)    *(COMMON)    . = ALIGN(4);    _ebss = .;         /* define a global symbol at bss end */    __bss_end__ = _ebss;  } >RAM  PROVIDE ( end = _ebss );  PROVIDE ( _end = _ebss );    .stack : ALIGN(8)  {    PROVIDE( _heap_end = . );     . = __stack_size;      PROVIDE( _estack = . );   }>RAM    .heap : ALIGN(0x10)  {PROVIDE( __LOS_HEAP_ADDR_START__ = . );. = __heap_size == 0 ? 0 : ORIGIN(RAM) + LENGTH(RAM);PROVIDE( __LOS_HEAP_ADDR_END__ = . );PROVIDE( _heap_end = . );  } >RAM  /* Remove information from the standard libraries */  /DISCARD/ :  {    libc.a ( * )    libm.a ( * )    libgcc.a ( * )  }}
  • [技术干货] 详解LiteOS中的结构体与设备管理中编解码插件的对应关系
    摘要:本贴详细解说设备接入服务中的编解码插件的每一个位和我们LiteOS中的数据发送用的结构体是如何一一对应的。一、编解码插件定义与结构体的对应我在下图中定义了一个消息,消息名为Smoke和我们在Demo/oc_smoke_template/oc_smoke_template.c文件中的结构体tag_app_Smoke 一一对应,请看图下的代码中的注释。图中①勾选了代表当设备接入收到特定的消息上报后,下发响应字段,已让设备知道数据已被服务器正确接收,不需要重发。图中④长度,单位字节,定义消息体时,系统会根据消息体的类型来自动生成(例如int16u就是2字节)。#pragma pack(1)    //注意这里,这个是让结构体以1个字节对齐,不出现空域 typedef struct     {         int8u messageId;     //定义了一个int8u类型(图中③)的变量messageId(图中②)代表地址域(图中⑤)     int8u Smoke_Value;  //定义了一个int16u类型(图中③)的变量Smoke_Value(图中②)表示烟感报警器的状态     } tag_app_Smoke;   //结构体名 #pragma pack()     //注意这里,这个是让结构体以1个字节对齐,不出现空域 //这里的int8u是指unsigned int类型的数据,并且保证大小是1字节也就是8位 //typedef unsigned char int8u;这是int8u的定义二、结构体的默认对齐    用Keil编译时,结构体默认是以4字节对齐,比如说A这个结构体就会出现空域2个字节的空域,后面发送的时候就会多发出去2个0,所以我们需要用#pragma pack(1)和#pragma pack() 来指定以1字节对齐tydef struct {     int8u    a;     int8u    b; } A;三、发送结构体/* 代码出自Demo/oc_smoke_template/oc_smoke_template.c */ #pragma pack(1) typedef struct     {         int8u messageId;      int8u Smoke_Value;   } tag_app_Smoke;   #pragma pack()  tag_app_Smoke Smoke; Smoke.messageId = cn_app_Smoke;     Smoke.Smoke_Value = htons((int)E53_SF1_Data.Smoke_Value);     oc_lwm2m_report( (char *)&Smoke, sizeof(Smoke), 1000);首先用定义一个结构体Smoke,分别给结构体中的各个成员赋值,最后oc_lwm2m_report函数发送,我现在画一个示意图,代表该结构体在内存中的分布,注意:我们已经设置了按照亿字节对齐,所以不会有空域。假设我们的内存从0x0001开始,一个内存地址对应一个字节,默认小端模式高字节存在高位,低字节存在低位内存地址结构体成员名称数据0x0001messageIDcn_app_Smoke假设是80x0002Smoke_Valuehtons((int)E53_SF1_Data.Smoke_Value)假设是2现在调用oc_lwm2m_report函数来发送,首先传入结构体的首字节的内存地址(&Smoke)并通过强制类型转换为char *,意思就是一次只取一个字节,在传入该结构体的大小(sizeof(Smoke)),oc_lwm2m_report函数就会从Smoke结构体的首地址开始取值一次只取一个字节并且指针向后移位一个字节直到把数据全部取出来发到发送缓存区中等待发送。四、设备接入服务收到数据最终设备接入服务收到的数据为(二进制):1000_0010,这是编解码插件就开始工作了,将1000解析出来并对应到messageID中,0010解析出来并对应到Smoke_Value中,转换为十六进制显示为{messageID=0x08,Smoke_Value=0x02}。PS:大家如果还有不理解的地方欢迎留言!
  • [问题求助] LiteOS移植内核版本的问题
    最近在做LiteOS,对于应该移植哪一个版本很疑惑。我看有论坛里有LiteOS_Lab和LiteOS两个版本,哪个最新并且还在维护呀,还有如果移植的话,应该移植哪个分支呢。我之前移植的是LiteOS下面的dev-deserted分支,已经写了两个LED任务,并且跑通了,但是今天领导让我确认一下新的版本。很疑惑,请求各位大佬不吝赐教啊。
  • [问题求助] 如何在RISC-V架构移植华为LiteOS?
    如何使用GD32VF103系列的开发板,基于RISC-V架构下移植华为的LiteOS?和在ARM下哪些地方不同呢?
  • [技术干货] LiteOS无法直接烧录或者烧录失败解决方法--ST-Link
    前提条件:程序编译成功,并且电脑上已经安装ST-Link驱动,你使用的仿真器也是ST-Link。上图黑色的是J-Link,下图紫色的是ST-Link,本教程适用于ST-Link,如果是J-Link,点击这里查看教程设备管理器中也能查看你使用的是ST-Link还是J-Link环境:Win10+ST-LINK Utility v4.3.0.0第一步:先到IoT Studio创建的工程目录中把Huawei_LiteOS.hex文件取出    该文件默认在GCC/build目录中,注意:由于大家IoT Studio版本不一致,所以可能不在build中,但是一定在GCC目录下,可以自己找找。第二步:打开STM32 ST-Link Utiliry并烧写程序        ①找到该软件,一般位于C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\STM32 ST-LINK Utility.exe中也可能安装时你自己指定了路径    ②打开STM32 ST-LINK Utility,选择File-->Open file,在选择刚才我们说的xxx.hex文件            ③点击connect to the target,下方会自动显示识别出来的芯片型号以及flash大小        ④点击Full chip erase,擦除整块芯片之前的程序        ⑤点击program verify并点击start,等待烧写并校验完成,你就能看到程序正在运行了    
  • [技术干货] LiteOS无法直接烧录或者烧录失败解决方法--J-Link
    前提条件:程序编译成功,并且电脑上已经安装J-Link驱动,你使用的仿真器也是J-Link。上图黑色的是J-Link,下图紫色的是ST-Link,本教程适用于J-Link,如果是ST-Link,请点击这里查看教程。设备管理器中也能查看你使用的是ST-Link还是J-Link环境:Win10+J-Linkv6.44第一步:先到IoT Studio创建的工程目录中把Huawei_LiteOS.hex文件取出    该文件默认在GCC/build目录中,注意:由于大家IoT Studio版本不一致,所以可能不在build中,但是一定在GCC目录下,可以自己找找。第二步:直接使用J-Flash V6.44h烧录    该软件的目录位于C:\ProgramData\Microsoft\Windows\Start Menu\Programs\SEGGER - J-Link V6.44h或者C:\Program Files (x86)\SEGGER\JLink_V644h或者是你自己安装时指定的路径。    ①打开J-Flash V6.44h并选择Create a new project,点击Start J-Flash。        ②点击右边...,选择你的芯片厂商ST在选择芯片型号。                        ③选择接线方式,一般都是SWD/JTAG,这两种接线的不同,可以百度查看差异,点击OK。        ④选择File-->Open data file,并找到你的hex文件所在目录选择XXXX.hex文件,点击打开        ⑤选择Target-->Connect        连接成功会有以下信息        ⑥先擦除在烧写或者直接烧写都可以        我一般使用“直接烧写”烧写,烧写完成之后按下开发板的复位键即可看到程序运行。
  • [问题求助] 基于LiteOS的Socket TCP通信速率只能达到200ms的周期
    LiteOS创建一个TCP通信任务,每隔100ms通过 lwip_send 接口往PC 网络调试助手发送一次数据(Hello World)。实际测试发现:1、TCP通信任务能够100ms调度一次;2、但是网络传输出现阻塞现象,200ms的周期发送两帧数据;3、通过 wireshark 抓包来看,确实是200ms的周期才发送数据。请问有什么方式实现网络通信的实时传输?以下为网络调试助手接收到的数据:[2020-04-23 10:07:11.549]# RECV ASCII FROM 192.168.168.99 :52032>Hello WorldHello World[2020-04-23 10:07:11.749]# RECV ASCII FROM 192.168.168.99 :52032>Hello WorldHello World[2020-04-23 10:07:11.949]# RECV ASCII FROM 192.168.168.99 :52032>Hello WorldHello World
  • [技术干货] 0x00 LiteOS_Lab仓库组件详解--OS
    摘要:之前我们在汇总帖中讨论过LiteOS_Lab中的所有东西都是以组件化实现的包括了OS,所以这期来详解OS组件github上LiteOS_Lab中OS组件直达链接:https://github.com/LiteOS/LiteOS_Lab/tree/iot_link/iot_link/osOSAL的AL=abstract layer 抽象层,其他地方的AL也可以以此类推。一、OS组件总览文件名作用linux可以在Linux运行的os,其实就是linux中抽象出来的os接口liteos可以在单片机上运行的os(stm32等),一整套内核(包括了任务调度等等功能),后面我也会详细说它macos可以在macos运行的os,其实就是macos中抽象出来的os接口novaos可以在单片机上运行的os(stm32等),比较精巧,一整套内核(包括了任务调度等等功能)osalos抽象层,给其他组件调用(at、shell等等),可以看下面的结构图理解调用关系ucosiiucosii比较经典的内核之一Readme.meos组件的介绍kconfig_os用于图形化配置os组件os.mk用于根据配置控制编译os的组件组件调用关系图:二、详解OSAL层由于篇幅有限,只能列举部分函数,以任务相关的函数为主。这些函数都在OSAL层中声明过了,不过它们是一个接口,它们只是去调用我们实现并注册好的任务函数。举个任务创建的例子:void* osal_task_create(const char *name,int (*task_entry)(void *args),\     void *args,int stack_size,void *stack,int prior)     {         void *ret = NULL;         if((NULL != s_os_cb) &&(NULL != s_os_cb->ops) &&(NULL != s_os_cb->ops->task_create))         {             ret = s_os_cb->ops->task_create(name, task_entry,args,stack_size,stack,prior);         }         return ret;     } /* 引自os/osal/osal.c */看到了吧,这个函数最终调用的是我们注册进s_os_cb结构体中ops成员中的task_create函数指针,如何注册呢?再来一个LiteOS注册的实例:Liteos的任务创建函数是LOS_TaskCreate我们需要对它进行以下封装,使它变成osal_task_create类型的函数static void *__task_create(const char *name,int (*task_entry)(void *args),\     void *args,int stack_size,void *stack,int prior)     {         void *ret = NULL;         UINT32 uwRet = LOS_OK;         UINT32  handle;         TSK_INIT_PARAM_S task_init_param;         memset (&task_init_param, 0, sizeof (TSK_INIT_PARAM_S));         task_init_param.uwArg = (unsigned int)(uintptr_t)args;         task_init_param.usTaskPrio = (unsigned short)prior;         task_init_param.pcName =(char *) name;         task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)task_entry;         task_init_param.uwStackSize = stack_size;         uwRet = LOS_TaskCreate(&handle, &task_init_param);         if(LOS_OK != uwRet){             return ret;         }         ret = (void *)(uintptr_t)handle;         return ret;     }     /* 引自os/liteos/liteos_imp.c */封装好了之后把他存到tag_os_ops类型的s_liteos_ops结构体中:并将s_liteos_ops结构体指针存到tag_os类型的s_link_liteos结构体中:最后调用osal_install函数完成注册:其他函数大家可以以此类推。PS:文章到这里就算写完了,如果有疑问请留言,或者又想听的内容也尽管留言!如果对你有帮助也希望能点个赞或者留个言,这是对我最大的鼓励!
  • [问题求助] LiteOS系统中文网中的“中断”介绍篇中关于中断初始化函数Los_HwiInit函数的使用问题
    在github上找到了关于这个函数的封装,但是发现封装的函数名称不一样,这是一个疑问,然后就是使用SDK中封装的函数即osHwiInit进行中断初始化,是否需要对中断的触发外设进行相应的中断线映射以及优先级的配置?若需要配置,那么华为封装的这个中断初始化函数的意义是啥?
  • [技术干货] Ubuntu下搭建LiteOS_Lab开发环境
    摘要:与LiteOS_Lab配套的开发工具IoT-Studio正在开发中,目前只有内测版,想移植LiteOS_Lab的朋友们可以参考此教程,搭建Ubuntu下的开发环境一、准备需要的软件Ubuntu19.10桌面版:一键直达华为开源镜像仓库https://mirrors.huaweicloud.com/ubuntu-releases/19.10/,直接点击链接进入下载下图版本即可。VMware虚拟机:我用的版本是15.5pro。LiteOS_Lab:这才是我们的主菜,下载地址https://github.com/LiteOS/LiteOS_Lab/gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux工具链:我们编译LiteOS_Lab就是使用该工具链,IoT-Studio中也是使用该工具链编译LiteOS_Lab。下载地址:https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads,先点击①再点击②即可下载,注意版本!Kconfig工具:LiteOS_Lab/tools/kconfiglib包含了,无需下载,该工具用于图形化配置和生成SDK配置。二、开始搭建开发环境关于如何在虚拟机中安装Ubuntu我就先略过,网上教程特别多,大家搜索一下就可以了。1.安装gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux工具链cd ~                        #切换到用户目录 mkdfir toolchain    #创建一个名为toolchain的目录,将下载好的gcc-arm-none-eabi压缩包放入 tar -jxvf gcc-arm-none-eabi-9-2019-q4-major-x86_64-linux.tar.bz2     #解压缩 cd gcc-arm-none-eabi-9-2019-q4-major    #你会在目录中看到以下文件夹arm-none-eabi  bin  lib  share,所有的工具都在bin目录中,所以我们要将bin添加到PATH变量中 sudo vim ~/.bashrc                                     #我们需要修改该文件,在该文件内添加PATH ############################################################################## 在~/.bashrc文件最后一行加上export PATH=~/toolchain/gcc-arm-none-eabi-9-2019-q4-major/bin:$PATH 注意:如果前面你没有使用和我相同的工具链版本或者没有解压到和我一样的目录中,请自行修改bin文件的路径 保存退出即可! ############################################################################## source ~/.bashrc                                #将刚刚的配置执行以下 echo $PATH                                       #查看PATH变量中有没有添加了我们的bin目录,正常情况你将得到我这样的输出 ############################################################################## /home/fanxinhao/toolchain/gcc-arm-none-eabi-9-2019-q4-major/bin:    这就是我们刚才添加的路径 /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin ############################################################################## #现在可以去测试下 cd LiteOS_Lab/targets/STM32L431_BearPi/GCC/        #进入任意开发板例程文件中的GCC目录 make                                                                            #执行编译指令 ############################################################################## 正常情况下,最后的打印结果中是如下格式,说你的arm-gcc工具链已经成功安装了    text    data     bss     dec     hex filename   90728     576   11296  102600   190c8 appbuild/Huawei_LiteOS.elf arm-none-eabi-objcopy -O ihex appbuild/Huawei_LiteOS.elf appbuild/Huawei_LiteOS.hex arm-none-eabi-objcopy -O binary -S appbuild/Huawei_LiteOS.elf appbuild/Huawei_LiteOS.bin ##############################################################################2.安装Kconfigcd ~                        #到用户目录 mkdir Work            #创建名为Work的目录,并将LiteOS_Lab放到该目录或者直接在该目录中克隆仓库 cd ~/Work/LiteOS_Lab/tools/kconfig/Kconfiglib    #你能看到很多.py的可执行文件,同样的我们需要将该目录添加到PATH sudo vim ~/.bashrc                                     #我们需要修改该文件,在该文件内添加PATH ############################################################################## 在~/.bashrc文件最后一行加上export PATH=~/Work/LiteOS_Lab/tools/kconfig/Kconfiglib:$PATH 注意:如果前面你没有使用和我相同的工具链版本或者没有解压到和我一样的目录中,请自行修改bin文件的路径 保存退出即可! ############################################################################## source ~/.bashrc                                #将刚刚的配置执行以下 echo $PATH                                       #查看PATH变量中有没有添加了我们的bin目录,正常情况你将得到我这样的输出 ############################################################################## /home/fanxinhao/Work/LiteOS_Lab/tools/kconfig/Kconfiglib:    #这就是我们刚才添加的目录 /home/fanxinhao/toolchain/gcc-arm-none-eabi-9-2019-q4-major/bin: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin ############################################################################## #现在可以去测试下 cd LiteOS_Lab/targets/STM32L431_BearPi/        #进入任意开发板例程文件中的目录中 menuconfig.py                                                    #启动Kconfig图形化菜单 #出现下图就代表配置成功了到此就算安装完成了!PS:需要用到的文件如果大家下载不下来,可以留言,或者私信我,我发给大家,因为附件大小有限制,所以无法上传
总条数:623 到第
上滑加载中