stc-xuewei 发表于 2025-5-28 11:00:44

用AiCube生成的工程中,有printf字符发送重定向函数,编译没有报警错误。当升级为CosyOS工程时,编译时有错误提示。我仿照前面的CosyOS工程试例,单独建一个C文件,将putchar()函数放进来,然后在函数的上面复制这一句#pragma functions(static),这样再编译时就没有错误提示了。这是什么原因呢?

CosyOS 发表于 2025-5-28 18:17:37

stc-xuewei 发表于 2025-5-28 11:00
用AiCube生成的工程中,有printf字符发送重定向函数,编译没有报警错误。当升级为CosyOS工程时,编译时有错 ...
启用全局可重入:


“1”是当 C251版本 >= 2.00 时,这些函数都声明了 static 属性,包括 putchar;
“2”是当 C251版本 <   2.00 时,我们不必管它,因为我们现在用的版本都会大于2.00。

启用全局可重入后:
1、如果你的 putchar 不做更多修饰,默认为 reentrant 属性;
2、如果你的 putchar 所在的C文件中,包含了 stdio.h,你的 putchar 也必须定义为 static 属性,
否则,声明和定义不同,导致报错,

3、如果你的 putchar 所在的C文件中,未包含 stdio.h,你的 putchar 无论是否定义为 static,都不会报错。
但是 你的 putchar 仍然必须定义为 static,否则它不会被编译。
因为 你的 putchar 未定义 static,不能满足使用要求,
此时 printf 仍然会调用 标准库中的 putchar,而非你的 putchar,
而后 你的 putchar 被 REMOVEUNUSED 移除掉了。

结论:
1、如果未启用全局可重入,用户的 putchar 可以普通定义方式,也可以定义 static 属性。
2、如果启用了全局可重入,用户的 putchar 必须 定义 static 属性。

方法1:
缺点是 putchar 之后的所有函数也一并定义了 static 属性。
#pragma functions(static)
char putchar(char c)
{

}

方法2:
只有 putchar 会被定义 static 属性,对后续其它函数无影响。
#pragma SAVE
#pragma functions(static)
char putchar(char c)
{

}
#pragma RESTORE




CosyOS 发表于 2025-5-28 18:43:02

sdwys 发表于 2025-5-27 17:44
/**
\brief      任务节点(控制块)
\details    CosyOS 的 任务节点 即 任务控制块,包含了任务所需的 ...

注意,在控制块结构体中,用 struct s_tasknode_ts 是在多次定义指针变量,而非实体。
这就是链表。。。

stc-xuewei 发表于 2025-5-29 23:48:30

我动态创建了2个任务,下载后不运行。但将任务改成静态创建后,却能正常运行。不知什么原因?后面附有工程文件。

CosyOS 发表于 2025-5-30 14:38:15

stc-xuewei 发表于 2025-5-29 23:48
我动态创建了2个任务,下载后不运行。但将任务改成静态创建后,却能正常运行。不知什么原因?后面附有工程 ...
你只需适当调整一下内存池就可以了,
把内存池指针改小一点,哪怕改成“2716”都能跑起来。

关于这个问题的原因我需要再深入研究一下,恐怕没有那么简单。

CosyOS 发表于 2025-5-30 15:17:33

stc-xuewei 发表于 2025-5-29 23:48
我动态创建了2个任务,下载后不运行。但将任务改成静态创建后,却能正常运行。不知什么原因?后面附有工程 ...
根本原因找到了,是 Starter 任务栈小了。
任务动态创建后,启动任务需要更大的任务栈,
syscfg.h 中,把 Starter 任务栈 设置大一些就好了,不必再调整内存池指针。




Istar_MCU 发表于 2025-6-2 09:56:07

{:guzhang:}

一束光的旅程 发表于 2025-6-3 23:31:26

我是用usbcdc库添加usb_init()就出现L127,L128错误,注释掉后就能正常编译。单独使用usbcdc程序是正常的。想请教一下老师们这个问题怎么解决。

一束光的旅程 发表于 2025-6-4 18:27:06

一束光的旅程 发表于 2025-6-3 23:31
我是用usbcdc库添加usb_init()就出现L127,L128错误,注释掉后就能正常编译。单独使用usbcdc程序是正常的。 ...

自己回复一下,参考了论坛坛友的一个解决方法,如下图所示:

CosyOS 发表于 2025-6-5 15:35:39

一束光的旅程 发表于 2025-6-4 18:27
自己回复一下,参考了论坛坛友的一个解决方法,如下图所示:
这个问题的根源在于,在 Keil C251/A251 下,在不同条件下,汇编函数的命名法是不同的。

这些条件具体包括了 Code Rom Size(Large、Huge)、函数属性(reentrant、static)等,
它们将影响汇编函数的尾缀命名规则。
总之在不同情况下,汇编函数名称后面可能需要添加不同的尾缀,如 ????_等。

你遇到的问题,void usb_init(); 如此声明,那么在 lib中,汇编函数的名称已固定为 usb_init。
当启用全局可重入时,编译器会认为 void usb_init() 是一个reentrant函数,它的汇编函数名称
应为 usb_init?_,但实际上它在lib中是命名为 usb_init,所以才会报错 L127、L128,未解析的
外部模型,因为找不到 usb_init?_。

个人观点:对于 STC32,不启用全局可重入函数是愚蠢的行为,如非必要,还是启用为好,
这样会像ARM一样易用,因为不必再像51一样,凡是函数都要考虑会不会重入?是否可重入?等问题。

解决方法(前提还是要启用全局可重入函数):

把 void usb_init(); 声明为 static属性,这样它的汇编函数名称仍为 usb_init,
这样问题完美解决


页: 102 103 104 105 106 107 108 109 110 111 [112] 113 114 115
查看完整版本: 全局不关总中断的 RTOS,CosyOS-III-V1.2.0, 送 擎天柱-AI8051U转89C52核心板