Shoteen 发表于 2024-10-26 03:00:05

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

项目中用到了大量的结构体,但是由于内存不足,只能把某些结构体定义在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


示波器波形如下,途中为CS管脚的电平波形图,可以见到,是23us左右


第二种方法定义如图所示


执行相同的逻辑,得到的时间不一样,为15us相差了接近7us



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






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

如果要 pt本身也存储在xdata,   可以这样写: MY_STRUCT_T* xdata pt;

CosyOS 发表于 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,定义变量时却没写,
结果是难以预料的,得看编译器的心情了。
建议你改用我给出的方法。




tzz1983 发表于 2024-10-26 10:13:48

本帖最后由 tzz1983 于 2024-10-26 10:15 编辑

CosyOS 发表于 2024-10-26 08:42
类型定义时,写 存储域 是无效的,最终结果不会符合你的预期。
存储域是变量的存储域,只有在定义变量时写 ...
说没关系,也还是有些关系,看代码和结果





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

CosyOS 发表于 2024-10-26 11:09:42

tzz1983 发表于 2024-10-26 10:13
说没关系,也还是有些关系,看代码和结果




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

tzz1983 发表于 2024-10-26 11:15:22

CosyOS 发表于 2024-10-26 11:09
是的,但这样操作是非标准的,容易产生歧义的,
在于编译器去怎样理解,不同编译器结果可能会有不同。
我 ...
我觉得多少还是得跟据编译器做出适当的调整,这些细节标准C上没有规定,属于灵活用法。
看个人吧,如果用非常规手法,就自己多验证,保证正确即可。

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

CosyOS 发表于 2024-10-26 11:16:23

tzz1983 发表于 2024-10-26 10:13
说没关系,也还是有些关系,看代码和结果




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

tzz1983 发表于 2024-10-26 11:30:30

CosyOS 发表于 2024-10-26 11:16
总之,相信我的结论,这东西我玩的多了,
当年我也这么玩过。
正是因为这种方法的不确定性、不可靠性,


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

不过, 就是在结构前加xdata 很方便哈{:lol:}

CosyOS 发表于 2024-10-26 12:05:10

tzz1983 发表于 2024-10-26 11:30
也对,道理好像是这么回事,Keil C和标准C 本身就有很大的差异域, xdata更不用说了。

不过, 就是在 ...

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

tzz1983 发表于 2024-10-26 12:37:06

CosyOS 发表于 2024-10-26 12:05
刚才我也做了一些实验,在类型定义中写 存储域,都能符合预期。
当年我碰到异常的情况想不起来了,等想起 ...

我做一些新产品开发,各种各样的,挺忙的
你呢,最近OS成熟了不少吧.
页: [1] 2
查看完整版本: 关于C251内核结构体定义区域的问题