Hi,
I am writing a driver in the style of Beningo, following this White Paper.
The structure is this:
I have a "serial" library, with a structure ser_dev_st containing a buffer and all the needed stuff, and can be instantiated as array to handle more serial consoles.
The "serial" rely on a HW related "uart", where here I am using a struct uart_hal_cgf_t initialized according to a Configuration Table. I wrote the driver and the hierarchy succesfully, but I crashed in the moment I inserted the ISRs in the "serial".
Here is the working structure:
------------------------------------------------------------------ in serial.c ------------------------------------------------------------------ typedef struct serial_device { rb_t serial_tx_buff; rb_t serial_rx_buff; uint8_t tx_buff[SER_RB_SIZE_TX]; uint8_t rx_buff[SER_RB_SIZE_RX]; uart_hal_cgf_t hal; } ser_dev_st; void Ser_init(ser_dev_st* console, uart_hal_cgf_t* config) { console->hal = config; /// a lot of code initializing the parameters of "console" according to "config" UartHal_init(console->hal); } ------------------------------------------------------------------ in uart_hal.c ------------------------------------------------------------------ typedef struct { uart_hal_ch_t channel; uart_hal_mode_t mode; long baudrate; } uart_hal_cgf_t; address_t volatile * const ucsra[NUM_UART_CHANNELS] = { (address_t*)&UCSR0A, (address_t*)&UCSR1A }; void UartHal_init(uart_hal_cgf_t* handle) { uint16_t baud_reg = 0; ucsra[handle->channel] = 0; // ecc ecc }
Now the situation is that the application can call the Ser_* functions with the relative ser_dev_st console, accessing to that particular ring buffers and interacting with them. The Serial is now modular and reusable and works, as long as the HAL, which is modular with respect to the hardware (2x UART, means ucsra is an array of 2 SFR register elements and so on). With the proper tables, I make the initializations.
The problem happens when I need to handle the driver uaing the ISR, I get stuck in the following situation, becase I have no way to tell which console use in the ISR:
--------------------------------------------- in serial.c --------------------------------------------- static void ser_rx_char_ISR(/* NO PARAMETERS ALLOWED */) { if (!Rb_is_full(console->serial_rx_buff)) ////////////////////////////// I WANT TO REFER TO &console SOMEHOW... { Rb_put_char(console->serial_rx_buff, Uart_get_char(console->hal)); } else { // ecc } //ecc }
How can I use a console associated to a given hal, or to a given interrupt? This is just because I cannot pass any argument in the ISR and I have to find a way to know which console to use, when an ISR trig.
Also, I normally use an "interrupt hal" to setup the ISR, like IntHal_vector_register(ser_rx_char_ISR, HAL_VECT_UART_RX_ID); where I just link to a callback present in the ISR(vect) space. This approach makes it portable nicely between AVR and ARM, but only now I switched to this more modular approach, and hence facing this ISR issue.
Thanks!