Platform drivers for Mbed.

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

Revision:
17:af1f2416dd26
Child:
20:4951ea6abee5
--- /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