找回密码
 立即注册
查看: 1006|回复: 109

STC单片机 uC/OS-II核心技术(12):关于临界区保护和函数可重入的测试题

[复制链接]

该用户从未签到

63

主题

660

回帖

1万

积分

荣誉版主

积分
10806
发表于 2024-3-22 12:10:28 | 显示全部楼层 |阅读模式
本帖最后由 杨为民 于 2024-3-31 11:05 编辑

说明:这是LAOXU考我的测试题,不是我考大家的测试题,2楼是我的答案。由于这个问题很典型,我希望大家也来参与而已。


(1)荣誉坛主LAOXU在自己的帖子里出了一道测试题:(《C51 和 C251 标准库的区别 》“https://www.stcaimcu.com/forum.p ... =7348&extra=&page=1”)
就这么一个简单例子, 主程序执行  strncpy函数 在加载参数变量时(相当于 OS系统的临界区), 被中断打断了,
当执行中断中的 strncpy函数,  在同一 ram地址上, 复盖加载参数变量,
中断返回后, 主程序的 strncpy函数 加载的参数变量, 会被改变!
分析汇编代码, 就能得出这一结论.
char  a1[ ]={1,2,3,4,5,6,7,8,9,0};
char  a2[ ]={9,8,7,6,5,4,3,2,2,0};
char  bb[10],cc[10];
void int1(void ) interrupt         1
{
  strncpy (bb, a1, 8);
}
void main(void)
{  do{
   strncpy (cc, a2, 8);
   }while(1);
}
LAOXU_01.jpg
LAOXU_02.jpg

(2)下面红字是他给我出的题目
红框中的 RAM地址重叠( strncpy函数 通过 RAM 加载参数变量), 怎么解决?
那怕优化全部取消(优化级0), 也没法解决, 这就是不可重入函数, 头大之处.
您老有办法解决吗? 静等回复.”

(3)上面就是LAOXU给我出的题目,指明要我回答,我回答后他不满意,追着要我回答“你老跑题啦~~~ 咱们现在说 keil C51怎么解决.
对于那么常见的问题的答案,我实在不愿意回答他,所以我说“我不愿意在这里跟你说,你问你老师去”
(4)有网友建议“那就重开一贴,细细讲解么”。我觉得这个建议很好,不如就放出来供大家讨论,先由大家来讨论,然后我再给出我的解决方法。


(5)怎么解决LAOXU提出的这个问题(红字的部分),各位坛友,大家都来说说,其实解决方法很简单,大家尽量往简单里猜


===============================================
(6)LAOXU把题目难度提高了,要求要有4个不同优先级的中断:
void int0(void ) interrupt  0  // 优先级 0
{
  strncpy (bb0, a0, 8);
}

void int1(void ) interrupt  1  // 优先级 1
{
  strncpy (bb1, a1, 8);
}

void int2(void ) interrupt  2  // 优先级 2
{
  strncpy (bb2, a2, 8);
}


void int3(void ) interrupt  3  // 优先级 3
{
  strncpy (bb3, a3, 8);
}



void main(void)
{  do{
   strncpy (cc, a2, 8);
   }while(1);
}

(7)LAOXU认为除了用他会的用汇编语言重新编写“strncpy”函数,没有其他方法可解决,他论证说:
像我 8楼的题目, 底层可实行关中断, 在低级中断中, 就不能用 关中断之法了, 因为一关中断,
影响所有高一层次的中断响应(相当于关闭所有高级中断, 同级或低级中断没影响), 只能采用压栈保护
受影响的那几个 RAM, 但问题是, 这 RAM地址是浮动的(受程序大小及内容影响), 随时可能变更
具体地址, 如何可靠有效保护这几个  RAM ?
当然, 每次编译后, 核对修改这几个保护 RAM地址也行, 需反复编译核对, 确保正确

(8)对于LAOXU新提出的增加了难度的这个问题,各位坛友,大家都来说说除了在C51里重新编写“strncpy”函数的方法外怎么解决,其实解决方法很简单,大家尽量往简单里猜。
回复 送花

使用道具 举报

该用户从未签到

63

主题

660

回帖

1万

积分

荣誉版主

积分
10806
 楼主| 发表于 2024-3-22 12:19:53 | 显示全部楼层
本帖最后由 杨为民 于 2024-3-23 22:57 编辑

一、最直观的解决方案
1)对于开始的简单题目,LAOXU的方法是最简单的方法,在底层(主程序), 调用前先关中断, 执行调用 strncpy , 调用后再打开中断”。
写成程序是这样的:
void main(void)
{  do{
    EA=0;
   strncpy (cc, a2, 8);
   EA=1;
   }while(1);
}
点评:这个方法真的是最直观、最简单可行和最实用的方法。
2)对于LAOXU自己的后面的高难度题,LAOXU承认除了重新编写函数使其成为可重入的之外自己没有其他方法:对, 我没有好的办法, 请你老指教.事实上很多时候, 如杨老师所言: "其实解决方法很简单", 只是, 他知道你, 你不认识他.
点评:对于LAOXU的回答,我很意外。他既然找到了简单题目的最简单解决方法,为什么不举一反三给出自己的后面的高难度题的最简单解决方法呢?

4最直观的解决方法就是把上面的方法重复5
void int0(void )interrupt  0  // 优先级 0
{
    EA=0;
  strncpy (bb0, a0, 8);
   EA=1;
}

void int1(void )interrupt  1  //
优先级 1
{
    EA=0;
  strncpy (bb1, a1, 8);
   EA=1;
}

void int2(void )interrupt  2  //
优先级 2
{
    EA=0;
  strncpy (bb2, a2, 8);
   EA=1;
}

void int3(void )interrupt  3  //
优先级 3
{
    EA=0;
  strncpy (bb3, a3, 8);
   EA=1;
}

void main(void)
{  do{
    EA=0;
   strncpy (cc, a2, 8);
   EA=1;
   }while(1);
}

二、给新手的教学方案
1)我去请教在大学教计算机基础课的老师,如何教懂新手解决这种在两个地方同时调用不可重入函数的问题,他打了给比方:
不可重入函数就像不能同时在两个地方炒菜的厨师一样,如果正在一个地方炒菜没有结束,就被叫到另外一个地方炒菜,那么等那边后菜做好再回来,前面的菜早就糊了。
解决的方法是在家里炒菜的时候关掉手机,不接收出门炒菜的请求就行,等把家里的菜炒完再打开电话,然后接到请求出门去炒菜,或者留在家里继续炒菜。
这个方案写成程序如下:
void int1(void ) interrupt        1
{
  出门炒菜:--> strncpy(bb, a1, 8);
}
void main(void)
{  do{
    关闭电话: --> EA=0;
   在家炒菜:--> strncpy(cc, a2, 8);
   打开电话: --> EA=1;
   }while(1);
}

2)我再问对于高难度的题目,如何教懂新手。他说按照“专心做完一件事情后再做另一件事情”的原则办就行了。
就像把熊猫装进冰箱一样,分三步:关闭手机、做菜、打开手机。
void int0(void ) interrupt        0
{
    关闭电话: --> EA=0;
  出门炒菜:--> strncpy(bb0, a0, 8);
   打开电话: --> EA=1;
}
void int1(void ) interrupt        1
{
    关闭电话: --> EA=0;
  出门炒菜:--> strncpy(bb1, a1, 8);
   打开电话: --> EA=1;
}
void int2(void ) interrupt         2
{
    关闭电话: --> EA=0;
  出门炒菜:--> strncpy(bb2, a2, 8);
   打开电话: --> EA=1;
}
void int3(void ) interrupt         3
{
    关闭电话: --> EA=0;
  出门炒菜:--> strncpy(bb3, a3, 8);
   打开电话: --> EA=1;
}

void main(void)
{  do{
    关闭电话: --> EA=0;
   在家炒菜:--> strncpy(cc, a2, 8);
   打开电话: --> EA=1;
   }while(1);
}

==== 第2部分 =================================================
三、可嵌套的关闭总中断的临界区保护方法
1上面的解决方法从OS的角度看是不完美的,因为这种方法是不可嵌套的。对于像题目中的解决某些库函数不可重入问题是没有问题的,但是对于解决用户自己编写的大型程序却是不够的,需要找到一些通用的可以嵌套的方法来
2)对于上面的程序例子,用计算机操作系统术语来说,从“main”函数开始的程序被称为后台任务,每一个中断服务程序ISR被称为一个前台任务。因此裸机编程只要包含中断程序,本身就是属于前后台多任务OS”,所以本文的题目也可以用操作系统OS的方法来解决。
3)像上面提到的不可重入函数,意思是如果两个任务同时调用该函数,则会产生冲突。因此这种不可重入函数属于OS理论中的“临界区”的一种。按照OS理论,要使用临界区,则必须进行“临界区保护”
4)具体地说,进入临界区之前,必须执行一段“进入临界区保护”的程序,这段程序的作用是禁止其他程序打断下面临界区程序的执行。比如上面程序中的“关闭总中断EA=0”就是一种“进入临界区保护”的程序,执行这句程序后,总中断被关闭(除不可屏蔽中断外)后,不会产生中断,后面的不可重入函数也也就不会被重入了,换言之,临界区得到保护了。
同样的,在临界区代码执行完后,也必须执行一段“退出临界区保护”的程序,这段程序的作用是解除保护措施,提供其他中断程序执行的机会。比如上面程序中的“打开总中断EA=1”就是一种“退出临界区保护”的程序,执行这句程序后,总中断被打开后,其他中断就能正常发生和执行了。
5)如果按照uC/OS-II RTOS的规则,用函数OS_ENTER_CRITICAL()来表示“进入临界区保护”的程序,用函数OS_EXIT_CRITICAL()来表示“退出临界区保护”的程序,那么上面最直观的解决方法可以写成下面形式:
void int0(void )interrupt  0  // 优先级 0
{
  OS_ENTER_CRITICAL();       //进入临界区保护
  strncpy (bb0, a0, 8);
OS_EXIT_CRITICAL ();       //退出临界区保护
}

void int1(void ) interrupt  1  //
优先级 1
{
OS_ENTER_CRITICAL();       //进入临界区保护
  strncpy (bb1, a1, 8);
OS_EXIT_CRITICAL ();       //退出临界区保护
}

void int2(void )interrupt  2  //
优先级 2
{
OS_ENTER_CRITICAL();       //进入临界区保护
  strncpy (bb2, a2, 8);
OS_EXIT_CRITICAL ();       //退出临界区保护
}



void int3(void )interrupt  3  //
优先级 3
{
  OS_ENTER_CRITICAL();       //进入临界区保护
  strncpy (bb3, a3, 8);
  OS_EXIT_CRITICAL ();       //退出临界区保护
}


void main(void)
{  do{
  OS_ENTER_CRITICAL();       //进入临界区保护
   strncpy (cc, a2, 8);
  OS_EXIT_CRITICAL ();       //退出临界区保护
   }while(1);
}

6)下面我以网友“tzz1983”移植的uC/OS-II为例来介绍“可嵌套的临界区保护方法”。下面的程序来源于《uGFX/GUI + uC/OS-II@STC32GuGFX/GUI@STC32G裸机》(https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7130&extra=page%3D1),有兴趣的网友可以去学习,如果有不清楚的地方,也请到这个主贴去提问,由主家亲自为你解答。
7uC/OS-II中的临界区保护方法程序见下面:
//进入临界段的方法(推荐3)
#define  OS_CRITICAL_METHOD   3     
//OS_CRITICAL_METHOD= 1 :直接使用处理器的开关中断指令来实现 (使用限制: 不支持嵌套, 调用OS服务前, 要保证EA=1)
#ifOS_CRITICAL_METHOD == 1                    /* 调用OS服务, 可能会使EA意外的被打开, 所以, 调用OS服务前一刻, 要保证EA=1 */
#define  OS_ENTER_CRITICAL()    EA=0            /* 使用限制: 不支持嵌套, 进入任务前,保证不开所有分中断, 即使EA被意外打开也不会实际有可响应的中断 */
#define  OS_EXIT_CRITICAL()     EA=1
#define  OS_TASK_SW()           {_bIE__=IE|0X80; OSCtxSw(); return;}
#endif
//OS_CRITICAL_METHOD= 2 :利用全局变量保存和恢复CPU的状态,最多8次嵌套   
#ifOS_CRITICAL_METHOD == 2
voidOS_CPU_SR_Save2(void);
voidOS_CPU_SR_Restore2(void);
extern  INT8U _bEA_8BIT_;          //临界区模式2全局保存8EA
#define  OS_ENTER_CRITICAL()    OS_CPU_SR_Save2()           /* 使用时可省去定义变量, 用着方便. 最多嵌套8, 效率略低于模式3, 支持函数内嵌套 */
#define  OS_EXIT_CRITICAL()     OS_CPU_SR_Restore2()
#define  OS_TASK_SW()          {if(_bEA_8BIT_&0x80){_bEA_8BIT_<<=1;_bIE__=IE|0X80;}else{_bEA_8BIT_<<=1;_bIE__=IE;}OSCtxSw(); return;}                     
#endif
//OS_CRITICAL_METHOD= 3 :状态字保存在局部变量cpu_sr
#ifOS_CRITICAL_METHOD == 3
#define  OS_ENTER_CRITICAL()    {cpu_sr=((!_testbit_(EA))?0X00:0X80);}  /* 直接用宏插入C语言, 省去调用过程. 可嵌套, 但不支持函数内嵌套 */
#define  OS_EXIT_CRITICAL()     {IE|=cpu_sr;}
#define  OS_TASK_SW()           {_bIE__=IE|cpu_sr; OSCtxSw();return;}
#endif
8)其中临界区保护方法“OS_CRITICAL_METHOD如果选择1,就是前面的直接关闭和打开总中断的方法
#ifOS_CRITICAL_METHOD == 1                    /* 调用OS服务, 可能会使EA意外的被打开, 所以, 调用OS服务前一刻, 要保证EA=1 */
#define  OS_ENTER_CRITICAL()    EA=0            /* 使用限制: 不支持嵌套, 进入任务前,保证不开所有分中断, 即使EA被意外打开也不会实际有可响应的中断 */
#define  OS_EXIT_CRITICAL()     EA=1
9)其中临界区保护方法“OS_CRITICAL_METHOD如果选择2,则是一种最大可以嵌套8层的方法,具体的方法可以去主贴看说明和讨论。
10)其中临界区保护方法“OS_CRITICAL_METHOD如果选择3,则是一种利用局部变量保存总中断状态、嵌套次数不受限制的方法,具体的方法可以去主贴看说明和讨论。
值得一提的是在STM32F单片机上的常见的RTOS包括FreeRTOSuC/OS-IIIRT-THREAD等,缺省的都采用这种方法。
11特别说明:这种临界区保护方法程序不依赖于RTOS,可以独立出来,直接应用到裸机编程中。有兴趣的读者可以从主贴中下载程序,然后把这部分孤立出来在自己的程序中试试。

==== 第3部分 =================================================
四、不关闭总中断的临界区保护方法
1)前面介绍的关闭总中断的临界区保护方法有一个明显的弊病,就是一竿子打死一船人:少数几个中断出现临界区保护(比如题目中的库函数不可重入问题)需求,就关闭所有的中断,这不合理。尤其是在低优先级中断中或者在后台任务“main”函数中关闭总中断,则高优先级的、甚至是不涉及临界区的中断就被屏蔽了,要等低优先级临界区完成后才被允许中断,对单片机系统的中断实时响应影响十分严重
2)那么不关闭总中断,只关闭涉及到的中断(系统的或者用户的中断)来进行临界区保护行不行?网友CosyOS给出了这样一个成功例子《全局不关总中断的RTOS / CosyOS-II for STC MCUhttps://www.stcaimcu.com/forum.php?mod=viewthread&tid=1807&extra=page%3D1)。
CosyOS中,在进入临界区保护后,只关闭系统中断,不关闭总中断,这样就不会影响到其他中断的实时响应了。下面给出的只是一个简化的裸机编程例子,网友有涉及到此项技术的在RTOS中如何实现和应用的具体细节的问题可以去他的主贴提问,由主家亲自为你解答。
3)由于本文的题目只涉及到中断0到中断3,按照CosyOS的思路,那么我们可以这样来编写临界区保护函数
void  OS_ENTER_CRITICAL(void){
       EX0=0;
       ET0=0;
       EX1=0;
       ET1=0;
}
void  OS_EXIT_CRITICAL (void){
       EX0=1;
       ET0=1;
       EX1=1;
       ET1=1;
}
4)将这两个进入和退出临界区保护的函数带到前面的程序中,就可以解决库函数不可重入的问题。因为进入临界区保护后这四个中断就不会再发生了,题目中的库函数就不会被重入了
5)总结:本文介绍了从简单的关闭总中断,到可嵌套的关闭总中断,到上面这个不关闭总中断只关闭涉及的局部中断方法,每个方法各有优越性,适不同的应用场合。
上面的关闭局部中断的方法仍然是不可嵌套的,要实现可嵌套的只关闭局部中断的临界区保护方法,只需要参照上面关闭总中断的方法继续编写程序就可以实现了。
本题目在中断中正常使用不可重入函数的方法属于典型的OS临界区保护范畴,除了上面介绍的三种方法,OS理论库中还有其他的解决方法,只是实现程序较复杂而已。



1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
回复 支持 1 反对 0 送花

使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 16:10:32 | 显示全部楼层
    对老司机来说(包括我), 什么关中断, 上锁 都不在话下, 根本没问题.

    我想表达的是对新手, 易犯错.

    51  OS 和 其他 CPU 的 OS 相比.
    要好多地方要特别注意, 需增加额外的命令加以保护, 其他 CPU 不用 !
    1. 不可重入特征(包括好多内部库函数)
    2. 通过 内部 RAM传递参数
    3. 指针函数要指定(通知编译器).

    这些都是 51构架特有的缺点(短板)

    对新手来说, 你想学 51 OS系统, 上述问题需重点注重考虑, 否则易 产生 BUG.

    其他 单片机, 如 251系(STC32), 没有上述问题, 只有少量不可重入的特定函数, 可通过关中断, 上锁, 互斥等手段加以控制, 不易犯错.

    点评

    (1)既然新手不知道哪些C51的标准库函数是不可重入的,而你这个老司机知道,何不把C51的标准库里哪些函数是不可重入的知识在论坛里奉献出来,别藏着掖着地去“危言耸听,吓唬大家” (2)既然新手不知道,而你这个  详情 回复 发表于 2024-3-22 17:14
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 16:29:13 | 显示全部楼层
    像 你老搞的 扩展 X51指令集, 后 2个扩展寄存器 放在 RAM(10H-17H)中, 不但 OS系统要保护 RAM(10H-17H) , 每个中断中使用, 都要特意保护 RAM(10H-17H) .

    难道不显麻烦吗?  新手不是更容易犯错吗?

    放在 受 编译器 保护的 寄存器中 多好啊, 省去一大堆麻烦, 新手也不需要了解这个那个注意事项, 更不容易犯错.

    点评

    我都不急,你急什么?怀疑别人的孩子不好养,这个心操得有点大  详情 回复 发表于 2024-3-22 17:22
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 17:13:50 | 显示全部楼层
    对 同等功能的 51 和 251 , STC 芯片 价格相差 5毛 左右. 251(STC32G) 比 51(STC8H) 性能更好速度更快.

    对于 上 OS系统的 产品来话, 本身功能强大, 也不要再乎 这 5毛钱了.

    所以推荐 朋友 们, 直接上 251(STC32G) 省去一大堆麻烦, 不用注意这注意那, 调试简单, 产品不易出 BUG, 可靠性稳定性也高.

    早期是没得选, 只有 51, 现在是能上 OS的单片机众多, 没必要吊死在 51这棵树上.

    当然, 一般不用 OS的产品, STC51 性价比还是不错的, 能用上的话, 比 251(STC32G) 省 5毛.
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    63

    主题

    660

    回帖

    1万

    积分

    荣誉版主

    积分
    10806
     楼主| 发表于 2024-3-22 17:14:46 | 显示全部楼层
    本帖最后由 杨为民 于 2024-3-22 17:24 编辑
    LAOXU 发表于 2024-3-22 16:10
    对老司机来说(包括我), 什么关中断, 上锁 都不在话下, 根本没问题.

    我想表达的是对新手, 易犯错.

    (1)既然新手不知道哪些C51的标准库函数是不可重入的,而你这个老司机知道,何不把C51的标准库里哪些函数是不可重入的知识在论坛里奉献出来,别藏着掖着地去“危言耸听,吓唬大家”
    (2)既然
    新手不知道,而你这个老司机知道怎么解决“红框中的 RAM地址重叠( strncpy函数 通过 RAM 加载参数变量)”,那请你在这里把你的解决方法告诉大家,而不是藏着掖着地去“危言耸听,吓唬大家”

    做一个“传道受业解惑”的师者,善莫大焉。请君从善

    点评

    最简单的方法, 在底层(主程序)中, 调用前先关中断, 执行调用 strncpy , 调用后再打开中断  详情 回复 发表于 2024-3-22 17:33
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    63

    主题

    660

    回帖

    1万

    积分

    荣誉版主

    积分
    10806
     楼主| 发表于 2024-3-22 17:22:51 | 显示全部楼层
    LAOXU 发表于 2024-3-22 16:29
    像 你老搞的 扩展 X51指令集, 后 2个扩展寄存器 放在 RAM(10H-17H)中, 不但 OS系统要保护 RAM(10H-17H) ,  ...

    我都不急,你急什么?怀疑别人的孩子不好养,你这个心操得有点大

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 17:28:58 | 显示全部楼层
    既然杨老师要讨论, 顶楼的题太简单了, 只有2次调用.

    现改成, 51有 4个中断级, 每个中断优先级中 有一次调用, 再加上底层一次调用, 共 5个层次的调用.

    如何做到互不干扰 ?

    最简单通用方法就是把这个函数写成可重入的, 无论 N次调用都不会出问题.

    现在前提是这个函数是不可重入的, 求解决方案, 不用编程, 讲述一下实现原理即可.

    点评

    我已经把新题目放在1楼了,请检查下是否符合你的要求  详情 回复 发表于 2024-3-22 18:56
    谢谢回答。 (1)你想提高题目的难度,我成全你,我修改后放在在顶楼。 (2)你给出的方法是“把这个函数写成可重入的, 无论 N次调用都不会出问题”。虽然你的这个方法也适用于新题目,但是你的这个方法对于新手太  详情 回复 发表于 2024-3-22 18:16
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 17:33:14 | 显示全部楼层
    杨为民 发表于 2024-3-22 17:14
    (1)既然新手不知道哪些C51的标准库函数是不可重入的,而你这个老司机知道,何不把C51的标准库里哪些函数 ...

    最简单的方法,

    在底层(主程序)中, 调用前先关中断, 执行调用 strncpy , 调用后再打开中断

    点评

    谢谢。 (1)为了新手能够理解下面将你的方法“最简单的方法,在底层(主程序)中, 调用前先关中断, 执行调用 strncpy , 调用后再打开中断”写成程序: void main(void) { do{ EA=0; strncpy (cc, a2, 8); E  详情 回复 发表于 2024-3-22 18:38
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    5 天前
  • 签到天数: 137 天

    [LV.7]常住居民III

    37

    主题

    872

    回帖

    3990

    积分

    荣誉版主

    积分
    3990
    发表于 2024-3-22 18:15:34 | 显示全部楼层
    像我 8楼的题目, 底层可实行关中断, 在低级中断中, 就不能用 关中断之法了, 因为一关中断,
    影响所有高一层次的中断响应(相当于关闭所有高级中断, 同级或低级中断没影响), 只能采用压栈保护
    受影响的那几个 RAM, 但问题是, 这 RAM地址是浮动的(受程序大小及内容影响), 随时可能变更
    具体地址, 如何可靠有效保护这几个  RAM ?

    当然, 每次编译后, 核对修改这几个保护 RAM地址也行, 需反复编译核对, 确保正确

    点评

    自言自语 自已回复自已, 上面我所言, "在低级中断中, 就不能用 关中断之法了, 因为一关中断,影响所有高一层次的中断响应(相当于关闭所有高级中断, 同级或低级中断没影响)" 我是坚决不采用不推荐这种方法的, 我非  详情 回复 发表于 2024-3-23 16:54
    =============================================== (6)LAOXU把题目难度提高了,要求要有4个不同优先级的中断: void int0(void ) interrupt 0 // 优先级 0 { strncpy (bb0, a0, 8); } void int1(void ) inter  详情 回复 发表于 2024-3-22 23:16
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-8 15:10 , Processed in 0.097886 second(s), 68 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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