找回密码
 立即注册
查看: 1659|回复: 16

有没有一款占用内存超小的抢占式RTOS?

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-30 15:53:34

7

主题

48

回帖

231

积分

中级会员

积分
231
发表于 2024-5-29 16:55:30 | 显示全部楼层 |阅读模式
我有一个程序,使用的是STC32G12K128芯片,35M频率,程序编译后占用的资源比较多,如下

Program Size: data=13.7 edata+hdata=3737 xdata=7684 const=1609 code=31953
creating hex file from ".\Obj\main"...
".\Obj\main" - 0 Error(s), 12 Warning(s).

edata使用了3737,xdata使用了7684,因为要驱动一个P3.75的LED大屏,35张模组,所以30张模组在xdata在,5张在edata中,以二维数组方式声明的内存

在这种情况下,还能上哪一款实时操作系统呢?

目前来说,任务如下:
刷新任务,函数需要10ms,那么每秒60HZ的话,需要每16ms执行1次刷新函数,如果17ms执行1次的话刷新率不到60,则肉眼可见的屏闪,有时虽然频率达到60hz,但刷新时快时慢屏也会闪,所以要想屏不闪,必须准时执行该任务!!
有3个任务,执行时间需要5ms,执行间隔100ms左右不影响

有1个任务,执行时间为0~2ms时间不定,间隔必须10ms
还有几个执行时间为0ms的任务,不影响

如果采用普通的 while(1){}的方式来写的话,9+4*3+2=23ms,1000/23=43HZ,明显不够,屏幕1闪1闪的

我目前使用的是官方的至简无错 改进版 调度方案,优先级最高的刷新任务,每16ms执行1次,3个需要5ms的任务,每80ms执行1次,但不是同时执行,也就是说分别计数到25,41,57时执行
虽然 这样改进后,屏幕稳定多了,但是碰到那个10ms间隔的任务就完蛋了,因为必须10ms执行1次,且执行的时间不确定,有时需0ms,有时需1ms,有时需2ms,导致刷新任务偶尔延误,屏偶尔闪烁

请问这种情况下,有没有一种占用内存在1k左右的抢占式RTOS呢?只要有最简单的抢占式调度就行了,不需要任务间的通信功能。。。


回复

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-30 07:46:22

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-5-30 09:22:17 | 显示全部楼层
本帖最后由 tzz1983 于 2024-5-30 11:21 编辑

一种用DMA刷新模组的办法:

模组显示驱动是用串行传输数据的,
单路串行信号分别为:
DAT: //数据
CLK: //同步串行时钟
其它辅助信号:
LE:   //数据锁存
OE:  //输出允许
A:B:C:D: //行扫描地址.

为了显示多种颜色和提高效率,采用多路串行数据传输
多路和单路相同,只是增加了DAT位,例如一个 HUB75 接口包含了6个数据端口:
R1://数据
G1://数据
B1://数据
R2://数据
G2://数据
B2://数据
CLK: //同步串行时钟

其它辅助信号:
LE:   //数据锁存
OE:  //输出允许
A:B:C:D: //行扫描地址.

STC32系列有LCM接口,并且可以DMA,稍加利用就可以用于模组的驱动,并且是DMA驱动,让CPU解放出来!
具体方法是:
1. 把LCM驱动的WR信号用作串行口的CLK信号,如下图
截图202405300901491342.jpg

2. LCM的16位数据口用作串行数据口,这样一次CLK就可以同时传输16位数据。
3. 把要显示的数据按照顺序放在XDATA中,然后启动DMA。很简单,并不难。这样就可以大幅减轻CPU的压力。
4. 做到以上几点,静态画面刷屏的事情基本就不用CPU管了,弄个PWM定时DMA传输.
5. CPU的主要工作就是更新XDATA中的显示数据,如果是静态画面,CPU将无事可做,CPU使用率可控制在2%以内!
6. 当然动态画面还是有压力的,主要因为要配合DMA格式,写点(也就是写XDATA)时可能要有相应的算法。

其它技巧:
1. 利用PWM中断来产生行扫描定时,为什么用PWM而不是用定时器?
因为PWM可以自动控制OE端,让屏幕的亮度无级调,效果很好!
2.   用或不用RTOS都没有关系,因为任务非常少,可以直接用一个低级中断来代替任务,更高效。

另外60HZ帧率实在是太低了,这也是最低的要求,仅人眼观察问题不大,
但是摄像机就拍不出来了,抖得很厉害,或者拍到的是一行行的乱七八糟。
我是做交通信号类的产品,要求比较高,我一般都做到200HZ以上的帧率,
资源允许时做到400HZ以上,这样就是摄像机拍出来,也是完好的图像

我也做模组相关的产品,以上是我的心得, 希望能帮到你
我曾用STC32G做一款产品,显示静态画面时,CPU使用率可控制在2%以内!
当然只是静态画面,动画还是有压力的,主要压力是不断更新XDATA中的显示内容。




回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-30 15:53:34

7

主题

48

回帖

231

积分

中级会员

积分
231
发表于 2024-5-30 10:15:12 | 显示全部楼层
tzz1*** 发表于 2024-5-30 09:22
一种用DMA刷新模组的办法:

模组显示驱动是用串行传输数据的,

谢谢回复,,我受到坛友“QQ624***”的启发,我用一个24位自动重载的定时器,16ms中断,把刷新代码放到中断中,就搞定了,,结果30M晶振跑这个程序,屏一点也不闪,其它任务通通放到while(1)中,不停的排队循环执行即可,只是那个10ms执行1次的任务,现在大于10ms了,估计再弄个10ms定时器就搞定了。。。

看来大部分其实根本用不到rtos,,只要硬件定时器足够多的话,比上rtos简单,呵呵!

不过你的回复我以后要去研究的,谢谢!~
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-30 15:53:34

7

主题

48

回帖

231

积分

中级会员

积分
231
发表于 2024-5-30 11:16:59 | 显示全部楼层
tzz1*** 发表于 2024-5-30 09:22
一种用DMA刷新模组的办法:

模组显示驱动是用串行传输数据的,

我又仔细看了一下你的回复,60HZ的刷新率,只是人眼看不出来,用手机拍,还是1行1行的,下次试试你说的DMA刷新技巧,,我的程序有3个任务分别占用5ms时间,就是用来更新xdata中的数据所消耗的时间
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2024-5-30 13:03:39 | 显示全部楼层
截图202405301300235402.jpg

截图202405301313061484.jpg

截图202405301302205529.jpg

截图202405301302575830.jpg

截图202405301303353979.jpg

回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2024-5-30 13:09:58 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:54
  • 最近打卡:2025-05-01 09:07:55

717

主题

1万

回帖

1万

积分

管理员

积分
15613
发表于 2024-5-30 13:14:39 | 显示全部楼层
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-30 15:53:34

7

主题

48

回帖

231

积分

中级会员

积分
231
发表于 2024-5-30 13:49:48 | 显示全部楼层
神*** 发表于 2024-5-30 13:09
【新提醒】视频教学《USB型 1T 8051 单片机原理及应用-STC8H8K64U》,山东大学陈桂友教授 - 视频教学,《 ...

非常感谢,,提供了这么详细的视频教程。。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:7
  • 最近打卡:2025-04-30 15:53:34

7

主题

48

回帖

231

积分

中级会员

积分
231
发表于 2024-6-13 16:50:05 | 显示全部楼层
神*** 发表于 2024-5-30 13:09
【新提醒】视频教学《USB型 1T 8051 单片机原理及应用-STC8H8K64U》,山东大学陈桂友教授 - 视频教学,《 ...

最近在学习这系列视频,正好学了DMA读写串口的视频,发现DMA方式串口接收数据的时候,很容易丢失数据啊。。。

  1. #include "stc/STC32G.h"
  2. #include "stdio.h"
  3. #include "intrins.h"
  4. typedef         unsigned char        u8;
  5. typedef         unsigned int        u16;
  6. typedef         unsigned long        u32;
  7. #define MAIN_Fosc       22118400L   //定义主时钟(精确计算115200波特率)
  8. #define Baudrate1       115200L
  9. bit        DmaTxFlag;
  10. bit        DmaRxFlag;
  11. u8 xdata DmaBuffer[21];
  12. void UART1_config(u8 brt);   // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  13. void DMA_Config(void);
  14. void Delay90us(void);
  15. void UartPutc(unsigned char dat)
  16. {
  17.         SBUF = dat;
  18.         while(TI == 0);
  19.         TI = 0;
  20. }
  21. char putchar(char c)
  22. {
  23.         UartPutc(c);
  24.         return c;
  25. }
  26. //========================================================================
  27. // 函数: void main(void)
  28. // 描述: 主函数。
  29. // 参数: none.
  30. // 返回: none.
  31. // 版本: VER1.0
  32. // 日期: 2014-11-28
  33. // 备注:
  34. //========================================================================
  35. void main(void)
  36. {
  37.         u16 i;
  38.        
  39.     WTST = 0;  //设置程序指令延时参数,赋值为0可将CPU执行指令的速度设置为最快
  40.     EAXFR = 1; //扩展寄存器(XFR)访问使能
  41.     CKCON = 0; //提高访问XRAM速度
  42.     P0M1 = 0x00;   P0M0 = 0x00;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  43.     P1M1 = 0x00;   P1M0 = 0x00;   //设置P1.1、P1.4、P1.5为漏极开路(实验箱加了上拉电阻到3.3V), P1.1在PWM当DAC电路通过电阻串联到P2.3
  44.     P2M1 = 0x00;   P2M0 = 0x00;   //设置P2.2~P2.5为漏极开路(实验箱加了上拉电阻到3.3V)
  45.     P3M1 = 0x00;   P3M0 = 0x00;   //设置P3.4、P3.6为漏极开路(实验箱加了上拉电阻到3.3V)
  46.     P4M1 = 0x00;   P4M0 = 0x00;   //设置P4.2~P4.5为漏极开路(实验箱加了上拉电阻到3.3V)
  47.     P5M1 = 0x00;   P5M0 = 0x00;   //设置P5.2、P5.3为漏极开路(实验箱加了上拉电阻到3.3V)
  48.     P6M1 = 0x00;   P6M0 = 0x00;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
  49.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  50.         for(i=0; i<256; i++)
  51.         {
  52.                 DmaBuffer[i] = i;
  53.         }
  54.         UART1_config(1);    // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  55.         printf("STC32G UART1 DMA Test Programme!\r\n");  //UART1发送一个字符串
  56.         DMA_Config();
  57.         EA = 1; //允许总中断
  58.         DmaTxFlag = 0;
  59.         DmaRxFlag = 0;
  60.         while (1)
  61.         {
  62.                 if(DmaRxFlag)
  63.                 {
  64.                         DmaRxFlag = 0;
  65.                         Delay90us();//模拟被其它中断 或 其它后台程序占用90us的时间,然后再开启DMA接收数据,则会丢失1个字节的数据
  66.                         DMA_UR1R_CR = 0xa1;                        //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
  67.                 }
  68.         }
  69. }
  70. void Delay90us(void)        //STC32G @22.1184MHz
  71. {
  72.         unsigned long edata i;
  73.         _nop_();
  74.         _nop_();
  75.         i = 496UL;
  76.         while (i) i--;
  77. }
  78. //========================================================================
  79. // 函数: void DMA_Config(void)
  80. // 描述: UART DMA 功能配置.
  81. // 参数: none.
  82. // 返回: none.
  83. // 版本: V1.0, 2021-5-6
  84. //========================================================================
  85. void DMA_Config(void)
  86. {
  87.         DMA_UR1T_CFG = 0x80;                //bit7 1:Enable Interrupt
  88.         DMA_UR1T_STA = 0x00;
  89.         DMA_UR1T_AMT = 20;                //设置传输总字节数(低8位):n+1
  90.         DMA_UR1T_AMTH = 0x00;                //设置传输总字节数(高8位):n+1
  91.         DMA_UR1T_TXAH = (u8)((u16)&DmaBuffer >> 8);
  92.         DMA_UR1T_TXAL = (u8)((u16)&DmaBuffer);
  93.         DMA_UR1T_CR = 0xc0;                        //bit7 1:使能 UART1_DMA, bit6 1:开始 UART1_DMA 自动发送
  94.         DMA_UR1R_CFG = 0x80;                //bit7 1:Enable Interrupt
  95.         DMA_UR1R_STA = 0x00;
  96.         DMA_UR1R_AMT = 20;                //设置传输总字节数(低8位):n+1
  97.         DMA_UR1R_AMTH = 0x00;                //设置传输总字节数(高8位):n+1
  98.         DMA_UR1R_RXAH = (u8)((u16)&DmaBuffer >> 8);
  99.         DMA_UR1R_RXAL = (u8)((u16)&DmaBuffer);
  100.         DMA_UR1R_CR = 0xa1;                        //bit7 1:使能 UART1_DMA, bit5 1:开始 UART1_DMA 自动接收, bit0 1:清除 FIFO
  101. }
  102. //========================================================================
  103. // 函数: void UART1_config(u8 brt)
  104. // 描述: UART1初始化函数。
  105. // 参数: brt: 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  106. // 返回: none.
  107. // 版本: VER1.0
  108. // 日期: 2014-11-28
  109. // 备注:
  110. //========================================================================
  111. void UART1_config(u8 brt)    // 选择波特率, 2: 使用Timer2做波特率, 其它值: 使用Timer1做波特率.
  112. {
  113.         u16 dat = (u16)(65536UL - (MAIN_Fosc / 4) / Baudrate1);
  114.         /*********** 波特率使用定时器2 *****************/
  115.         if(brt == 2)
  116.         {
  117.         S1BRT = 1;        //S1 BRT Use Timer2;
  118.             T2R = 0;        //Timer stop
  119.             T2_CT = 0;        //Timer2 set As Timer
  120.             T2x12 = 1;        //Timer2 set as 1T mode
  121.             T2H = dat >> 8;
  122.             T2L = dat;
  123.             ET2 = 0;    //禁止中断
  124.             T2R = 1;        //Timer run enable
  125.         }
  126.         /*********** 波特率使用定时器1 *****************/
  127.         else
  128.         {
  129.                 TR1 = 0;
  130.         S1BRT = 0;                //S1 BRT Use Timer1;
  131.         T1_CT = 0;                //Timer1 set As Timer
  132.         T1x12 = 1;                //Timer1 set as 1T mode
  133.                 TMOD &= ~0x30;  //Timer1_16bitAutoReload;
  134.                 TH1 = dat >> 8;
  135.                 TL1 = dat;
  136.         ET1 = 0;    //禁止中断
  137.                 TR1  = 1;
  138.         }
  139.         /*************************************************/
  140.         SCON = (SCON & 0x3f) | 0x40;    //UART1模式, 0x00: 同步移位输出, 0x40: 8位数据,可变波特率, 0x80: 9位数据,固定波特率, 0xc0: 9位数据,可变波特率
  141. //  PS  = 1;    //高优先级中断
  142. //        ES  = 1;    //允许中断
  143.         REN = 1;    //允许接收
  144.         P_SW1 &= 0x3f;
  145.         P_SW1 |= 0x00;      //UART1 switch to, 0x00: P3.0 P3.1, 0x40: P3.6 P3.7, 0x80: P1.6 P1.7, 0xC0: P4.3 P4.4
  146. }
  147. //========================================================================
  148. // 函数: void UART1_DMA_Interrupt (void) interrupt 50/51
  149. // 描述: UART1 DMA中断函数
  150. // 参数: none.
  151. // 返回: none.
  152. // 版本: VER1.0
  153. // 日期: 2021-5-8
  154. // 备注:
  155. //========================================================================
  156. void UART1T_DMA_Interrupt(void) interrupt DMA_UR1T_VECTOR
  157. {
  158.         if (DMA_UR1T_STA & 0x01)        //发送完成
  159.         {
  160.                 DMA_UR1T_STA &= ~0x01;
  161.         }
  162.         if (DMA_UR1T_STA & 0x04)        //数据覆盖
  163.         {
  164.                 DMA_UR1T_STA &= ~0x04;
  165.         }
  166. }
  167. void UART1R_DMA_Interrupt(void) interrupt DMA_UR1R_VECTOR
  168. {       
  169.         if (DMA_UR1R_STA & 0x01)        //接收完成
  170.         {
  171.                 DMA_UR1R_STA &= ~0x01;
  172.                 DmaRxFlag = 1;
  173.                 //开始发送数据
  174.                 DMA_UR1T_AMT = DMA_UR1R_AMT;                        //数据长度
  175.                 DMA_UR1T_CR |= 0x60;                //开始发送数据
  176.         }
  177.         if (DMA_UR1R_STA & 0x02)        //数据丢弃
  178.         {
  179.                 DMA_UR1R_STA &= ~0x02;
  180.         }
  181. }
复制代码
执行结果:
1718267925000.png


当以DMA方式接收串口数据时,能否增加配置,循环接收数据,比如我缓存区设100,接50就产生就接收完成,开始接收标志位不清零,模块还可以继续接收数据,把接收到的数据保存到缓存区后面50字节中,如此循环接收

还有,DMA本身是为了减少串口中断次数的,而示例中有个超时程序,5ms没有接收到数据则停止,这样的话反而得开3个中断,定时器中断,串口中断,DMA中断,比没有DMA方式所开的中断更多了

这时能不能内部做个超时处理呢?比如缓存区设为100,接收到第1个字符开始记时,自动按波特率算出接收1个字符需要的时间,中间有超过n个字符的时间没有收到数据则中断,让用户去处理数据,n可以配置0,1,2,3


点评

这个代码用了比较久了,已稳定,可以参照一下, UART1_DMA 目标机型, STC32G  详情 回复 发表于 2024-6-14 08:30
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-04-30 07:46:22

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-6-14 08:30:32 | 显示全部楼层
乘*** 发表于 2024-6-13 16:50
最近在学习这系列视频,正好学了DMA读写串口的视频,发现DMA方式串口接收数据的时候,很容易丢失数据啊。 ...

这个代码用了比较久了,已稳定,可以参照一下, UART1_DMA  目标机型, STC32G

UART1.rar (2.41 KB, 下载次数: 132)

回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:22 , Processed in 0.149268 second(s), 111 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表