各位,我正在开发一个使用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模块。