Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
irq.cpp
- Committer:
- mahphalke
- Date:
- 2021-07-13
- Revision:
- 17:af1f2416dd26
File content as of revision 17:af1f2416dd26:
/***************************************************************************//**
* @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