Forked repository for pushing changes
Diff: irq.cpp
- Revision:
- 17:af1f2416dd26
diff -r 61ad39564f45 -r af1f2416dd26 irq.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/irq.cpp Tue Jul 13 13:58:07 2021 +0530 @@ -0,0 +1,436 @@ +/***************************************************************************//** + * @file irq.cpp + * @brief Implementation of Interrupt Mbed platform driver interfaces +******************************************************************************** + * Copyright (c) 2020-2021 Analog Devices, Inc. + * All rights reserved. + * + * This software is proprietary to Analog Devices, Inc. and its licensors. + * By using this software you agree to the terms of the associated + * Analog Devices Software License Agreement. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include <stdio.h> +#include <mbed.h> + +// Platform support needs to be C-compatible to work with other drivers +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "error.h" +#include "irq.h" +#include "irq_extra.h" +#include "uart_extra.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +using namespace std::chrono; + +/** +* @struct mbed_irq_callback_desc +* @brief Structure holding the callback functions for mbed irqs +* @note The callback functions are mapped with 'irq_id' structure +*/ +typedef struct { + struct callback_desc callback_ext_int_id1; + struct callback_desc callback_ext_int_id2; + struct callback_desc callback_ext_int_id3; + struct callback_desc callback_ext_int_id4; + struct callback_desc callback_ext_int_id5; + struct callback_desc callback_uart_rx_id1; + struct callback_desc callback_ticker_id; +} mbed_irq_callback_desc; + +/* Mbed callback function pointer typedef */ +typedef void(*mbed_callback_func)(void); + +/* Mbed irq callback structure variable */ +static mbed_irq_callback_desc mbed_irq_callbacks; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Mbed callback function for external interrupt ID1 event + * @return none + */ +static void mbed_ext_int_id1_callback(void) +{ + if (mbed_irq_callbacks.callback_ext_int_id1.callback) { + mbed_irq_callbacks.callback_ext_int_id1.callback( + mbed_irq_callbacks.callback_ext_int_id1.ctx, EXTERNAL_INT_ID1, NULL); + } +} + + +/** + * @brief Mbed callback function for external interrupt ID2 event + * @return none + */ +static void mbed_ext_int_id2_callback(void) +{ + if (mbed_irq_callbacks.callback_ext_int_id2.callback) { + mbed_irq_callbacks.callback_ext_int_id2.callback( + mbed_irq_callbacks.callback_ext_int_id2.ctx, EXTERNAL_INT_ID2, NULL); + } +} + + +/** + * @brief Mbed callback function for external interrupt ID3 event + * @return none + */ +static void mbed_ext_int_id3_callback(void) +{ + if (mbed_irq_callbacks.callback_ext_int_id3.callback) { + mbed_irq_callbacks.callback_ext_int_id3.callback( + mbed_irq_callbacks.callback_ext_int_id3.ctx, EXTERNAL_INT_ID3, NULL); + } +} + + +/** + * @brief Mbed callback function for external interrupt ID4 event + * @return none + */ +static void mbed_ext_int_id4_callback(void) +{ + if (mbed_irq_callbacks.callback_ext_int_id4.callback) { + mbed_irq_callbacks.callback_ext_int_id4.callback( + mbed_irq_callbacks.callback_ext_int_id4.ctx, EXTERNAL_INT_ID4, NULL); + } +} + + +/** + * @brief Mbed callback function for external interrupt ID5 event + * @return none + */ +static void mbed_ext_int_id5_callback(void) +{ + if (mbed_irq_callbacks.callback_ext_int_id5.callback) { + mbed_irq_callbacks.callback_ext_int_id5.callback( + mbed_irq_callbacks.callback_ext_int_id5.ctx, EXTERNAL_INT_ID5, NULL); + } +} + + +/** + * @brief Mbed callback function for UART Rx ID1 event + * @return none + */ +static void mbed_uart_rx_id1_callback(void) +{ + if (mbed_irq_callbacks.callback_uart_rx_id1.callback) { + mbed_irq_callbacks.callback_uart_rx_id1.callback( + mbed_irq_callbacks.callback_uart_rx_id1.ctx, UART_RX_INT_ID1, NULL); + } +} + + +/** + * @brief Mbed callback function for ticker ID event + * @return none + */ +static void mbed_ticker_id_callback(void) +{ + if (mbed_irq_callbacks.callback_ticker_id.callback) { + mbed_irq_callbacks.callback_ticker_id.callback( + mbed_irq_callbacks.callback_ticker_id.ctx, TICKER_INT_ID, NULL); + } +} + + +/** + * @brief Initialized the controller for the peripheral interrupts + * @param desc[in, out] - Pointer where the configured instance is stored + * @param param[in] - Configuration information for the instance + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + mbed::Ticker *ticker; + mbed_irq_desc *new_mbed_desc; + + if (!desc || !param) { + return FAILURE; + } + + irq_ctrl_desc *new_desc = (irq_ctrl_desc *)malloc(sizeof(irq_ctrl_desc)); + if (!new_desc) { + goto err_new_desc; + } + + new_mbed_desc = (mbed_irq_desc *)malloc(sizeof(mbed_irq_desc)); + if (!new_mbed_desc) { + goto err_new_mbed_desc; + } + + new_desc->irq_ctrl_id = param->irq_ctrl_id; + + new_mbed_desc->int_mode = ((mbed_irq_init_param *)param->extra)->int_mode; + new_mbed_desc->int_obj_type = ((mbed_irq_init_param *) + param->extra)->int_obj_type; + new_mbed_desc->ext_int_pin = ((mbed_irq_init_param *) + param->extra)->ext_int_pin; + + /* Ticker is a special mbed class used for generating recurring interrupt. + * The object of this class is created during interrupt initialization as: + * 1) To avoid having seperate module for it. + * 2) To avoid having multiple instances of Ticker class + * */ + if (param->irq_ctrl_id == TICKER_INT_ID) { + /* Create new instance of Ticker class */ + ticker = new Ticker(); + if (!ticker) { + goto err_ticker; + } + + new_mbed_desc->int_obj_type = (mbed::Ticker *)ticker; + new_mbed_desc->ticker_period_usec = ((mbed_irq_init_param *) + param->extra)->ticker_period_usec; + } + + new_desc->extra = (irq_ctrl_desc *)new_mbed_desc; + + *desc = new_desc; + + return SUCCESS; + +err_ticker: + free(new_mbed_desc); +err_new_mbed_desc: + free(new_desc); +err_new_desc: + // Nothing to free + + return FAILURE; +} + + +/** + * @brief Free the resources allocated by irq_ctrl_init() + * @param desc[in, out] - Interrupt controller descriptor. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + uint8_t irq_id; + + if (!desc) { + return FAILURE; + } + + if (((mbed_irq_desc *)desc->extra)->int_obj) { + free(((mbed_irq_desc *)desc->extra)->int_obj); + } + + /* Unregister all callbacks */ + for (irq_id = 0; irq_id < (uint8_t)NB_INTERRUPTS; irq_id++) { + if (irq_unregister(desc, irq_id) != SUCCESS) + return FAILURE; + } + + if ((irq_ctrl_desc *)desc->extra) { + free((irq_ctrl_desc *)desc->extra); + } + + free(desc); + + return SUCCESS; +} + + +/** + * @brief Registers a IRQ callback function to irq controller. + * @param desc[in] - The IRQ controller descriptor. + * @param irq_id[in] - Interrupt identifier. + * @param callback_desc - Descriptor of the callback. If it is NULL, the + * callback will be unregistered + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + InterruptIn *ext_interrupt; + mbed::UnbufferedSerial *uart_rx_port; + mbed::Ticker *ticker; + PinName ext_int_pin; + mbed_callback_func mbed_callback; + + if (!desc || !callback_desc) { + return FAILURE; + } + + switch (irq_id) { + case EXTERNAL_INT_ID1: + case EXTERNAL_INT_ID2: + case EXTERNAL_INT_ID3: + case EXTERNAL_INT_ID4: + case EXTERNAL_INT_ID5: + /* Attach external interrupt to input pin */ + ext_int_pin = (PinName)((mbed_irq_desc *)(desc->extra))->ext_int_pin; + if (!ext_int_pin) { + return FAILURE; + } + + ext_interrupt = new InterruptIn(ext_int_pin); + if (!ext_interrupt) { + return FAILURE; + } + + switch (irq_id) { + case EXTERNAL_INT_ID1: + mbed_irq_callbacks.callback_ext_int_id1.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ext_int_id1.ctx = callback_desc->ctx; + mbed_callback = mbed_ext_int_id1_callback; + break; + + case EXTERNAL_INT_ID2: + mbed_irq_callbacks.callback_ext_int_id2.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ext_int_id2.ctx = callback_desc->ctx; + mbed_callback = mbed_ext_int_id2_callback; + break; + + case EXTERNAL_INT_ID3: + mbed_irq_callbacks.callback_ext_int_id3.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ext_int_id3.ctx = callback_desc->ctx; + mbed_callback = mbed_ext_int_id3_callback; + break; + + case EXTERNAL_INT_ID4: + mbed_irq_callbacks.callback_ext_int_id4.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ext_int_id4.ctx = callback_desc->ctx; + mbed_callback = mbed_ext_int_id4_callback; + break; + + case EXTERNAL_INT_ID5: + mbed_irq_callbacks.callback_ext_int_id5.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ext_int_id5.ctx = callback_desc->ctx; + mbed_callback = mbed_ext_int_id5_callback; + break; + + default: + return FAILURE; + } + + /* Register a callback function to external interrupt event */ + if (((mbed_irq_desc *)(desc->extra))->int_mode == EXT_IRQ_FALL) { + ext_interrupt->fall(mbed_callback); + } else if (((mbed_irq_desc *)(desc->extra))->int_mode == EXT_IRQ_RISE) { + ext_interrupt->rise(mbed_callback); + } else { + return FAILURE; + } + + /* Store the external interrupt object to be freed from irq_ctrl_remove() */ + ((mbed_irq_desc *)(desc->extra))->int_obj = ext_interrupt; + + ext_interrupt->enable_irq(); + + break; + + case UART_RX_INT_ID1: + uart_rx_port = (mbed::UnbufferedSerial *)(((mbed_irq_desc *)( + desc->extra))->int_obj_type); + if (!uart_rx_port) { + return FAILURE; + } + + mbed_irq_callbacks.callback_uart_rx_id1.callback = callback_desc->callback; + mbed_irq_callbacks.callback_uart_rx_id1.ctx = callback_desc->ctx; + + /* Register a callback function to receive UnbufferedSerial port event */ + uart_rx_port->attach(mbed_uart_rx_id1_callback, UnbufferedSerial::RxIrq); + + break; + + case TICKER_INT_ID: + /* Create the new ticker instance */ + ticker = (mbed::Ticker *)(((mbed_irq_desc *)( + desc->extra))->int_obj_type); + if (!ticker) { + return FAILURE; + } + + mbed_irq_callbacks.callback_ticker_id.callback = callback_desc->callback; + mbed_irq_callbacks.callback_ticker_id.ctx = callback_desc->ctx; + + ticker->attach(mbed_ticker_id_callback, + microseconds(((mbed_irq_desc *)(desc->extra))->ticker_period_usec)); + break; + + default: + return FAILURE; + } + + return SUCCESS; +} + + +/** + * @brief Unregister a IRQ callback function. + * @param desc[in] - The IRQ controller descriptor. + * @param irq_id[in] - Interrupt identifier. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t irq_unregister(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + if (!desc) { + return FAILURE; + } + + switch (irq_id) { + case EXTERNAL_INT_ID1: + mbed_irq_callbacks.callback_ext_int_id1.callback = NULL; + break; + + case EXTERNAL_INT_ID2: + mbed_irq_callbacks.callback_ext_int_id2.callback = NULL; + break; + + case EXTERNAL_INT_ID3: + mbed_irq_callbacks.callback_ext_int_id3.callback = NULL; + break; + + case EXTERNAL_INT_ID4: + mbed_irq_callbacks.callback_ext_int_id4.callback = NULL; + break; + + case EXTERNAL_INT_ID5: + mbed_irq_callbacks.callback_ext_int_id5.callback = NULL; + break; + + case UART_RX_INT_ID1: + mbed_irq_callbacks.callback_uart_rx_id1.callback = NULL; + break; + + case TICKER_INT_ID: + mbed_irq_callbacks.callback_ticker_id.callback = NULL; + break; + + default: + return FAILURE; + } + + return SUCCESS; +} + +#ifdef __cplusplus // Closing extern c +} +#endif