Folks, I am working on an embedded system in C that uses an I2C module. Other modules that use the I2C have the I2C module as a dependency, or "child system". They pass it message context structs and when the I2C module is ready it asynchronously sends or reads messages as the context instructs, running a callback from the context to let the overlying module know the work has completed, successfully or with error.

I would like the I2C module to be able to recover itself from errors i.e. reset external connected hardware, itself and then reinitialise the external devices. the former two of these three actions can be handled internal to the I2C module with no problem, however the I2C module doesn't know what overlying modules may want to use it and need to send data to external devices to configure them again after their earlier hardware reset.

The message contexts could have callbacks to reinitialisation functions, but the I2C module only holds a reference to one of these at a time, the one it is currently working on how would it know to call the reinitialise handle for the next time a different module (with reset hardware) wants to talk to it's external hardware? the overlying module doesn't know the I2C has been reset, and the I2C module doesn't know if the overlying module has performed its reinitialisation sequence or not, or even if it needs to.

Is there a common design pattern to ameliorate such a problem?

To illustrate differently:

Normal initialisation of I2C and external hardware sequence:

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.
    //
}

Reset and reinitialisation sequence: If the normal sequence from above has already happened but now the I2C ISR is altered to detects errors:

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.
}

Thanks!

有帮助吗?

解决方案

What about to put all your devies initialisation to 'aggregate' function and call it when need?

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
}

其他提示

For design patterns in the embedded context take a look here and here.

Especially the watchdog timer fits your case.

I think it is not the I2C module which should reset the HW.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top