Forked repo of Platform Drivers- Analog Devices

Files at this revision

API Documentation at this revision

Comitter:
Janani Sunil
Date:
Mon Nov 22 22:26:51 2021 +0530
Parent:
19:3c61197500c4
Commit message:
The following changes were made:
1.) Modified udelay() function for generating more accurate smaller usec delays
2.) Implemented the irq_enable and irq_disable functions
3.) Removed the confusion b/w application created peripheral object and interrupt specific object
4.) Created PWM extra init structure and added PWM pin as it's member for multiplatform project compatibility
5.) Added a module for timer and its related header file

Changed in this revision

delay.cpp Show annotated file Show diff for this revision Revisions of this file
irq.cpp Show annotated file Show diff for this revision Revisions of this file
irq_extra.h Show annotated file Show diff for this revision Revisions of this file
pwm.cpp Show annotated file Show diff for this revision Revisions of this file
pwm_extra.h Show annotated file Show diff for this revision Revisions of this file
spi.cpp Show annotated file Show diff for this revision Revisions of this file
timer.cpp Show annotated file Show diff for this revision Revisions of this file
timer_extra.h Show annotated file Show diff for this revision Revisions of this file
--- a/delay.cpp	Wed Sep 29 12:32:10 2021 +0100
+++ b/delay.cpp	Mon Nov 22 22:26:51 2021 +0530
@@ -39,7 +39,10 @@
  */
 void udelay(uint32_t usecs)
 {
-	wait_us(usecs);
+	/* wait_ns is more time efficient function compared to wait_us
+	 * Note: For higher values of delay (more than few msec), it is better to use
+	 * mdelay() function as no error/limit checking is done in this function */
+	wait_ns(usecs * 1000);
 }
 
 /**
@@ -50,7 +53,7 @@
 void mdelay(uint32_t msecs)
 {
 	if (msecs) {
-		HAL_Delay(msecs);
+		thread_sleep_for(msecs);
 	}
 }
 
--- a/irq.cpp	Wed Sep 29 12:32:10 2021 +0100
+++ b/irq.cpp	Mon Nov 22 22:26:51 2021 +0530
@@ -164,6 +164,7 @@
 		      const struct irq_init_param *param)
 {
 	mbed::Ticker *ticker;
+	InterruptIn *ext_interrupt;
 	mbed_irq_desc *new_mbed_desc;
 
 	if (!desc || !param) {
@@ -181,28 +182,49 @@
 	}
 
 	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 */
+	switch (param->irq_ctrl_id) {
+	case EXTERNAL_INT_ID1:
+	case EXTERNAL_INT_ID2:
+	case EXTERNAL_INT_ID3:
+	case EXTERNAL_INT_ID4:
+	case EXTERNAL_INT_ID5:
+		/* Create a new external interrupt object */
+		ext_interrupt = new InterruptIn((PinName)(new_mbed_desc->ext_int_pin));
+		if (!ext_interrupt) {
+			goto err_interrupt;
+		}
+
+		new_mbed_desc->int_obj = (mbed::InterruptIn *)ext_interrupt;
+		break;
+
+	case TICKER_INT_ID:
+		/* 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
+		* */
 		ticker = new Ticker();
 		if (!ticker) {
-			goto err_ticker;
+			goto err_interrupt;
 		}
 
-		new_mbed_desc->int_obj_type = (mbed::Ticker *)ticker;
+		new_mbed_desc->int_obj = (mbed::Ticker *)ticker;
 		new_mbed_desc->ticker_period_usec = ((mbed_irq_init_param *)
 						     param->extra)->ticker_period_usec;
+		break;
+
+	case UART_RX_INT_ID1:
+		/* UART object must be created from uart.cpp module by an application */
+		new_mbed_desc->int_obj = ((mbed_irq_init_param *)
+					  param->extra)->int_obj_type;
+		break;
+
+	default:
+		goto err_interrupt;
 	}
 
 	new_desc->extra = (irq_ctrl_desc *)new_mbed_desc;
@@ -211,7 +233,7 @@
 
 	return SUCCESS;
 
-err_ticker:
+err_interrupt:
 	free(new_mbed_desc);
 err_new_mbed_desc:
 	free(new_desc);
@@ -268,9 +290,6 @@
 			      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) {
@@ -283,17 +302,6 @@
 	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;
@@ -329,7 +337,9 @@
 			return FAILURE;
 		}
 
-		/* Register a callback function to external interrupt event */
+		ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
+
+		/* Select interrupt mode */
 		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) {
@@ -338,41 +348,16 @@
 			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:
@@ -431,6 +416,95 @@
 	return SUCCESS;
 }
 
+/**
+ * @brief	Enable specific interrupt
+ * @param	desc[in] - The IRQ controller descriptor.
+ * @param	irq_id[in] - Interrupt identifier.
+ * @return	SUCCESS in case of success, FAILURE otherwise.
+ */
+int32_t irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id)
+{
+	InterruptIn *ext_interrupt;
+	mbed::UnbufferedSerial *uart_rx_port;
+	mbed::Ticker *ticker;
+
+	if (!desc || !desc->extra) {
+		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:
+		ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
+		ext_interrupt->enable_irq();
+		break;
+
+	case UART_RX_INT_ID1:
+		uart_rx_port = (mbed::UnbufferedSerial *)(((mbed_irq_desc *)(
+					desc->extra))->int_obj);
+		uart_rx_port->attach(mbed_uart_rx_id1_callback, UnbufferedSerial::RxIrq);
+		break;
+
+	case TICKER_INT_ID:
+		ticker = (mbed::Ticker *)(((mbed_irq_desc *)(desc->extra))->int_obj);
+		ticker->attach(mbed_ticker_id_callback,
+			       microseconds(((mbed_irq_desc *)(desc->extra))->ticker_period_usec));
+		break;
+
+	default:
+		return FAILURE;
+	}
+
+	return SUCCESS;
+}
+
+/**
+ * @brief	Disable specific interrupt
+ * @param	desc[in] - The IRQ controller descriptor.
+ * @param	irq_id[in] - Interrupt identifier.
+ * @return	SUCCESS in case of success, FAILURE otherwise.
+ */
+int32_t irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id)
+{
+	InterruptIn *ext_interrupt;
+	mbed::UnbufferedSerial *uart_rx_port;
+	mbed::Ticker *ticker;
+
+	if (!desc || !desc->extra) {
+		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:
+		ext_interrupt = (InterruptIn *)(((mbed_irq_desc *)(desc->extra))->int_obj);
+		ext_interrupt->disable_irq();
+		break;
+
+	case UART_RX_INT_ID1:
+		uart_rx_port = (mbed::UnbufferedSerial *)(((mbed_irq_desc *)(
+					desc->extra))->int_obj);
+		uart_rx_port->attach(NULL, UnbufferedSerial::RxIrq);
+		break;
+
+	case TICKER_INT_ID:
+		ticker = (mbed::Ticker *)(((mbed_irq_desc *)(desc->extra))->int_obj);
+		ticker->detach();
+		break;
+
+	default:
+		return FAILURE;
+	}
+
+	return SUCCESS;
+}
+
 #ifdef __cplusplus // Closing extern c
 }
 #endif
--- a/irq_extra.h	Wed Sep 29 12:32:10 2021 +0100
+++ b/irq_extra.h	Mon Nov 22 22:26:51 2021 +0530
@@ -74,7 +74,8 @@
 	uint32_t int_mode;				// Interrupt mode (falling/rising etc)
 	uint32_t ext_int_pin; 			// External Interrupt pin
 	uint32_t ticker_period_usec;	// Time period in usec for ticker event
-	void *int_obj_type;  			// Interrupt handling object
+	/* Application created peripheral object to attach/generate interrupt for (e.g. UART) */
+	void *int_obj_type;
 } mbed_irq_init_param;
 
 /**
@@ -85,8 +86,7 @@
 	uint32_t int_mode;				// Interrupt mode (falling/rising etc)
 	uint32_t ext_int_pin;			// External Interrupt pin
 	uint32_t ticker_period_usec; 	// Time period in usec for ticker event
-	void *int_obj_type;  			// Interrupt handling object
-	void *int_obj;					// Interrupt object (e.g. InterruptIn)
+	void *int_obj;					// Interrupt specific object (e.g. InterruptIn, Ticker)
 } mbed_irq_desc;
 
 #ifdef __cplusplus // Closing extern c
--- a/pwm.cpp	Wed Sep 29 12:32:10 2021 +0100
+++ b/pwm.cpp	Mon Nov 22 22:26:51 2021 +0530
@@ -68,11 +68,11 @@
 		goto err_new_pwm_desc;
 	}
 
-	new_pwm_desc->id = param->id;	// Pin number
+	new_pwm_desc->id = param->id;	// PWM Id
 	new_pwm_desc->period_ns = param->period_ns;	// PWM period
 
 	/* Create and initialize Mbed PWM object */
-	pwm = new PwmOut((PinName)param->id);
+	pwm = new PwmOut((PinName)((mbed_pwm_init_param *)(param->extra))->pwm_pin);
 	if (!pwm) {
 		goto err_pwm;
 	}
--- a/pwm_extra.h	Wed Sep 29 12:32:10 2021 +0100
+++ b/pwm_extra.h	Mon Nov 22 22:26:51 2021 +0530
@@ -34,6 +34,10 @@
 /********************** Variables and User defined data types *****************/
 /******************************************************************************/
 
+typedef struct {
+	uint16_t pwm_pin;	// PWM pin number
+} mbed_pwm_init_param;
+
 struct mbed_pwm_desc {
 	void *pwm_obj;	/* Mbed PWM instance/object */
 };
--- a/spi.cpp	Wed Sep 29 12:32:10 2021 +0100
+++ b/spi.cpp	Mon Nov 22 22:26:51 2021 +0530
@@ -217,6 +217,56 @@
 	return FAILURE;
 }
 
+
+/**
+ * @brief Transfer (write/read) the number of SPI messages
+ * @param desc - The SPI descriptor
+ * @param msgs - Pointer to SPI messages
+ * @param num_of_msgs - Number of SPI messages
+ * @return SUCCESS in case of success, FAILURE otherwise.
+ * @note Use of this function requires CSB pin to be software controlled
+ */
+int32_t spi_transfer(struct spi_desc *desc, struct spi_msg *msgs,
+		     uint32_t num_of_msgs)
+{
+	mbed::SPI *spi; 			// pointer to new spi instance
+	mbed::DigitalOut *csb;   	// pointer to new CSB instance
+	uint8_t msg_cnt;			// SPI message counter
+
+	if (desc) {
+		if (!((mbed_spi_desc *)desc->extra)->use_sw_csb)
+			return FAILURE;
+
+		spi = (SPI *)(((mbed_spi_desc *)(desc->extra))->spi_port);
+		csb = (DigitalOut *)(((mbed_spi_desc *)(desc->extra))->csb_gpio);
+
+		if (!spi || !csb)
+			return FAILURE;
+
+		for (msg_cnt = 0; msg_cnt < num_of_msgs; msg_cnt++) {
+			csb->write(GPIO_LOW);
+
+			/* Perform synchronous SPI write and read */
+			if (!msgs[msg_cnt].tx_buff) {
+				spi->write(NULL, 0,
+					   (char *)msgs[msg_cnt].rx_buff, msgs[msg_cnt].bytes_number);
+			} else {
+				spi->write((const char *)msgs[msg_cnt].tx_buff, msgs[msg_cnt].bytes_number,
+					   (char *)msgs[msg_cnt].rx_buff, msgs[msg_cnt].bytes_number);
+			}
+
+			if (msgs[msg_cnt].cs_change) {
+				csb->write(GPIO_HIGH);
+			}
+		}
+
+		csb->write(GPIO_HIGH);
+		return SUCCESS;
+	}
+
+	return FAILURE;
+}
+
 #ifdef __cplusplus  // Closing extern c
 }
 #endif //  _cplusplus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timer.cpp	Mon Nov 22 22:26:51 2021 +0530
@@ -0,0 +1,190 @@
+/**************************************************************************//**
+ *   @file    timer.cpp
+ *   @brief   Implementation of Timer MBED Platform Driver Interfaces
+*******************************************************************************
+ * Copyright (c) 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 Drivers need to be C-compatible to work with other drivers
+#ifdef __cplusplus
+extern "C"
+{
+#endif	//__cplusplus
+
+#include "timer.h"
+#include "error.h"
+#include "timer_extra.h"
+using namespace std::chrono;
+
+/*****************************************************************************/
+/******************** Variables and User Defined Data Types ******************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/************************** Functions Declarations ***************************/
+/*****************************************************************************/
+
+/*****************************************************************************/
+/************************** Functions Definitions ****************************/
+/*****************************************************************************/
+
+/**
+ * @brief Initialize the timer peripheral
+ * @param desc[in, out] - The Timer descriptor
+ * @param init_param[in] - Structure that contains Timer Initialization Parameters
+ * @return SUCCESS in case of success, FAILURE otherwise
+ */
+int32_t timer_init(struct timer_desc **desc,
+		   struct timer_init_param *param)
+{
+	timer_desc *new_timer;			// Pointer to timer descriptor
+	mbed_timer_desc *mbed_desc;		// Pointer to mbed timer descriptor
+	mbed::Timer *timer;				// Pointer to new Timer instance
+
+	if (desc && param) {
+		new_timer = (timer_desc *)malloc(sizeof(timer_desc));
+		if (!new_timer) {
+			goto err_new_desc;
+		}
+		new_timer->freq_hz = param->freq_hz;
+		new_timer->id = param->id;
+		new_timer->load_value = param->load_value;
+
+		mbed_desc = (mbed_timer_desc *)malloc(sizeof(mbed_timer_desc));
+		if (!mbed_desc) {
+			goto err_mbed_desc;
+		}
+
+		timer  = new Timer();
+		if (!timer) {
+			goto err_timer_instance;
+		}
+
+		mbed_desc->timer  = timer;
+		new_timer->extra = (mbed_timer_desc *) mbed_desc;
+
+		*desc = new_timer;
+		return SUCCESS;
+	}
+	return FAILURE;
+
+err_timer_instance:
+	free(mbed_desc);
+	free(new_timer);
+err_mbed_desc:
+	free(new_timer);
+err_new_desc:
+	// Nothing to free
+
+	return FAILURE;
+}
+
+
+/**
+* @brief Start Timer.
+* @param desc[in] - The Timer Descriptor.
+* @return SUCCESS in case of success, FAILURE otherwise.
+*/
+int32_t timer_start(struct timer_desc *desc)
+{
+	mbed::Timer *timer;
+
+	if (!desc) {
+		return FAILURE;
+	}
+	timer = (Timer *)(((mbed_timer_desc *)(desc->extra))->timer);
+	if (!timer) {
+		return FAILURE;
+	}
+	timer->start();
+
+	return SUCCESS;
+}
+
+
+/**
+* @brief Stop Timer.
+* @param desc[in] - The Timer Descriptor.
+* @return SUCCESS in case of success, FAILURE otherwise.
+*/
+int32_t timer_stop(struct timer_desc *desc)
+{
+	mbed::Timer *timer;
+
+	if (!desc) {
+		return FAILURE;
+	}
+	timer = (Timer *)(((mbed_timer_desc *)(desc->extra))->timer);
+	if (!timer) {
+		return FAILURE;
+	}
+	timer->stop();
+
+	return SUCCESS;
+}
+
+
+/**
+* @brief Release all the resources allocated by Timer.
+* @param desc[in] - The Timer Descriptor.
+* @return SUCCESS in case of success, FAILURE otherwise
+*/
+int32_t timer_remove(struct timer_desc *desc)
+{
+	if (desc) {
+		// Free the timer object
+		if ((Timer *)(((mbed_timer_desc *)(desc->extra))->timer)) {
+			delete((Timer *)(((mbed_timer_desc *)(desc->extra))->timer));
+		}
+		// Free the extra descriptor object
+		if ((mbed_timer_desc *)(desc->extra)) {
+			free((mbed_timer_desc *)(desc->extra));
+		}
+		// Free the Timer descriptor
+		free(desc);
+
+		return SUCCESS;
+	}
+	return FAILURE;
+}
+
+
+/**
+* @brief Get the elapsed time in nanoseconds.
+* @param desc[in] - The Timer descriptor
+* @param elapsed_time[out] - Pointer where the elapsed time value is stored
+* @return SUCCESS in case of success, FAILURE otherwise
+*/
+int32_t get_elapsed_time_in_nsec(struct timer_desc *desc,
+				 uint64_t *elapsed_time)
+{
+	mbed::Timer *timer;
+
+	if (!desc) {
+		return FAILURE;
+	}
+
+	timer = (Timer *)(((mbed_timer_desc *)(desc->extra))->timer);
+	if (!timer) {
+		return FAILURE;
+	}
+	*elapsed_time = duration_cast<nanoseconds>(timer->elapsed_time()).count();
+
+	return SUCCESS;
+}
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timer_extra.h	Mon Nov 22 22:26:51 2021 +0530
@@ -0,0 +1,57 @@
+/***************************************************************************//*
+ * @file    timer_extra.h
+ * @brief   Header containing extra types for Timer interface
+******************************************************************************
+ * Copyright (c) 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.
+******************************************************************************/
+
+#ifndef _TIMER_EXTRA_H_
+#define _TIMER_EXTRA_H_
+
+// Platform support needs to be C-compatible to work with other drivers
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************/
+/***************************** Include Files *********************************/
+/*****************************************************************************/
+
+#include "stdio.h"
+#include "stdint.h"
+
+/*****************************************************************************/
+/********************** Macros and Constants Definition **********************/
+/*****************************************************************************/
+
+/******************************************************************************/
+/********************** Variables and User defined data types *****************/
+/******************************************************************************/
+
+/**
+* @struct mbed_timer_desc
+* @brief Structure holding the mbed specific Timer parameters
+*/
+typedef struct mbed_timer_desc {
+	void *timer;		// Object to the mbed Timer class
+} mbed_timer_desc;
+
+/******************************************************************************/
+/*****************************Function Declarations****************************/
+/******************************************************************************/
+
+/* Function to capture the elapsed time in nanoseconds */
+int32_t	get_elapsed_time_in_nsec(struct timer_desc *desc,
+				 uint64_t *elapsed_time);
+
+#ifdef __cplusplus // Closing extern c
+}
+#endif
+
+#endif /*_TIMER_EXTRA_H_ */