您如何 return 嵌入式系统中的错误代码?

How would you return error codes in an embedded system?

所以我正在编写自己的 HAL,现在我对如何 return 函数中的错误代码有点争论。 所以一般的想法是我有一个 I2C_read() 函数:

int32_t I2C_read(I2C_handle_t i2c, uint8_t addr, uint8_t reg);

其中return是成功时的字节,或者发生错误时的负错误值。因为我在这里只从 I2C 读取一个字节,所以 int32_t 将有足够的 space 来处理这两个字节,错误时的错误代码和成功时读取的字节。 但是现在我已经读到,return 来自一个函数的两种不同“类型”的数据通常是不好的做法。 所以我现在的争论是我应该怎么做: 要么我做:

i2c_err_t I2C_read(I2C_handle_t i2c, uint8_t addr, uint8_t reg, uint8_t *data);

我只是把 data 作为读取字节的缓冲区和 return 错误代码
或者

uint8_t I2C_read(I2C_handle_t i2c, uint8_t addr, uint8_t reg, i2c_err_t *err);

其中我 return 数据并将错误放入缓冲区。

那么你们认为哪个更好,或者你们可以给我另一个实现方法的想法。

我还考虑过创建一个 struct,我在其中放入 returned 值和错误代码,但我认为这会过于过度设计,因为用这个处理数组一种方法。

But now I've read that it is general bad practice to return two different "types" of data from a function.

确实,拆分数据和错误处理通常会更好,这样就不会出现意外混淆。这也支持更高级的错误处理(错误原因多于一个)。

i2c_err_t I2C_read(I2C_handle_t i2c, uint8_t addr, uint8_t reg, uint8_t *data);

此版本是大多数专业 API 的设计方式 - return 类型(枚举、结构等)保留用于结果变量。通常,该库中的每个 public 函数都会使用相同的 return 类型,但会记录在哪些条件下将其编码为 return 的错误。

从技术上讲,通过参数传递错误代码也没有错,但使用 return 类型是“事实上的标准”,大多数库都是这样做的。

此外,这意味着您可以编写如下代码:if(I2C_read(...) == SOMETHING),以防调用者只对检查一个特定的结果代码感兴趣。

让调用者将这些错误传递给一些项目范围的错误处理程序也是常见的做法,prints/logs/takes 操作等