这是交易:我正在开发一个C函数,它配置一个包含许多成员的结构,如* BASE(指向结构的指针),ID,MODE;但BASE是一个结构,可能被定义为(例如)“struct a”,“struct b”,“...”,具体取决于接口。这是结构(和一些例子)声明:
typedef unsigned int u32_t;
typedef unsigned char u8_t;
typedef struct _interface_t{
u32_t *BASE;
u8_t ID;
u32_t MODE;
} interface_t;
interface_t USART0_DEV = {AT91C_BASE_US0, AT91C_ID_US0, 0}; // <-- Here we have a AT91C_BASE_US0 struct as *BASE
interface_t USART1_DEV = {AT91C_BASE_US1, AT91C_ID_US1, 0};
interface_t TC0_DEV = {AT91C_BASE_TC0, AT91C_ID_TC0, 0}; // <-- Here we have a AT91C_BASE_TC0 struct as *BASE
interface_t TC1_DEV = {AT91C_BASE_TC1, AT91C_ID_TC1, 0};
interface_t TC2_DEV = {AT91C_BASE_TC2, AT91C_ID_TC2, 0};
interface_t TWI_DEV = {AT91C_BASE_TWI, AT91C_ID_TWI, 0}; // <-- Here we have a AT91C_BASE_TWI struct as *BASE
如您所见,我使用u32_t
而不是结构,因为我正在声明指向该结构的指针。后来我将我的功能定义为:
unsigned char ConfigureDevice(interface_t *Interface, u32_t config, u32_t Speed, u32_t IRQ_Trigger, void (*Interface_irq_handler)(void)){
...
Interface->BASE->US_IER = IRQ_Trigger; //Note: US_IER Must receive a vector to a function
...
}
但我收到错误'US_IER无法解决'。
所以我尝试了AT91S_USART InterfaceBASE = Interface->BASE; InterfaceBASE->US_IER = IRQ_Trigger;
而不是Interface->BASE->US_IER = IRQ_Trigger;
并且没有错误。但我不能使用它,因为我并不总是知道我正在处理什么样的接口(直到我读ID成员)。
甚至最糟糕的是:当我尝试编译时,conflicting type qualifiers for 'u32_t'
typedef中的u32_t
和initialization from incompatible pointer type
以及near initialization for USART0_DEV.BASE
警告中的每个{{1}都会出现interface_t
错误定义。
我在论坛中搜索但我无法弄清楚我的错误。这些有点帮助:
我的代码出了什么问题?
我该怎么做才能使用像Interface->BASE->US_IER
编辑:嗨!,现在这就是我所得到的:
typedef struct _Interface_t{
struct PERIPH_BASE * BASE;
u32_t ID;
u32_t MODE;
Interface_t;
Interface_t USART0_DEV = {(struct PERIPH_BASE *)AT91C_BASE_US0, AT91C_ID_US0, 0};
...
unsigned char ConfigureDevice(Interface_t *Interface, u32_t config, u32_t Speed, u32_t IRQ_Trigger,...
...
((AT91S_SYS)Interface->BASE)->AIC_IECR = IRQ_Trigger; //No problems marked by Eclipse Code Editor
....
}
看起来很好,但在编译时我得到cast to union type from type not present in union
错误...
答案 0 :(得分:1)
如果您希望保持“开放”状态,则应将BASE
定义为
void *BASE;
或者,为了发信号/记录它是一个特殊的指针,你可以使用不完整的类型:
struct hwbase * BASE;
并将其定义为
interface_t USART0_DEV = {AT91C_BASE_US0, AT91C_ID_US0, 0};
如果您使用void *
或更确切地说
interface_t USART0_DEV = {(struct hwbase *)AT91C_BASE_US0, AT91C_ID_US0, 0};
第二个选项。
然后,在使用它之后,在确保使用正确类型的硬件(例如TWI,USART)之后,您可以进行投射。
将指针从上方投射到右侧类型,例如
unsigned char ConfigureDevice(interface_t *Interface, u32_t config, u32_t Speed, u32_t IRQ_Trigger, void (*Interface_irq_handler)(void)){
...
((AT91S_USART *)Interface->BASE)->US_IER = IRQ_Trigger; //Note: US_IER Must receive a vector to a function
...
}
(这里我不确定AT91S_USART
是否已经是指针类型 - 在这种情况下,你省略*
。)
另一种选择可能是添加一些函数指针,以便有一种“穷人的OOP”:
typedef void config_func(struct _interface_t *, whateveryouneed...)
config_func config_usart; // forward declaration, does as well ensire you have no typo in the function
typedef struct _interface_t{
void *BASE;
u8_t ID;
u32_t MODE;
config_func * configure; // function pointer
} interface_t;
interface_t USART0_DEV = {AT91C_BASE_US0, AT91C_ID_US0, 0, config_usart };
void config_usart(struct _interface_t * iface, whateveryouneed...)
{
AT91S_USART * my_base = iface->BASE;
...
my_base->US_IER = ...
...
}
答案 1 :(得分:0)
您已将基本成员定义为u32_t上的指针,因此编译器认为它指向的是u32_t,而u32_t没有名为US_IER的成员。 使用“代码”的“工作”版本时会发生什么情况是从uint_32 *到AT91S_USART *的指针的隐式转换,其中包含想要的成员。
答案 2 :(得分:0)
BASE是u32_t pointer
类型的变量,并尝试访问US_IER
中实际不可用的成员u32_t pointer
。但是你期望将其定义为u32_t pointer
而不是structure pointer
可能是不可能的,因为如果通过结构指针访问成员,编译器应该已经定义了成员。
但对于您的情况(即,具有128种不同的接口类型),使用这3个必需成员(在所有128个接口中通用)US_IER, US_IAM, US_IDM
定义结构类型,并在该结构中定义具有所需可能成员的联合,并尝试使用开关盒或其他方式访问这些项目。