依赖项重置设计模式(嵌入式C)



各位,我正在开发一个使用I2C模块的C嵌入式系统。使用I2C的其他模块将I2C模块作为依赖项或"子系统"。它们向它传递消息上下文结构,当I2C模块准备好时,它会根据上下文指示异步发送或读取消息,从上下文运行回调,让覆盖的模块知道工作已经完成、成功或有错误。

我希望I2C模块能够从错误中恢复,即重置外部连接的硬件,然后重新初始化外部设备。这三个动作中的前两个可以在I2C模块内部处理,没有问题,但是I2C模块不知道什么覆盖的模块可能想要使用它,并且需要向外部设备发送数据,以便在它们之前的硬件重置后再次配置它们。

消息上下文可能有对重新初始化函数的回调,但I2C模块一次只保留对其中一个函数的引用,即它当前正在处理的函数,它如何知道下次其他模块(具有重置硬件)想要与它的外部硬件对话时调用重新初始化句柄?覆盖模块不知道I2C已被重置,并且I2C模块不知道覆盖模块是否已执行其重新初始化序列,甚至不知道是否需要。

有没有一种通用的设计模式来改善这样的问题?

以不同的方式说明:

I2C和外部硬件序列的正常初始化:

initExtIOExpander() {
    context_t initialisationMsg = {/*...*/};
    i2cSend(&initialisationMsg )
}
initExtADC() {
    context_t initialisationMsg = {/*...*/};
    i2cSend(&initialisationMsg )
}
i2cSend() {
    // Start sending data using passed context, 
}
interrupt i2c_isr() {
    //If the message completed run the callback handle in the current context
    // else do the next part of the message, etc.
}
main () {
    //...
    initI2c();
    initExtIOExpander();
    initExtADC();
    //...
    // Use external devices here.
    //
}

重置和重新初始化顺序:如果上面的正常序列已经发生,但现在I2C ISR被更改以检测错误:

interrupt i2c_isr () {
    //If there was an error reset external H/W, and own H/W
    //  but how to know to call initExtIOExpander() and initExtADC()??
    //  this module might know about the ADC if it is processing and ADC
    //  message but it has "forgotten" about the IO expander or any other 
    //  device
    // else if the message completed run the callback handle in the current 
    //  context
    // else do the next part of the message, etc.
}

谢谢!

如何将所有设备初始化为"聚合"函数,并在需要时调用它?

void init_all_i2c_devices(void) {
    initExtIOExpander();
    initExtADC();
    ...
}
interrupt i2c() {
     ....
     init_all_i2c_devices();// or i2c_init_callback()
}
main() {
    init_i2c();
    init_all_i2c_devices();
    // set_i2c_init_callback(init_all_i2c_devices) if need
}

对于嵌入式上下文中的设计模式,请查看此处和此处。

特别是看门狗计时器适合您的情况。

我认为应该重置硬件的不是I2C模块。

最新更新