Platform drivers for Mbed.

Dependents:   EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers irq.cpp Source File

irq.cpp

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  * @file  irq.cpp
00003  * @brief Implementation of Interrupt Mbed platform driver interfaces
00004 ********************************************************************************
00005  * Copyright (c) 2020-2021 Analog Devices, Inc.
00006  * All rights reserved.
00007  *
00008  * This software is proprietary to Analog Devices, Inc. and its licensors.
00009  * By using this software you agree to the terms of the associated
00010  * Analog Devices Software License Agreement.
00011 *******************************************************************************/
00012 
00013 /******************************************************************************/
00014 /***************************** Include Files **********************************/
00015 /******************************************************************************/
00016 
00017 #include <stdio.h>
00018 #include <mbed.h>
00019 
00020 // Platform support needs to be C-compatible to work with other drivers
00021 #ifdef __cplusplus
00022 extern "C"
00023 {
00024 #endif
00025 
00026 #include "error.h"
00027 #include "irq.h"
00028 #include "irq_extra.h"
00029 #include "uart_extra.h"
00030 
00031 /******************************************************************************/
00032 /*************************** Types Declarations *******************************/
00033 /******************************************************************************/
00034 
00035 using namespace std::chrono;
00036 
00037 /**
00038 * @struct mbed_irq_callback_desc
00039 * @brief Structure holding the callback functions for mbed irqs
00040 * @note  The callback functions are mapped with 'irq_id' structure
00041 */
00042 typedef struct {
00043     struct callback_desc callback_ext_int_id1;
00044     struct callback_desc callback_ext_int_id2;
00045     struct callback_desc callback_ext_int_id3;
00046     struct callback_desc callback_ext_int_id4;
00047     struct callback_desc callback_ext_int_id5;
00048     struct callback_desc callback_uart_rx_id1;
00049     struct callback_desc callback_ticker_id;
00050 } mbed_irq_callback_desc;
00051 
00052 /* Mbed callback function pointer typedef */
00053 typedef void(*mbed_callback_func)(void);
00054 
00055 /* Mbed irq callback structure variable */
00056 static mbed_irq_callback_desc mbed_irq_callbacks;
00057 
00058 /******************************************************************************/
00059 /************************ Functions Declarations ******************************/
00060 /******************************************************************************/
00061 
00062 /******************************************************************************/
00063 /************************ Functions Definitions *******************************/
00064 /******************************************************************************/
00065 
00066 /**
00067  * @brief   Mbed callback function for external interrupt ID1 event
00068  * @return  none
00069  */
00070 static void mbed_ext_int_id1_callback(void)
00071 {
00072     if (mbed_irq_callbacks.callback_ext_int_id1.callback) {
00073         mbed_irq_callbacks.callback_ext_int_id1.callback(
00074             mbed_irq_callbacks.callback_ext_int_id1.ctx, EXTERNAL_INT_ID1, NULL);
00075     }
00076 }
00077 
00078 
00079 /**
00080  * @brief   Mbed callback function for external interrupt ID2 event
00081  * @return  none
00082  */
00083 static void mbed_ext_int_id2_callback(void)
00084 {
00085     if (mbed_irq_callbacks.callback_ext_int_id2.callback) {
00086         mbed_irq_callbacks.callback_ext_int_id2.callback(
00087             mbed_irq_callbacks.callback_ext_int_id2.ctx, EXTERNAL_INT_ID2, NULL);
00088     }
00089 }
00090 
00091 
00092 /**
00093  * @brief   Mbed callback function for external interrupt ID3 event
00094  * @return  none
00095  */
00096 static void mbed_ext_int_id3_callback(void)
00097 {
00098     if (mbed_irq_callbacks.callback_ext_int_id3.callback) {
00099         mbed_irq_callbacks.callback_ext_int_id3.callback(
00100             mbed_irq_callbacks.callback_ext_int_id3.ctx, EXTERNAL_INT_ID3, NULL);
00101     }
00102 }
00103 
00104 
00105 /**
00106  * @brief   Mbed callback function for external interrupt ID4 event
00107  * @return  none
00108  */
00109 static void mbed_ext_int_id4_callback(void)
00110 {
00111     if (mbed_irq_callbacks.callback_ext_int_id4.callback) {
00112         mbed_irq_callbacks.callback_ext_int_id4.callback(
00113             mbed_irq_callbacks.callback_ext_int_id4.ctx, EXTERNAL_INT_ID4, NULL);
00114     }
00115 }
00116 
00117 
00118 /**
00119  * @brief   Mbed callback function for external interrupt ID5 event
00120  * @return  none
00121  */
00122 static void mbed_ext_int_id5_callback(void)
00123 {
00124     if (mbed_irq_callbacks.callback_ext_int_id5.callback) {
00125         mbed_irq_callbacks.callback_ext_int_id5.callback(
00126             mbed_irq_callbacks.callback_ext_int_id5.ctx, EXTERNAL_INT_ID5, NULL);
00127     }
00128 }
00129 
00130 
00131 /**
00132  * @brief   Mbed callback function for UART Rx ID1 event
00133  * @return  none
00134  */
00135 static void mbed_uart_rx_id1_callback(void)
00136 {
00137     if (mbed_irq_callbacks.callback_uart_rx_id1.callback) {
00138         mbed_irq_callbacks.callback_uart_rx_id1.callback(
00139             mbed_irq_callbacks.callback_uart_rx_id1.ctx, UART_RX_INT_ID1, NULL);
00140     }
00141 }
00142 
00143 
00144 /**
00145  * @brief   Mbed callback function for ticker ID event
00146  * @return  none
00147  */
00148 static void mbed_ticker_id_callback(void)
00149 {
00150     if (mbed_irq_callbacks.callback_ticker_id.callback) {
00151         mbed_irq_callbacks.callback_ticker_id.callback(
00152             mbed_irq_callbacks.callback_ticker_id.ctx, TICKER_INT_ID, NULL);
00153     }
00154 }
00155 
00156 
00157 /**
00158  * @brief   Initialized the controller for the peripheral interrupts
00159  * @param   desc[in, out] - Pointer where the configured instance is stored
00160  * @param   param[in] - Configuration information for the instance
00161  * @return  SUCCESS in case of success, FAILURE otherwise.
00162  */
00163 int32_t irq_ctrl_init(struct irq_ctrl_desc **desc,
00164               const struct irq_init_param *param)
00165 {
00166     mbed::Ticker *ticker;
00167     InterruptIn *ext_interrupt;
00168     mbed_irq_desc *new_mbed_desc;
00169 
00170     if (!desc || !param) {
00171         return FAILURE;
00172     }
00173 
00174     irq_ctrl_desc *new_desc = (irq_ctrl_desc *)malloc(sizeof(irq_ctrl_desc));
00175     if (!new_desc) {
00176         goto err_new_desc;
00177     }
00178 
00179     new_mbed_desc = (mbed_irq_desc *)malloc(sizeof(mbed_irq_desc));
00180     if (!new_mbed_desc) {
00181         goto err_new_mbed_desc;
00182     }
00183 
00184     new_desc->irq_ctrl_id = param->irq_ctrl_id;
00185     new_mbed_desc->int_mode = ((mbed_irq_init_param *)param->extra)->int_mode;
00186     new_mbed_desc->ext_int_pin = ((mbed_irq_init_param *)
00187                       param->extra)->ext_int_pin;
00188 
00189     switch (param->irq_ctrl_id) {
00190     case EXTERNAL_INT_ID1:
00191     case EXTERNAL_INT_ID2:
00192     case EXTERNAL_INT_ID3:
00193     case EXTERNAL_INT_ID4:
00194     case EXTERNAL_INT_ID5:
00195         /* Create a new external interrupt object */
00196         ext_interrupt = new InterruptIn((PinName)(new_mbed_desc->ext_int_pin));
00197         if (!ext_interrupt) {
00198             goto err_interrupt;
00199         }
00200 
00201         new_mbed_desc->int_obj = (mbed::InterruptIn *)ext_interrupt;
00202         break;
00203 
00204     case TICKER_INT_ID:
00205         /* Ticker is a special mbed class used for generating recurring interrupt.
00206         * The object of this class is created during interrupt initialization as:
00207         * 1) To avoid having seperate module for it.
00208         * 2) To avoid having multiple instances of Ticker class
00209         * */
00210         ticker = new Ticker();
00211         if (!ticker) {
00212             goto err_interrupt;
00213         }
00214 
00215         new_mbed_desc->int_obj = (mbed::Ticker *)ticker;
00216         new_mbed_desc->ticker_period_usec = ((mbed_irq_init_param *)
00217                              param->extra)->ticker_period_usec;
00218         break;
00219 
00220     case UART_RX_INT_ID1:
00221         /* UART object must be created from uart.cpp module by an application */
00222         new_mbed_desc->int_obj = ((mbed_irq_init_param *)
00223                       param->extra)->int_obj_type;
00224         break;
00225 
00226     default:
00227         goto err_interrupt;
00228     }
00229 
00230     new_desc->extra = (irq_ctrl_desc *)new_mbed_desc;
00231 
00232     *desc = new_desc;
00233 
00234     return SUCCESS;
00235 
00236 err_interrupt:
00237     free(new_mbed_desc);
00238 err_new_mbed_desc:
00239     free(new_desc);
00240 err_new_desc:
00241     // Nothing to free
00242 
00243     return FAILURE;
00244 }
00245 
00246 
00247 /**
00248  * @brief   Free the resources allocated by irq_ctrl_init()
00249  * @param   desc[in, out] - Interrupt controller descriptor.
00250  * @return  SUCCESS in case of success, FAILURE otherwise.
00251  */
00252 int32_t irq_ctrl_remove(struct irq_ctrl_desc *desc)
00253 {
00254     uint8_t irq_id;
00255 
00256     if (!desc) {
00257         return FAILURE;
00258     }
00259 
00260     if (((mbed_irq_desc *)desc->extra)->int_obj) {
00261         free(((mbed_irq_desc *)desc->extra)->int_obj);
00262     }
00263 
00264     /* Unregister all callbacks */
00265     for (irq_id = 0; irq_id < (uint8_t)NB_INTERRUPTS; irq_id++) {
00266         if (irq_unregister(desc, irq_id) != SUCCESS)
00267             return FAILURE;
00268     }
00269 
00270     if ((irq_ctrl_desc *)desc->extra) {
00271         free((irq_ctrl_desc *)desc->extra);
00272     }
00273 
00274     free(desc);
00275 
00276     return SUCCESS;
00277 }
00278 
00279 
00280 /**
00281  * @brief   Registers a IRQ callback function to irq controller.
00282  * @param   desc[in] - The IRQ controller descriptor.
00283  * @param   irq_id[in] - Interrupt identifier.
00284  * @param   callback_desc - Descriptor of the callback. If it is NULL, the
00285  *          callback will be unregistered
00286  * @return  SUCCESS in case of success, FAILURE otherwise.
00287  */
00288 int32_t irq_register_callback(struct irq_ctrl_desc *desc,
00289                   uint32_t irq_id,
00290                   struct callback_desc *callback_desc)
00291 {
00292     InterruptIn *ext_interrupt;
00293     mbed_callback_func mbed_callback;
00294 
00295     if (!desc || !callback_desc) {
00296         return FAILURE;
00297     }
00298 
00299     switch (irq_id) {
00300     case EXTERNAL_INT_ID1:
00301     case EXTERNAL_INT_ID2:
00302     case EXTERNAL_INT_ID3:
00303     case EXTERNAL_INT_ID4:
00304     case EXTERNAL_INT_ID5:
00305         switch (irq_id) {
00306         case EXTERNAL_INT_ID1:
00307             mbed_irq_callbacks.callback_ext_int_id1.callback = callback_desc->callback;
00308             mbed_irq_callbacks.callback_ext_int_id1.ctx = callback_desc->ctx;
00309             mbed_callback = mbed_ext_int_id1_callback;
00310             break;
00311 
00312         case EXTERNAL_INT_ID2:
00313             mbed_irq_callbacks.callback_ext_int_id2.callback = callback_desc->callback;
00314             mbed_irq_callbacks.callback_ext_int_id2.ctx = callback_desc->ctx;
00315             mbed_callback = mbed_ext_int_id2_callback;
00316             break;
00317 
00318         case EXTERNAL_INT_ID3:
00319             mbed_irq_callbacks.callback_ext_int_id3.callback = callback_desc->callback;
00320             mbed_irq_callbacks.callback_ext_int_id3.ctx = callback_desc->ctx;
00321             mbed_callback = mbed_ext_int_id3_callback;
00322             break;
00323 
00324         case EXTERNAL_INT_ID4:
00325             mbed_irq_callbacks.callback_ext_int_id4.callback = callback_desc->callback;
00326             mbed_irq_callbacks.callback_ext_int_id4.ctx = callback_desc->ctx;
00327             mbed_callback = mbed_ext_int_id4_callback;
00328             break;
00329 
00330         case EXTERNAL_INT_ID5:
00331             mbed_irq_callbacks.callback_ext_int_id5.callback = callback_desc->callback;
00332             mbed_irq_callbacks.callback_ext_int_id5.ctx = callback_desc->ctx;
00333             mbed_callback = mbed_ext_int_id5_callback;
00334             break;
00335 
00336         default:
00337             return FAILURE;
00338         }
00339 
00340         ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
00341 
00342         /* Select interrupt mode */
00343         if (((mbed_irq_desc *)(desc->extra))->int_mode == EXT_IRQ_FALL) {
00344             ext_interrupt->fall(mbed_callback);
00345         } else if (((mbed_irq_desc *)(desc->extra))->int_mode == EXT_IRQ_RISE) {
00346             ext_interrupt->rise(mbed_callback);
00347         } else {
00348             return FAILURE;
00349         }
00350 
00351         break;
00352 
00353     case UART_RX_INT_ID1:
00354         mbed_irq_callbacks.callback_uart_rx_id1.callback = callback_desc->callback;
00355         mbed_irq_callbacks.callback_uart_rx_id1.ctx = callback_desc->ctx;
00356         break;
00357 
00358     case TICKER_INT_ID:
00359         mbed_irq_callbacks.callback_ticker_id.callback = callback_desc->callback;
00360         mbed_irq_callbacks.callback_ticker_id.ctx = callback_desc->ctx;
00361         break;
00362 
00363     default:
00364         return FAILURE;
00365     }
00366 
00367     return SUCCESS;
00368 }
00369 
00370 
00371 /**
00372  * @brief   Unregister a IRQ callback function.
00373  * @param   desc[in] - The IRQ controller descriptor.
00374  * @param   irq_id[in] - Interrupt identifier.
00375  * @return  SUCCESS in case of success, FAILURE otherwise.
00376  */
00377 int32_t irq_unregister(struct irq_ctrl_desc *desc, uint32_t irq_id)
00378 {
00379     if (!desc) {
00380         return FAILURE;
00381     }
00382 
00383     switch (irq_id) {
00384     case  EXTERNAL_INT_ID1:
00385         mbed_irq_callbacks.callback_ext_int_id1.callback = NULL;
00386         break;
00387 
00388     case EXTERNAL_INT_ID2:
00389         mbed_irq_callbacks.callback_ext_int_id2.callback = NULL;
00390         break;
00391 
00392     case EXTERNAL_INT_ID3:
00393         mbed_irq_callbacks.callback_ext_int_id3.callback = NULL;
00394         break;
00395 
00396     case EXTERNAL_INT_ID4:
00397         mbed_irq_callbacks.callback_ext_int_id4.callback = NULL;
00398         break;
00399 
00400     case EXTERNAL_INT_ID5:
00401         mbed_irq_callbacks.callback_ext_int_id5.callback = NULL;
00402         break;
00403 
00404     case UART_RX_INT_ID1:
00405         mbed_irq_callbacks.callback_uart_rx_id1.callback = NULL;
00406         break;
00407 
00408     case TICKER_INT_ID:
00409         mbed_irq_callbacks.callback_ticker_id.callback = NULL;
00410         break;
00411 
00412     default:
00413         return FAILURE;
00414     }
00415 
00416     return SUCCESS;
00417 }
00418 
00419 /**
00420  * @brief   Enable specific interrupt
00421  * @param   desc[in] - The IRQ controller descriptor.
00422  * @param   irq_id[in] - Interrupt identifier.
00423  * @return  SUCCESS in case of success, FAILURE otherwise.
00424  */
00425 int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id)
00426 {
00427     InterruptIn *ext_interrupt;
00428     mbed::UnbufferedSerial *uart_rx_port;
00429     mbed::Ticker *ticker;
00430 
00431     if (!desc || !desc->extra) {
00432         return FAILURE;
00433     }
00434 
00435     switch (irq_id) {
00436     case EXTERNAL_INT_ID1:
00437     case EXTERNAL_INT_ID2:
00438     case EXTERNAL_INT_ID3:
00439     case EXTERNAL_INT_ID4:
00440     case EXTERNAL_INT_ID5:
00441         ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
00442         ext_interrupt->enable_irq();
00443         break;
00444 
00445     case UART_RX_INT_ID1:
00446         uart_rx_port = (mbed::UnbufferedSerial *)(((mbed_irq_desc *)(
00447                     desc->extra))->int_obj);
00448         uart_rx_port->attach(mbed_uart_rx_id1_callback, UnbufferedSerial::RxIrq);
00449         break;
00450 
00451     case TICKER_INT_ID:
00452         ticker = (mbed::Ticker *)(((mbed_irq_desc *)(desc->extra))->int_obj);
00453         ticker->attach(mbed_ticker_id_callback,
00454                    microseconds(((mbed_irq_desc *)(desc->extra))->ticker_period_usec));
00455         break;
00456 
00457     default:
00458         return FAILURE;
00459     }
00460 
00461     return SUCCESS;
00462 }
00463 
00464 /**
00465  * @brief   Disable specific interrupt
00466  * @param   desc[in] - The IRQ controller descriptor.
00467  * @param   irq_id[in] - Interrupt identifier.
00468  * @return  SUCCESS in case of success, FAILURE otherwise.
00469  */
00470 int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id)
00471 {
00472     InterruptIn *ext_interrupt;
00473     mbed::UnbufferedSerial *uart_rx_port;
00474     mbed::Ticker *ticker;
00475 
00476     if (!desc || !desc->extra) {
00477         return FAILURE;
00478     }
00479 
00480     switch (irq_id) {
00481     case EXTERNAL_INT_ID1:
00482     case EXTERNAL_INT_ID2:
00483     case EXTERNAL_INT_ID3:
00484     case EXTERNAL_INT_ID4:
00485     case EXTERNAL_INT_ID5:
00486         ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
00487         ext_interrupt->disable_irq();
00488         break;
00489 
00490     case UART_RX_INT_ID1:
00491         uart_rx_port = (mbed::UnbufferedSerial *)(((mbed_irq_desc *)(
00492                     desc->extra))->int_obj);
00493         uart_rx_port->attach(NULL, UnbufferedSerial::RxIrq);
00494         break;
00495 
00496     case TICKER_INT_ID:
00497         ticker = (mbed::Ticker *)(((mbed_irq_desc *)(desc->extra))->int_obj);
00498         ticker->detach();
00499         break;
00500 
00501     default:
00502         return FAILURE;
00503     }
00504 
00505     return SUCCESS;
00506 }
00507 
00508 #ifdef __cplusplus // Closing extern c
00509 }
00510 #endif