找回密码
 立即注册
查看: 788|回复: 32

关于C251内核结构体定义区域的问题

[复制链接]
  • 打卡等级:偶尔看看II
  • 打卡总天数:28
  • 最近打卡:2025-01-08 16:11:02

12

主题

26

回帖

224

积分

中级会员

积分
224
发表于 2024-10-26 03:00:05 | 显示全部楼层 |阅读模式
项目中用到了大量的结构体,但是由于内存不足,只能把某些结构体定义在xdata区域,我用了两种定义方法:
第一种:
定义结构体类型
typedef struct
{
    UInt8 Member1;
    UInt8 Member2;
    UInt8 Member3;
    UInt8 Member4;
} xdata MY_STRUCT_T;
定义结构体变量
MY_STRUCT_T var;

第二种:
定义结构体类型

typedef struct
{
    UInt8 Member1;
    UInt8 Member2;
    UInt8 Member3;
    UInt8 Member4;
} MY_STRUCT_T;


typedef MY_STRUCT_T xdata MY_STRUCT_T_XDATA;
定义结构体变量
MY_STRUCT_T_XDATA var;

这两种定义方式都可以把数据定义在xdata区域,但是跑相同的代码时,两者的执行时间不同,我这里拿我写的一个按键状态机举例子

第一种方法,定义按键对象结构体时,执行按键状态机扫描程序执行时间是23.45us
截图202410260254497913.jpg
截图202410260254022738.jpg
示波器波形如下,途中为CS管脚的电平波形图,可以见到,是23us左右
截图202410260254266274.jpg

第二种方法定义如图所示
截图202410260251103609.jpg
截图202410260250268406.jpg
执行相同的逻辑,得到的时间不一样,为15us相差了接近7us

截图202410260250424259.jpg

采用第二种方法时,程序运行时有的时候会发生一些不可预料的问题,但是现在还找不到原因,究竟是什么原因导致了执行相同的逻辑,放在相同的xdata区域内部,但是会发生不可预料的问题。
希望有大佬能够解答!!!8051内核和Cortex内核很不同,使用复杂一点的结构体真的很头痛!而且Cortex内核的C代码直接移植如果内存不够还得把所有内存较大的手动移到xdata区域,特别是一些复杂的结构体应用!






截图202410260250197736.jpg
回复

使用道具 举报 送花

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

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 08:17:45 | 显示全部楼层
本帖最后由 tzz1983 于 2024-10-26 08:20 编辑

没有仔细看代码,不知道为什么产生不可预料的仰错误,可以降低优化等级,关掉全局重入选项试试。

在结构体前加xdata修饰时要注意。如下代码:
第一种:
定义结构体类型
typedef struct
{
    UInt8 Member1;
    UInt8 Member2;
    UInt8 Member3;
    UInt8 Member4;
} xdata MY_STRUCT_T;

如果  MY_STRUCT_T  var;   //var 是在XDATA区。这很容易理解
如果 MY_STRUCT_T  *pt;   //此时注意,指针变量本身pt并不一定存储在xdata区域,
                                       //根据项目内存模式设定,可能在 data,  edata, xdata。  
                                       //但是pt一定是指向XDATA的专用指针,即两字节指针,普通指针是4字节。

如果要 pt本身也存储在xdata,   可以这样写: MY_STRUCT_T  * xdata pt;
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 08:42:48 | 显示全部楼层
本帖最后由 CosyOS 于 2024-10-26 09:10 编辑

类型定义时,写 存储域 是无效的,最终结果不会符合你的预期。
存储域是变量的存储域,只有在定义变量时写存储域才是有效的。


定义结构体变量,常见的方法可以有如下3种:


1、typedef struct(别名)+ 定义变量
typedef struct
{
    /* 成员定义;*/
}Button_t;
Button_t xdata BUTTON;


此法为典型的用法。


2、typedef struct(标识)+ 定义变量
typedef struct Button_s
{
    /* 成员定义;*/
};
struct Button_s xdata BUTTON;


此法为万能的用法,尤其是定义链表数据结构时,必用此法。


3、直接定义结构体变量
struct
{
    /* 成员定义;*/
}xdata BUTTON;


此法适用于 内部变量,即该变量仅在此C文件中引用。



你的两种方法,在 typedef 时都写了 xdata,定义变量时却没写,
结果是难以预料的,得看编译器的心情了。
建议你改用我给出的方法。




点评

说没关系,也还是有些关系,看代码和结果 [attachimg]61357[/attachimg] [attachimg]61356[/attachimg] 结构有修饰,但定义变量dedicated时没有修饰,很明显它被分配到了xdata  详情 回复 发表于 2024-10-26 10:13
回复 支持 3 反对 0

使用道具 举报 送花

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

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 10:13:48 | 显示全部楼层
本帖最后由 tzz1983 于 2024-10-26 10:15 编辑
Cos*** 发表于 2024-10-26 08:42
类型定义时,写 存储域 是无效的,最终结果不会符合你的预期。
存储域是变量的存储域,只有在定义变量时写 ...

说没关系,也还是有些关系,看代码和结果

截图202410261011505671.jpg

截图202410261011245430.jpg

结构有修饰,但定义变量dedicated时没有修饰,很明显它被分配到了xdata

点评

总之,相信我的结论,这东西我玩的多了, 当年我也这么玩过。 正是因为这种方法的不确定性、不可靠性, 才摒弃了。  详情 回复 发表于 2024-10-26 11:16
是的,但这样操作是非标准的,容易产生歧义的, 在于编译器去怎样理解,不同编译器结果可能会有不同。 我们编程要尽量采用标准的方法,这样结果才是是确定的, 而不是“猜测”编译器会怎么处理。 即使做了实验验证,  详情 回复 发表于 2024-10-26 11:09
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 11:09:42 | 显示全部楼层
tzz1*** 发表于 2024-10-26 10:13
说没关系,也还是有些关系,看代码和结果

是的,但这样操作是非标准的,容易产生歧义的,
在于编译器去怎样理解,不同编译器结果可能会有不同。
我们编程要尽量采用标准的方法,这样结果才是是确定的,
而不是“猜测”编译器会怎么处理。
即使做了实验验证,可如果换了一个编译器,谁又能保证
会是相同的结果呢?

点评

我觉得多少还是得跟据编译器做出适当的调整,这些细节标准C上没有规定,属于灵活用法。 看个人吧,如果用非常规手法,就自己多验证,保证正确即可。 在C++上,我就经常看到, 结构 + const *xxxxP ; 定义出来的指  详情 回复 发表于 2024-10-26 11:15
回复 支持 反对

使用道具 举报 送花

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

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 11:15:22 | 显示全部楼层
Cos*** 发表于 2024-10-26 11:09
是的,但这样操作是非标准的,容易产生歧义的,
在于编译器去怎样理解,不同编译器结果可能会有不同。
我 ...

我觉得多少还是得跟据编译器做出适当的调整,这些细节标准C上没有规定,属于灵活用法。
看个人吧,如果用非常规手法,就自己多验证,保证正确即可。

在C++上,我就经常看到, typedef 结构 + const *xxxxP  ;  定义出来的指针就是常指针, 这种做法很普遍
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 11:16:23 | 显示全部楼层
tzz1*** 发表于 2024-10-26 10:13
说没关系,也还是有些关系,看代码和结果

总之,相信我的结论,这东西我玩的多了,
当年我也这么玩过。
正是因为这种方法的不确定性、不可靠性,
才摒弃了。

点评

也对,道理好像是这么回事,Keil C 和标准C 本身就有很大的差异域, xdata更不用说了。 不过, 就是在结构前加xdata 很方便哈  详情 回复 发表于 2024-10-26 11:30
回复 支持 反对

使用道具 举报 送花

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

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 11:30:30 | 显示全部楼层
Cos*** 发表于 2024-10-26 11:16
总之,相信我的结论,这东西我玩的多了,
当年我也这么玩过。
正是因为这种方法的不确定性、不可靠性,

也对,道理好像是这么回事,Keil C  和标准C 本身就有很大的差异域, xdata更不用说了。

不过, 就是在结构前加xdata 很方便哈

点评

刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。 当年我碰到异常的情况想不起来了,等想起来再告诉你。 最近忙啥呢?  详情 回复 发表于 2024-10-26 12:05
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-10-26 12:05:10 | 显示全部楼层
tzz1*** 发表于 2024-10-26 11:30
也对,道理好像是这么回事,Keil C  和标准C 本身就有很大的差异域, xdata更不用说了。

不过, 就是在 ...

刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。
当年我碰到异常的情况想不起来了,等想起来再告诉你。
最近忙啥呢?

点评

我觉得我们可以开个新帖来总结 Keil C251 的一些特殊之处, 特别是会出现编译BUG的情况,大家把自己遇到的情况汇集起来,避免重复踩坑。 我现在能回忆起来的关于Keil C251几点: 1. AI8051U刚出来时,好像是“大明  详情 回复 发表于 2024-10-26 13:08
我做一些新产品开发,各种各样的,挺忙的 你呢,最近OS成熟了不少吧.  详情 回复 发表于 2024-10-26 12:37
回复 支持 反对

使用道具 举报 送花

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

33

主题

1079

回帖

2319

积分

荣誉版主

积分
2319
发表于 2024-10-26 12:37:06 | 显示全部楼层
Cos*** 发表于 2024-10-26 12:05
刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。
当年我碰到异常的情况想不起来了,等想起 ...

我做一些新产品开发,各种各样的,挺忙的
你呢,最近OS成熟了不少吧.
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 06:33 , Processed in 0.317048 second(s), 123 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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