Platform drivers for Mbed.
Dependents: EVAL-CN0535-FMCZ EVAL-CN0535-FMCZ EVAL-AD568x-AD569x EVAL-AD7606 ... more
Revision 20:4951ea6abee5, committed 2021-11-29
- Comitter:
- Kjansen
- Date:
- Mon Nov 29 12:39:54 2021 +0000
- 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
5.) Added a module for timer and its related header file
Changed in this revision
diff -r 3c61197500c4 -r 4951ea6abee5 delay.cpp --- a/delay.cpp Wed Sep 29 12:32:10 2021 +0100 +++ b/delay.cpp Mon Nov 29 12:39:54 2021 +0000 @@ -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); } }
diff -r 3c61197500c4 -r 4951ea6abee5 irq.cpp --- a/irq.cpp Wed Sep 29 12:32:10 2021 +0100 +++ b/irq.cpp Mon Nov 29 12:39:54 2021 +0000 @@ -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
diff -r 3c61197500c4 -r 4951ea6abee5 irq_extra.h --- a/irq_extra.h Wed Sep 29 12:32:10 2021 +0100 +++ b/irq_extra.h Mon Nov 29 12:39:54 2021 +0000 @@ -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
diff -r 3c61197500c4 -r 4951ea6abee5 pwm.cpp --- a/pwm.cpp Wed Sep 29 12:32:10 2021 +0100 +++ b/pwm.cpp Mon Nov 29 12:39:54 2021 +0000 @@ -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; }
diff -r 3c61197500c4 -r 4951ea6abee5 pwm_extra.h --- a/pwm_extra.h Wed Sep 29 12:32:10 2021 +0100 +++ b/pwm_extra.h Mon Nov 29 12:39:54 2021 +0000 @@ -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 */ };
diff -r 3c61197500c4 -r 4951ea6abee5 spi.cpp --- a/spi.cpp Wed Sep 29 12:32:10 2021 +0100 +++ b/spi.cpp Mon Nov 29 12:39:54 2021 +0000 @@ -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
diff -r 3c61197500c4 -r 4951ea6abee5 timer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/timer.cpp Mon Nov 29 12:39:54 2021 +0000 @@ -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
diff -r 3c61197500c4 -r 4951ea6abee5 timer_extra.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/timer_extra.h Mon Nov 29 12:39:54 2021 +0000 @@ -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_ */