Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C、 ";“外部”;硬件抽象层中的变量类型_C_Types_Embedded_Extern_Hal - Fatal编程技术网

C、 ";“外部”;硬件抽象层中的变量类型

C、 ";“外部”;硬件抽象层中的变量类型,c,types,embedded,extern,hal,C,Types,Embedded,Extern,Hal,我正在研究硬件抽象层。此HAL的目的是在linux驱动程序和MCU驱动程序之间轻松切换 我正在研究SPI接口。下面是“打开”SPI接口的HAL函数的签名 hal/spi.h spi_handle_t spi_open(spi_port_t channel, spi_config_t config); // forward declaration of a struct, with typedef and struct tag: typedef struct spi_handle_t spi_

我正在研究硬件抽象层。此HAL的目的是在linux驱动程序和MCU驱动程序之间轻松切换

我正在研究SPI接口。下面是“打开”SPI接口的HAL函数的签名

hal/spi.h

spi_handle_t spi_open(spi_port_t channel, spi_config_t config);

// forward declaration of a struct, with typedef and struct tag:
typedef struct spi_handle_t spi_handle_t; 

// Require the caller to declare a spi_handle_t* pointer, not an object:
spi_handle_t* spi_init (...); 
spi_端口:

  • 在Linux上,它是一种基本类型:uint32\u t
  • 在MCU上,它是一个结构
spi配置:

  • 在Linux和MCU上,它都是一个结构,但具有不同的字段
因此,在mcu/spi.c中,我在某一点上有:

typedef spiBASE_t spi_channel_t;
typedef spiDAT1_t spi_config_t;

spi_handle_t spi_open(spi_channel_t channel, spi_config_t config) {
.
.
.
}
对于linux/spi.c

typedef uint32_t spi_channel_t;
typedef ChannelConfig_t spi_config_t;

spi_handle_t spi_open(spi_channel_t channel, spi_config_t config) {
.
.
.
}
现在问题出在hal/spi.h中,我需要定义什么是spi\u channel\u t和spi\u config\t

有没有一种方法可以做出这样的事情(我知道使用extern是不可能的,但是对于解释问题…)


这会对编译器说:“好的,这两种类型没有在头文件中定义,但是您仍然可以在我传递给工具链的一个文件中找到它们的存储大小。”

这样做的典型方式是使用hal/spi.h中的预处理器:

#if defined(HAL_LINUX)
typedef uint32_t spi_port_t; /* int in linux */
#elif defined(HAL_MCU)
typedef struct {
    /* your struct in bare metal app */
} spi_port_t;
#else
#error "Platform not defined!"
#endif
您还可以将不同的类型放入不同的头中,如
hal/spi_linux.h
hal/spi_mcu.h
,并有条件地将其中一个包含在
hal/spi.h


或者,您可以只获取指针并将其转换为实际类型。这将不太安全,因为您必须在运行时检查平台并决定指针后面的类型,但这一决定取决于许多其他因素。

您似乎在寻找一种称为不透明类型的技巧。这是一种使用结构的前向声明的方法,以实现C中的私有封装和多态性。它通常用于专业编写的嵌入式系统驱动程序,具体实现方式如下:

hal/spi.h

spi_handle_t spi_open(spi_port_t channel, spi_config_t config);

// forward declaration of a struct, with typedef and struct tag:
typedef struct spi_handle_t spi_handle_t; 

// Require the caller to declare a spi_handle_t* pointer, not an object:
spi_handle_t* spi_init (...); 
mcu/spi.c

struct spi_handle_t
{
  // whatever you need here - these are now 100% private members
};

spi_handle_t* spi_init (...)
{
  spi_handle* result = address_of_some_static_memory_pool;

  /* init struct members here */

  return result;  
}
struct spi_handle_t
{
  uint32_t something;
  // whatever you need here - these are now 100% private members
};

spi_handle_t* spi_init (...)
{
  spi_handle* result = malloc(sizeof *result); // malloc is fine to use in Linux

  /* init struct members here */

  return result;  
}
linux/spi.c

struct spi_handle_t
{
  // whatever you need here - these are now 100% private members
};

spi_handle_t* spi_init (...)
{
  spi_handle* result = address_of_some_static_memory_pool;

  /* init struct members here */

  return result;  
}
struct spi_handle_t
{
  uint32_t something;
  // whatever you need here - these are now 100% private members
};

spi_handle_t* spi_init (...)
{
  spi_handle* result = malloc(sizeof *result); // malloc is fine to use in Linux

  /* init struct members here */

  return result;  
}

现在,调用者必须将
spi\u句柄*
传递给驱动程序中的其他函数。这不仅对于OO设计很方便,而且还可以在多个实例中运行相同的代码。例如,如果MCU上有两个不同的SPI硬件外设,并且希望以不同的方式使用它们,但使用相同的驱动程序代码。

您可以将Linux“本机”类型定义为具有单个成员的结构。那对你有用吗?然后,您的头只需将这些类型声明为
struct
。。。所谓不透明结构。如果这听起来不错的话,也许我可以添加更多(甚至作为一个答案)。我没有想到这个选项+1您也可以使用
typedef struct spi_handle_t*spi_handle_t实现此功能spi\u channel\u t
spi\u config\u t
,它不适用于THO。这意味着,如果您试图定义作为参数提供的类型的实例,则它们的类型总是不完整的。@eeucalyptus您必须以相同的方式实现它们,但在这种情况下,我真的不明白为什么这些不应该是结构的私有成员。在正常使用情况下,用户应一次性设置波特率、时钟设置和通道等内容,并且从此不再对它们进行干扰。感谢您的回复@Lundin!事实上,我在不知情的情况下将你的建议应用于另一个项目。我也可以将此方法应用于spi_channel_t和spi_Confug_t,但这两种方法在MCU上有很多字段。所以它不适用。我也考虑过这个想法。但它需要创建一个附加头。所以我不认为我会应用这个想法。