没有uint8_t数据类型的MCU上具有uint8_t的结构 [英] structs with uint8_t on a MCU without uint8_t datatype

查看:362
本文介绍了没有uint8_t数据类型的MCU上具有uint8_t的结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是嵌入式软件开发人员,并且想与外部设备连接.该设备通过SPI发送数据.该数据的结构是由外部设备制造商预先定义的,无法进行编辑.制造商正在为某些Header文件提供所有通过SPI发送的所有数据的typedef. 制造商还提供了API以正确的方式处理接收到的数据包(我可以访问该API的来源).

I am an Embedded Software developer and I want to interface to an external device. This device sends data via SPI. The structure of that data is predefined from the external device manufacturer and can't be edited. The manufacturer is providing some Header files with many typedefs of all the data send via SPI. The manufacturer also offers an API to handle the received packets in the correct way(I have access to the source of that API).

由于我的问题: 类型定义的结构包含许多uint8_t数据类型.不幸的是,我们的MCU不支持uint8_t数据类型,因为最小的类型是16位宽(因此,即使一个char也具有16位).

Now to my problem: The typedefed structures contain many uint8_t datatypes. Unfortunately, our MCU doesn't support uint8_t datatypes, because the smallest type is 16bit-wide(so even a char has 16-bit).

要正确使用API​​,必须在结构中填充通过SPI接收的数据.由于传入的数据是字节数据包,因此我们不能仅将这些数据复制到结构中,因为对于这些8位类型,我们的结构使用16位. 结果,我们需要做很多移位操作才能正确分配接收到的数据.

To use the API correctly the structures must be filled with the data received via SPI. Since the incoming data is byte-packet, we can't just copy this data into the struct, because our structs use 16-bit for those 8-bit types. As a result, we need to do many bitshift-operations to assign the received data correctly.

示例:(制造商的typedef结构)

EXAMPLE:(manufacturers typedef struct)

typedef struct NETX_COMMUNICATION_CHANNEL_INFOtag
{
  uint8_t   bChannelType;              //uint16_t in our system
  uint8_t   bChannelId;                //uint16_t in our system
  uint8_t   bSizePositionOfHandshake;  //uint16_t in our system
  uint8_t   bNumberOfBlocks;           //uint16_t in our system
  uint32_t  ulSizeOfChannel;           
  uint16_t  usCommunicationClass;      
  uint16_t  usProtocolClass;           
  uint16_t  usProtocolConformanceClass;
  uint8_t   abReserved[2];             //uint16_t in our system
} NETX_COMMUNICATION_CHANNEL_INFO;

有人能想到解决此问题的简便方法吗? 我真的不想为每种接收到的数据包类型编写单独的位移操作. (性能/时间/空间浪费)

Can anybody think of an easy workaround to this problem? I really don't want to write a separate bitshift operation for every received packet type. (performance/time/space-waste)

我的想法 (使用位域将2xuint8_t填充到uint16_t或4xuint8_t填充到uint32_t)

My Idea (using bitfields to stuff 2xuint8_t into uint16_t or 4xuint8_t into uint32_t)

typedef struct NETX_COMMUNICATION_CHANNEL_INFOtag
{
  struct packet_uint8{
    uint32_t  bChannelType              :8;
    uint32_t  bChannelId                :8;
    uint32_t  bSizePositionOfHandshake  :8;
    uint32_t  bNumberOfBlocks           :8;
  }packet_uint8;
  uint32_t  ulSizeOfChannel;               
  uint16_t  usCommunicationClass;          
  uint16_t  usProtocolClass;               
  uint16_t  usProtocolConformanceClass;    
  uint16_t  abReserved;                    
} NETX_COMMUNICATION_CHANNEL_INFO;

现在,我不确定该解决方案是否会起作用,因为位域内的位顺序不一定是源文件中的顺序. (或者所有位域的大小都一样吗?)

Now I am not sure if this solution is going to work since the order of the bits inside the bitfield is not necessarily the order in the source file. (or is it if all the bitfields have the same size?)

我希望我对问题的描述足够好,让您理解.

I hope I described the problem well enough for you to understand.

感谢和问候.

推荐答案

您的编译器手册应该描述位字段的布局方式.请仔细阅读.还有一个叫做__attribute__((byte_peripheral))的东西,应该可以帮助在内存映射的设备中合理地打包位域.

Your compiler manual should describe how the bit fields are laid out. Read it carefully. There is something called __attribute__((byte_peripheral)) too that should help with packing bitfields sanely in memory-mapped devices.

如果不确定 bitfields ,只需将uint16_t用于这些字段和带有位移的访问宏即可,例如

If you're unsure about the bitfields, just use uint16_t for these fields and an access macro with bit shifts, for example

#define FIRST(x) ((x) >> 8)
#define SECOND(x) ((x) & 0xFF)

...
    uint16_t channel_type_and_id;
...

int channel_type = FIRST(x->channel_type_and_id);
int channel_id = SECOND(x->channel_type_and_id);

然后,您只需要确定平台的字节顺序即可.是否需要更改MCU似乎支持的字节序?您可以重新定义这些宏.

Then you just need to be sure of the byte-order of the platform. If you need to change endianness which the MCU seems to support? you can just redefine these macros.

位域很可能仍将根据位移位来实现,因此不会有太多的节省-并且如果寄存器有 个字节访问函数,则编译器将知道如何优化x & 0xff使用它们

A bitfield would most probably still be implemented in terms of bitshifts so there wouldn't be much savings - and if there are byte-access functions for registers, then a compiler would know to optimize x & 0xff to use them

这篇关于没有uint8_t数据类型的MCU上具有uint8_t的结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆