神农鼎
发表于 2023-11-16 20:39:12
STC现代8051,STC新型主流8051的中断响应过程
STC8H8K64U / STC8A8K64D4 / STC8C / STC8G 等
神农鼎
发表于 2023-11-16 20:43:14
STC32G12K128/STC32G8K64现代STC32位8051
CosyOS
发表于 2023-11-16 21:26:55
神农鼎 发表于 2023-11-16 20:43
STC32G12K128/STC32G8K64现代STC32位8051
感谢!{:4_196:}
CosyOS
发表于 2023-11-16 22:20:30
终于找到原因了!为何用 STC8A8K 测试时,PendSV 使用 TM3、TM4 会死机?
原因是:当TM3/TM4中断关闭时,中断标志位置1后再开启中断,则无法响应中断。
也就是说,必须在中断已经开启的前提下,中断标志位再置1,才能响应中断。
具体验证过程不再说明了。
而采用各外部中断、TM1中断,就不会有这个问题。
下面是 CosyOS-II 退出任务临界区函数:
注释说明:PendSV 用 TM4,当调用此函数时,已在任务临界区中,即 TM4 中断已为关闭状态
void su_exit_critical(void)
{
s_taskcri_counter--;
if(!s_taskcri_counter){
if(s_sign_scheduling){
mPendSV_Set; // 触发PendSV:AUXINTIF |= T4IF;
mSysIRQ_Enable; // 先开TM0中断,再开PendSV中断:ET0 = 1; IE2 |= ET4;
while(s_sign_scheduling); // 由于无法进入TM4中断,程序将永远在这里循环。
}
else{
mSysIRQ_Enable;
}
}
}
为何无法进入TM4中断?原因也找到了,当TM4中断关闭时,AUXINTIF |= T4IF 会失效。
那可能有人会说,可以先开PendSV中断,再触发PendSV不就行了吗?
答案是不行的,原因我就不多说了,总之是不行。
所以,只能选择可行的中断做为PendSV。
-- END --
CosyOS
发表于 2023-11-16 23:29:23
CosyOS 发表于 2023-11-16 22:20
终于找到原因了!为何用 STC8A8K 测试时,PendSV 使用 TM3、TM4 会死机?
原因是:当TM3/TM4中断关闭时,中 ...
你说的有道理
tzz1983
发表于 2023-11-21 12:26:28
本帖最后由 tzz1983 于 2023-11-21 12:34 编辑
昨天晚上利用休息时间,欣赏了一下CosyOS的作品,感觉很好,学到很多东西{:lol:}
本来想顺着着main函数走一圈,看看到底都做了些啥, 结果发现貌似没那么简单, 宏的定义层次有点深啊,哈哈
打算今晚继续研究, 暂时放弃读原码, 先学会怎么用再说!
有几个疑问:(CosyOS-II-STC32G版)
1.作者加了START251.A51
IF XDATALEN <> 0
MOV DPTR,#WORD0 XDATASTART
MOV WR6,#XDATALEN
CLR A
XDATALOOP: MOVX @DPTR,A
INC DPTR
DEC WR6,#1
JNE XDATALOOP
ENDIF
这是清零64K xdata的节奏啊,实际只有8K, 会不会有点浪费时间?(刚才看错了,把地址当成数量 ,实际清零8K)
2.我以前都不加文件START251.A51,不加会有什么影响?
3. 项目没有设置全局重入和REMOVEUNUSED,只设置了NOOVERLAY命令。 这样没问题吗?
CosyOS大侠哥哥, 来走一波解释一下看看
CosyOS
发表于 2023-11-21 13:28:32
tzz1983 发表于 2023-11-21 12:26
昨天晚上利用休息时间,欣赏了一下CosyOS的作品,感觉很好,学到很多东西
本来想顺着着main函数走一圈,看 ...
这里涉及的问题比较多,容我慢慢道来。
CosyOS
发表于 2023-11-21 14:18:59
本帖最后由 CosyOS 于 2023-11-21 16:11 编辑
tzz1983 发表于 2023-11-21 12:26
昨天晚上利用休息时间,欣赏了一下CosyOS的作品,感觉很好,学到很多东西
本来想顺着着main函数走一圈,看 ...
1、加这个启动文件的目的就是为了内存清零,当然不加也可,这是我的个人习惯。
2、一般情况下内存不清零也不会有问题。
3、有时会有某些全局变量,我们希望它初始化时为零,这时可以考虑以下三种方式:
方法一、定义变量时,直接赋初值为零。
方法二、启动文件内存清零。
方法三、系统初始化时,赋初值为0或用 memset 清零。
方法一适用于一般变量,即占用内存空间较小的变量。
方法二、方法三适用于大型变量,即占用内存空间较大的变量,如大型的数组、结构体等。
为何要如此应用?因为在定义变量时直接赋初值,会增加额外的常量,并占用常量区即flash,这个变量有多大增加的常量就有多大。
而采用方法二、方法三就不会有这个副作用。
如分别仅定义变量和定义并赋初值进行对比:
char u_array; // 未赋初值
char u_array = {0}; // 整个数组赋初值为0
用户可自行对比测试,看编译后有什么区别。
仅设置了NOOVERLAY,以前是考虑为了方便测试“私信”功能,我计划在下一版本中改为“Generate reentrant functions” + “REMOVEUNUSED”。
关于251,CosyOS提供了两种方案:
方案一、“Generate reentrant functions” + “REMOVEUNUSED”。
方案二、“NOOVERLAY” + “reentrant” + “手动移除未使用”。
这个具体区别可参考 开发流程.md。
CosyOS
发表于 2023-11-21 15:37:55
本帖最后由 CosyOS 于 2023-12-5 13:37 编辑
1、系统初始化后,内存区域未必是0。
如果我们希望某些内存区域或全局变量初始化后为零,则必须采取相应的清零操作,如启动文件内存清零、变量赋初值为0等方式,
否则初值未必为零,可能会导致应用错误。
2、某些全局变量,我们需要初始化为特定值(非0),包括基本类型的变量、数据结构(数组、结构体等)。
我通常的做法是:
1、启动文件内存清零。
2、某些全局变量,如果需要初始化为特定值,在定义时直接赋初值。
CosyOS
发表于 2023-11-21 15:37:55
本帖最后由 CosyOS 于 2023-12-5 13:37 编辑
1、系统初始化后,内存区域未必是0。
如果我们希望某些内存区域或全局变量初始化后为零,则必须采取相应的清零操作,如启动文件内存清零、变量赋初值为0等方式,
否则初值未必为零,可能会导致应用错误。
2、某些全局变量,我们需要初始化为特定值(非0),包括基本类型的变量、数据结构(数组、结构体等)。
我通常的做法是:
1、启动文件内存清零。
2、某些全局变量,如果需要初始化为特定值,在定义时直接赋初值。