From ffc7b911289b3f030bc6cef2619315cb1199de92 Mon Sep 17 00:00:00 2001 From: "Galanakis, Minos" Date: Wed, 20 Dec 2017 09:35:31 +0000 Subject: [PATCH 1/4] CM3DS: update tickers implementation The HAL implementation (us_ticker.c and lp_ticker.c) now calls function in cmsdk_ticker.c file. This file contains the necessary logic to be able to only use one hardware timer (CMSDK timer) per mbed ticker. This commit also updates the timer driver and removes legacy definition. Change-Id: If40413822832117f9b78f38d2cdda7847284b035 Signed-off-by: Galanakis, Minos Signed-off-by: Hugues de Valon --- .../TARGET_CM3DS_MPS2/cmsdk_ticker.c | 166 +++++++++++ .../TARGET_CM3DS_MPS2/cmsdk_ticker.h | 150 ++++++++++ .../TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h | 192 +------------ .../TARGET_CM3DS_MPS2/device/apb_timer.c | 265 ------------------ .../TARGET_CM3DS_MPS2/device/apb_timer.h | 111 -------- .../TARGET_CM3DS_MPS2/device/cmsis.h | 4 +- .../TARGET_CM3DS_MPS2/device/device_cfg.h | 33 +++ .../drivers/timer_cmsdk/timer_cmsdk_drv.c | 223 +++++++++++++++ .../drivers/timer_cmsdk/timer_cmsdk_drv.h | 254 +++++++++++++++++ .../device/platform_devices.c | 37 +++ .../device/platform_devices.h | 36 +++ .../TARGET_CM3DS_MPS2/lp_ticker.c | 113 ++++++++ .../TARGET_CM3DS_MPS2/us_ticker.c | 169 +++++------ targets/targets.json | 2 +- 14 files changed, 1086 insertions(+), 669 deletions(-) create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.c create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.h delete mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.c delete mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.h create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.c create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.h create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.c new file mode 100644 index 0000000000..74dbc55588 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file cmsdk_ticker.c + * Two abstracted functionalities for CMSDK APB Timers + * 1. Measure elapsed time + * 2. Timer interval interrupt + * + * Passed \ref tick_drv_data_t should be initialized by the caller + * for using these services accordingly. + * See details \ref tick_cfg_t and \ref tick_data_t. + */ + +#include "cmsdk_ticker.h" + +void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data) +{ + if (!timer_data->data->is_initialized) { + timer_cmsdk_init(timer_data->cfg->timer_driver); + timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver, + TIMER_CMSDK_MAX_RELOAD); + timer_cmsdk_enable_interrupt(timer_data->cfg->timer_driver); + NVIC_EnableIRQ(timer_data->cfg->irq_n); + + timer_data->data->max_interval_time = + timer_data->cfg->convert_tick_to_time(TIMER_CMSDK_MAX_RELOAD); + timer_data->data->reload_time = timer_data->data->max_interval_time; + timer_data->data->is_initialized = true; + timer_cmsdk_enable(timer_data->cfg->timer_driver); + } +} + +uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data) +{ + uint32_t current_elapsed = 0; + + if (!timer_data->data->is_initialized) { + cmsdk_ticker_init(timer_data); + } + current_elapsed = timer_cmsdk_get_elapsed_value(timer_data->cfg->timer_driver); + /* + * If for the same reload cycle (ie. cumulated_time is the same) the + * current elapsed time is lower than the previous one, it means that the + * timer has wrapped around without the system logging it. To ensure that + * we are always returning an increasing time in those condition, we return + * the time perviously read. + */ + if ((timer_data->data->previous_cumulated_time == + timer_data->data->cumulated_time) && + (current_elapsed < timer_data->data->previous_elapsed)) { + current_elapsed = timer_data->data->previous_elapsed; + } + + timer_data->data->previous_elapsed = current_elapsed; + timer_data->data->previous_cumulated_time = + timer_data->data->cumulated_time; + + return (timer_data->data->cumulated_time + + timer_data->cfg->convert_tick_to_time(current_elapsed)); +} + +void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data, + uint32_t timestamp) +{ + uint32_t interval = 0; + uint32_t interval_reload_tick = 0; + + /* Stop before read to avoid race condition with IRQ. */ + timer_cmsdk_disable(timer_data->cfg->timer_driver); + uint32_t current_time = cmsdk_ticker_read(timer_data); + + timer_data->data->interval_callback_enabled = true; + + /* + * We always assume that the event is in the future, even if this + * substraction underflows it is still corect. + */ + interval = (timestamp - current_time); + + if (interval >= timer_data->data->max_interval_time) { + /* Event will be in the future but the time is too big: set max */ + interval_reload_tick = TIMER_CMSDK_MAX_RELOAD; + timer_data->data->reload_time = timer_data->data->max_interval_time; + } else { + /* Event will be in the future in a time that can be set */ + interval_reload_tick = + timer_data->cfg->convert_time_to_tick(interval); + timer_data->data->reload_time = interval; + } + + /* Store the current elapsed time, before reset the timer */ + timer_data->data->cumulated_time = current_time; + /* Reset the timer with new reload value */ + timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver, + interval_reload_tick); + timer_cmsdk_reset(timer_data->cfg->timer_driver); + + timer_cmsdk_enable(timer_data->cfg->timer_driver); +} + +void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data) +{ + if (!timer_data->data->is_initialized) { + cmsdk_ticker_init(timer_data); + } + + timer_data->data->interval_callback_enabled = false; + + /* Stop before read to avoid race condition with IRQ. */ + timer_cmsdk_disable(timer_data->cfg->timer_driver); + /* If interval interrupt is disabled, restore the default max interval, + * but save the current elapsed time before changing the timer. */ + timer_data->data->cumulated_time = cmsdk_ticker_read(timer_data); + /* Reset the timer with default reload value */ + timer_cmsdk_set_reload_value(timer_data->cfg->timer_driver, + TIMER_CMSDK_MAX_RELOAD); + timer_data->data->reload_time = timer_data->data->max_interval_time; + + timer_cmsdk_reset(timer_data->cfg->timer_driver); + timer_cmsdk_enable(timer_data->cfg->timer_driver); +} + +void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data) +{ + timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver); +} + +void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data) +{ + NVIC_SetPendingIRQ(timer_data->cfg->irq_n); +} + +void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data) +{ + uint32_t reload_val = 0; + /* If timer's internal interrupt status is not active, then not overflow, + * but explicit interrupt request was fired by cmsdk_ticker_fire_interrupt. + */ + if (timer_cmsdk_is_interrupt_active(timer_data->cfg->timer_driver)) { + /* 1. Calculate cumulated time by overflow */ + timer_cmsdk_clear_interrupt(timer_data->cfg->timer_driver); + reload_val = timer_cmsdk_get_reload_value(timer_data->cfg->timer_driver); + timer_data->data->cumulated_time += + timer_data->cfg->convert_tick_to_time(reload_val); + } + + /* 2. Call mbed interval interrupt handler if it's required */ + if (timer_data->data->interval_callback_enabled) { + cmsdk_ticker_disable_interrupt(timer_data); + timer_data->cfg->interval_callback(); + } +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.h new file mode 100644 index 0000000000..93f75c75b1 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/cmsdk_ticker.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +/** + * \file cmsdk_ticker.h + * CMSDK Ticker implements the functionalities of mbed tickers: + * 1. Elapsed time measurement + * 2. Interval interrupt request + * + * This ticker service is based on CMSDK APB Timers, abstracting + * the HAL logic, the timer driver and interrupt number. + * These parameters should be passed to the functions by + * an initialized \ref tick_drv_data_t pointer. + */ + +#ifndef CMSDK_TICKER_H +#define CMSDK_TICKER_H + +#include + +#include "CMSDK_CM3DS.h" +#include "timer_cmsdk_drv.h" + +#define SEC_TO_USEC_MULTIPLIER 1000000U + +/** + * brief Encapsulating struct for config data \ref tick_cfg_t and + * the current status \ref tick_data_t. + */ +struct tick_drv_data_t { + const struct tick_cfg_t* const cfg; + struct tick_data_t* const data; +}; + +/** + * brief Configuration data of the CMSDK ticker + */ +struct tick_cfg_t { + /** Pointer to the used CMSDK Timer's device structure */ + struct timer_cmsdk_dev_t* const timer_driver; + /** IRQ number of the used CMSDK Timer */ + const IRQn_Type irq_n; + /** Interval callback of mbed*/ + void (*const interval_callback)(); + /** Function pointers to call for conversions of clock ticks and defined + * time unit. + * These conversions define the unit of the measured time. + */ + uint32_t (*const convert_tick_to_time)(uint32_t tick); + uint32_t (*const convert_time_to_tick)(uint32_t time); +}; + +/** + * brief Current state data of the CMSDK ticker + */ +struct tick_data_t { + /** True if initialized the ticker, false otherwise */ + bool is_initialized; + /** Measured elapsed time in the defined unit by + * \ref convert_tick_to_time and \ref convert_time_to_tick */ + uint32_t cumulated_time; + /** Max interval time possible to set, in the defined unit by + * \ref convert_tick_to_time and \ref convert_time_to_tick */ + uint32_t max_interval_time; + /** Current reload time in the defined unit by + * \ref convert_tick_to_time and \ref convert_time_to_tick */ + uint32_t reload_time; + /** Interval IRQ callback is requested */ + bool interval_callback_enabled; + /** Previous cumulated time calculated for this ticker. Used in the + * cmsdk_ticker_read function to detect that the timer has wrapped. */ + uint32_t previous_cumulated_time; + /** Previous elapsed value for this ticker. Used in the + * cmsdk_ticker_read function to detect that the timer has wrapped. */ + uint32_t previous_elapsed; +}; + +/** + * \brief Init the CMSDK Ticker + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + */ +void cmsdk_ticker_init(const struct tick_drv_data_t* timer_data); + +/** + * \brief Read elapsed time by CMSDK Ticker + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + * + * \return Elapsed time in the unit defined by \ref convert_tick_to_time + */ + +uint32_t cmsdk_ticker_read(const struct tick_drv_data_t* timer_data); + +/** + * \brief Request interval interrupt by time stamp \ref timestamp_t + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + * \param[in] timestamp Absolute time \ref timestamp_t value when the interval + * is requested. Unit of the timestamp is defined by + * \ref convert_tick_to_time and \ref convert_time_to_tick + */ +void cmsdk_ticker_set_interrupt(const struct tick_drv_data_t* timer_data, + uint32_t timestamp); + +/** + * \brief Disable interval interrupt + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + */ +void cmsdk_ticker_disable_interrupt(const struct tick_drv_data_t* timer_data); + +/** + * \brief Clear interval interrupt + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + */ +void cmsdk_ticker_clear_interrupt(const struct tick_drv_data_t* timer_data); + +/** + * \brief Set pending interrupt that should be fired right away. + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + */ +void cmsdk_ticker_fire_interrupt(const struct tick_drv_data_t* timer_data); + +/** + * \brief Interrupt handler of the given CMSDK Timer + * + * \warning This function may be called from multiple interrupt handlers, + * so extra care must be taken for re-entrancy! + * + * \param[in] timer_data Pointer to the used CMSDK Timer's device structure + */ +void cmsdk_ticker_irq_handler(const struct tick_drv_data_t* timer_data); +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h index 06031211e1..06c9a930fd 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 ARM Limited. All rights reserved. + * Copyright (c) 2009-2018 ARM Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * @@ -202,191 +202,6 @@ typedef struct #define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */ #define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */ - -/*----------------------------- Timer (TIMER) -------------------------------*/ -typedef struct -{ - __IO uint32_t CTRL; /* Offset: 0x000 (R/W) Control Register */ - __IO uint32_t VALUE; /* Offset: 0x004 (R/W) Current Value Register */ - __IO uint32_t RELOAD; /* Offset: 0x008 (R/W) Reload Value Register */ - union { - __I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */ - __O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */ - }; - -} CMSDK_TIMER_TypeDef; - -/* CMSDK_TIMER CTRL Register Definitions */ - -#define CMSDK_TIMER_CTRL_IRQEN_Pos 3 /* CMSDK_TIMER CTRL: IRQEN Position */ -#define CMSDK_TIMER_CTRL_IRQEN_Msk (0x01ul << CMSDK_TIMER_CTRL_IRQEN_Pos) /* CMSDK_TIMER CTRL: IRQEN Mask */ - -#define CMSDK_TIMER_CTRL_SELEXTCLK_Pos 2 /* CMSDK_TIMER CTRL: SELEXTCLK Position */ -#define CMSDK_TIMER_CTRL_SELEXTCLK_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTCLK_Pos) /* CMSDK_TIMER CTRL: SELEXTCLK Mask */ - -#define CMSDK_TIMER_CTRL_SELEXTEN_Pos 1 /* CMSDK_TIMER CTRL: SELEXTEN Position */ -#define CMSDK_TIMER_CTRL_SELEXTEN_Msk (0x01ul << CMSDK_TIMER_CTRL_SELEXTEN_Pos) /* CMSDK_TIMER CTRL: SELEXTEN Mask */ - -#define CMSDK_TIMER_CTRL_EN_Pos 0 /* CMSDK_TIMER CTRL: EN Position */ -#define CMSDK_TIMER_CTRL_EN_Msk (0x01ul << CMSDK_TIMER_CTRL_EN_Pos) /* CMSDK_TIMER CTRL: EN Mask */ - -#define CMSDK_TIMER_VAL_CURRENT_Pos 0 /* CMSDK_TIMER VALUE: CURRENT Position */ -#define CMSDK_TIMER_VAL_CURRENT_Msk (0xFFFFFFFFul << CMSDK_TIMER_VAL_CURRENT_Pos) /* CMSDK_TIMER VALUE: CURRENT Mask */ - -#define CMSDK_TIMER_RELOAD_VAL_Pos 0 /* CMSDK_TIMER RELOAD: RELOAD Position */ -#define CMSDK_TIMER_RELOAD_VAL_Msk (0xFFFFFFFFul << CMSDK_TIMER_RELOAD_VAL_Pos) /* CMSDK_TIMER RELOAD: RELOAD Mask */ - -#define CMSDK_TIMER_INTSTATUS_Pos 0 /* CMSDK_TIMER INTSTATUS: INTSTATUSPosition */ -#define CMSDK_TIMER_INTSTATUS_Msk (0x01ul << CMSDK_TIMER_INTSTATUS_Pos) /* CMSDK_TIMER INTSTATUS: INTSTATUSMask */ - -#define CMSDK_TIMER_INTCLEAR_Pos 0 /* CMSDK_TIMER INTCLEAR: INTCLEAR Position */ -#define CMSDK_TIMER_INTCLEAR_Msk (0x01ul << CMSDK_TIMER_INTCLEAR_Pos) /* CMSDK_TIMER INTCLEAR: INTCLEAR Mask */ - - -/*------------- Timer (TIM) --------------------------------------------------*/ -typedef struct -{ - __IO uint32_t Timer1Load; /* Offset: 0x000 (R/W) Timer 1 Load */ - __I uint32_t Timer1Value; /* Offset: 0x004 (R/ ) Timer 1 Counter Current Value */ - __IO uint32_t Timer1Control; /* Offset: 0x008 (R/W) Timer 1 Control */ - __O uint32_t Timer1IntClr; /* Offset: 0x00C ( /W) Timer 1 Interrupt Clear */ - __I uint32_t Timer1RIS; /* Offset: 0x010 (R/ ) Timer 1 Raw Interrupt Status */ - __I uint32_t Timer1MIS; /* Offset: 0x014 (R/ ) Timer 1 Masked Interrupt Status */ - __IO uint32_t Timer1BGLoad; /* Offset: 0x018 (R/W) Background Load Register */ - uint32_t RESERVED0; - __IO uint32_t Timer2Load; /* Offset: 0x020 (R/W) Timer 2 Load */ - __I uint32_t Timer2Value; /* Offset: 0x024 (R/ ) Timer 2 Counter Current Value */ - __IO uint32_t Timer2Control; /* Offset: 0x028 (R/W) Timer 2 Control */ - __O uint32_t Timer2IntClr; /* Offset: 0x02C ( /W) Timer 2 Interrupt Clear */ - __I uint32_t Timer2RIS; /* Offset: 0x030 (R/ ) Timer 2 Raw Interrupt Status */ - __I uint32_t Timer2MIS; /* Offset: 0x034 (R/ ) Timer 2 Masked Interrupt Status */ - __IO uint32_t Timer2BGLoad; /* Offset: 0x038 (R/W) Background Load Register */ - uint32_t RESERVED1[945]; - __IO uint32_t ITCR; /* Offset: 0xF00 (R/W) Integration Test Control Register */ - __O uint32_t ITOP; /* Offset: 0xF04 ( /W) Integration Test Output Set Register */ -} CMSDK_DUALTIMER_BOTH_TypeDef; - -#define CMSDK_DUALTIMER1_LOAD_Pos 0 /* CMSDK_DUALTIMER1 LOAD: LOAD Position */ -#define CMSDK_DUALTIMER1_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_LOAD_Pos) /* CMSDK_DUALTIMER1 LOAD: LOAD Mask */ - -#define CMSDK_DUALTIMER1_VALUE_Pos 0 /* CMSDK_DUALTIMER1 VALUE: VALUE Position */ -#define CMSDK_DUALTIMER1_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_VALUE_Pos) /* CMSDK_DUALTIMER1 VALUE: VALUE Mask */ - -#define CMSDK_DUALTIMER1_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Position */ -#define CMSDK_DUALTIMER1_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_EN_Pos) /* CMSDK_DUALTIMER1 CTRL_EN: CTRL Enable Mask */ - -#define CMSDK_DUALTIMER1_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Position */ -#define CMSDK_DUALTIMER1_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_MODE_Pos) /* CMSDK_DUALTIMER1 CTRL_MODE: CTRL MODE Mask */ - -#define CMSDK_DUALTIMER1_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Position */ -#define CMSDK_DUALTIMER1_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER1 CTRL_INTEN: CTRL Int Enable Mask */ - -#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Position */ -#define CMSDK_DUALTIMER1_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER1_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER1 CTRL_PRESCALE: CTRL PRESCALE Mask */ - -#define CMSDK_DUALTIMER1_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Position */ -#define CMSDK_DUALTIMER1_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER1 CTRL_SIZE: CTRL SIZE Mask */ - -#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Position */ -#define CMSDK_DUALTIMER1_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER1_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER1 CTRL_ONESHOOT: CTRL ONESHOOT Mask */ - -#define CMSDK_DUALTIMER1_INTCLR_Pos 0 /* CMSDK_DUALTIMER1 INTCLR: INT Clear Position */ -#define CMSDK_DUALTIMER1_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER1_INTCLR_Pos) /* CMSDK_DUALTIMER1 INTCLR: INT Clear Mask */ - -#define CMSDK_DUALTIMER1_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Position */ -#define CMSDK_DUALTIMER1_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER1 RAWINTSTAT: Raw Int Status Mask */ - -#define CMSDK_DUALTIMER1_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Position */ -#define CMSDK_DUALTIMER1_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER1_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER1 MASKINTSTAT: Mask Int Status Mask */ - -#define CMSDK_DUALTIMER1_BGLOAD_Pos 0 /* CMSDK_DUALTIMER1 BGLOAD: Background Load Position */ -#define CMSDK_DUALTIMER1_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER1_BGLOAD_Pos) /* CMSDK_DUALTIMER1 BGLOAD: Background Load Mask */ - -#define CMSDK_DUALTIMER2_LOAD_Pos 0 /* CMSDK_DUALTIMER2 LOAD: LOAD Position */ -#define CMSDK_DUALTIMER2_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_LOAD_Pos) /* CMSDK_DUALTIMER2 LOAD: LOAD Mask */ - -#define CMSDK_DUALTIMER2_VALUE_Pos 0 /* CMSDK_DUALTIMER2 VALUE: VALUE Position */ -#define CMSDK_DUALTIMER2_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_VALUE_Pos) /* CMSDK_DUALTIMER2 VALUE: VALUE Mask */ - -#define CMSDK_DUALTIMER2_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Position */ -#define CMSDK_DUALTIMER2_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_EN_Pos) /* CMSDK_DUALTIMER2 CTRL_EN: CTRL Enable Mask */ - -#define CMSDK_DUALTIMER2_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Position */ -#define CMSDK_DUALTIMER2_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_MODE_Pos) /* CMSDK_DUALTIMER2 CTRL_MODE: CTRL MODE Mask */ - -#define CMSDK_DUALTIMER2_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Position */ -#define CMSDK_DUALTIMER2_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER2 CTRL_INTEN: CTRL Int Enable Mask */ - -#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Position */ -#define CMSDK_DUALTIMER2_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER2_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER2 CTRL_PRESCALE: CTRL PRESCALE Mask */ - -#define CMSDK_DUALTIMER2_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Position */ -#define CMSDK_DUALTIMER2_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER2 CTRL_SIZE: CTRL SIZE Mask */ - -#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Position */ -#define CMSDK_DUALTIMER2_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER2_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER2 CTRL_ONESHOOT: CTRL ONESHOOT Mask */ - -#define CMSDK_DUALTIMER2_INTCLR_Pos 0 /* CMSDK_DUALTIMER2 INTCLR: INT Clear Position */ -#define CMSDK_DUALTIMER2_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER2_INTCLR_Pos) /* CMSDK_DUALTIMER2 INTCLR: INT Clear Mask */ - -#define CMSDK_DUALTIMER2_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Position */ -#define CMSDK_DUALTIMER2_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER2 RAWINTSTAT: Raw Int Status Mask */ - -#define CMSDK_DUALTIMER2_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Position */ -#define CMSDK_DUALTIMER2_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER2_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER2 MASKINTSTAT: Mask Int Status Mask */ - -#define CMSDK_DUALTIMER2_BGLOAD_Pos 0 /* CMSDK_DUALTIMER2 BGLOAD: Background Load Position */ -#define CMSDK_DUALTIMER2_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER2_BGLOAD_Pos) /* CMSDK_DUALTIMER2 BGLOAD: Background Load Mask */ - - -typedef struct -{ - __IO uint32_t TimerLoad; /* Offset: 0x000 (R/W) Timer Load */ - __I uint32_t TimerValue; /* Offset: 0x000 (R/W) Timer Counter Current Value */ - __IO uint32_t TimerControl; /* Offset: 0x000 (R/W) Timer Control */ - __O uint32_t TimerIntClr; /* Offset: 0x000 (R/W) Timer Interrupt Clear */ - __I uint32_t TimerRIS; /* Offset: 0x000 (R/W) Timer Raw Interrupt Status */ - __I uint32_t TimerMIS; /* Offset: 0x000 (R/W) Timer Masked Interrupt Status */ - __IO uint32_t TimerBGLoad; /* Offset: 0x000 (R/W) Background Load Register */ -} CMSDK_DUALTIMER_SINGLE_TypeDef; - -#define CMSDK_DUALTIMER_LOAD_Pos 0 /* CMSDK_DUALTIMER LOAD: LOAD Position */ -#define CMSDK_DUALTIMER_LOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_LOAD_Pos) /* CMSDK_DUALTIMER LOAD: LOAD Mask */ - -#define CMSDK_DUALTIMER_VALUE_Pos 0 /* CMSDK_DUALTIMER VALUE: VALUE Position */ -#define CMSDK_DUALTIMER_VALUE_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_VALUE_Pos) /* CMSDK_DUALTIMER VALUE: VALUE Mask */ - -#define CMSDK_DUALTIMER_CTRL_EN_Pos 7 /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Position */ -#define CMSDK_DUALTIMER_CTRL_EN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_EN_Pos) /* CMSDK_DUALTIMER CTRL_EN: CTRL Enable Mask */ - -#define CMSDK_DUALTIMER_CTRL_MODE_Pos 6 /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Position */ -#define CMSDK_DUALTIMER_CTRL_MODE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_MODE_Pos) /* CMSDK_DUALTIMER CTRL_MODE: CTRL MODE Mask */ - -#define CMSDK_DUALTIMER_CTRL_INTEN_Pos 5 /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Position */ -#define CMSDK_DUALTIMER_CTRL_INTEN_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_INTEN_Pos) /* CMSDK_DUALTIMER CTRL_INTEN: CTRL Int Enable Mask */ - -#define CMSDK_DUALTIMER_CTRL_PRESCALE_Pos 2 /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Position */ -#define CMSDK_DUALTIMER_CTRL_PRESCALE_Msk (0x3ul << CMSDK_DUALTIMER_CTRL_PRESCALE_Pos) /* CMSDK_DUALTIMER CTRL_PRESCALE: CTRL PRESCALE Mask */ - -#define CMSDK_DUALTIMER_CTRL_SIZE_Pos 1 /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Position */ -#define CMSDK_DUALTIMER_CTRL_SIZE_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_SIZE_Pos) /* CMSDK_DUALTIMER CTRL_SIZE: CTRL SIZE Mask */ - -#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos 0 /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Position */ -#define CMSDK_DUALTIMER_CTRL_ONESHOOT_Msk (0x1ul << CMSDK_DUALTIMER_CTRL_ONESHOOT_Pos) /* CMSDK_DUALTIMER CTRL_ONESHOOT: CTRL ONESHOOT Mask */ - -#define CMSDK_DUALTIMER_INTCLR_Pos 0 /* CMSDK_DUALTIMER INTCLR: INT Clear Position */ -#define CMSDK_DUALTIMER_INTCLR_Msk (0x1ul << CMSDK_DUALTIMER_INTCLR_Pos) /* CMSDK_DUALTIMER INTCLR: INT Clear Mask */ - -#define CMSDK_DUALTIMER_RAWINTSTAT_Pos 0 /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Position */ -#define CMSDK_DUALTIMER_RAWINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_RAWINTSTAT_Pos) /* CMSDK_DUALTIMER RAWINTSTAT: Raw Int Status Mask */ - -#define CMSDK_DUALTIMER_MASKINTSTAT_Pos 0 /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Position */ -#define CMSDK_DUALTIMER_MASKINTSTAT_Msk (0x1ul << CMSDK_DUALTIMER_MASKINTSTAT_Pos) /* CMSDK_DUALTIMER MASKINTSTAT: Mask Int Status Mask */ - -#define CMSDK_DUALTIMER_BGLOAD_Pos 0 /* CMSDK_DUALTIMER BGLOAD: Background Load Position */ -#define CMSDK_DUALTIMER_BGLOAD_Msk (0xFFFFFFFFul << CMSDK_DUALTIMER_BGLOAD_Pos) /* CMSDK_DUALTIMER BGLOAD: Background Load Mask */ - - /*-------------------- General Purpose Input Output (GPIO) -------------------*/ typedef struct { @@ -760,11 +575,6 @@ typedef struct #define CMSDK_UART2 ((CMSDK_UART_TypeDef *) CMSDK_UART2_BASE ) #define CMSDK_UART3 ((CMSDK_UART_TypeDef *) CMSDK_UART3_BASE ) #define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE ) -#define CMSDK_TIMER0 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER0_BASE ) -#define CMSDK_TIMER1 ((CMSDK_TIMER_TypeDef *) CMSDK_TIMER1_BASE ) -#define CMSDK_DUALTIMER ((CMSDK_DUALTIMER_BOTH_TypeDef *) CMSDK_DUALTIMER_BASE ) -#define CMSDK_DUALTIMER1 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_1_BASE ) -#define CMSDK_DUALTIMER2 ((CMSDK_DUALTIMER_SINGLE_TypeDef *) CMSDK_DUALTIMER_2_BASE ) #define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE ) #define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE ) #define CMSDK_GPIO0 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO0_BASE ) diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.c deleted file mode 100644 index 5289ac0c94..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.c +++ /dev/null @@ -1,265 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "cmsis.h" -#include "apb_timer.h" - -/* Timer Private Data */ -typedef struct { - /* Timer Definition */ - CMSDK_TIMER_TypeDef *timerN; - /* Timer IRQn */ - uint32_t timerIRQn; - /* Timer Reload Value */ - uint32_t timerReload; - /* Timer state */ - uint32_t state; -} apb_timer_t; - -/* Timer state definitions */ -#define TIMER_INITIALIZED (1) -#define TIMER_ENABLED (1 << 1) - -/* - * This Timer is written for MBED OS and keeps count - * of the ticks. All the elaboration logic is demanded - * to the upper layers. - */ -#define TIMER_MAX_VALUE 0xFFFFFFFF -#define TIMER_TICKS_US (SystemCoreClock/1000000) - -/* Timers Array */ -static apb_timer_t Timers[NUM_TIMERS]; - -void Timer_Index_Init(uint32_t timer, uint32_t reload, - CMSDK_TIMER_TypeDef *TimerN, uint32_t IRQn) -{ - Timers[timer].timerN = TimerN; - Timers[timer].timerIRQn = IRQn; - Timers[timer].timerReload = reload; - Timers[timer].state = TIMER_INITIALIZED; -} - -/* - * Timer_Initialize(): Initializes an hardware timer - * timer: timer to be Initialized - * time_us: timer reload value in us - 0 to reload to timer max value - * time_us = tick_value / TIMER_TICKS_US - */ -#define TIMER_INIT(index, reload) Timer_Index_Init(index, reload, CMSDK_TIMER##index, TIMER##index##_IRQn) -void Timer_Initialize(uint32_t timer, uint32_t time_us) -{ - uint32_t reload = 0; - - if (timer < NUM_TIMERS) { - if (time_us == 0) { - reload = TIMER_MAX_VALUE; - } else { - reload = (time_us) * TIMER_TICKS_US; - } - switch (timer) { - case 0: - TIMER_INIT(0, reload); - break; - case 1: - TIMER_INIT(1, reload); - break; - default: - break; - } - } -} - -/* - * Timer_Enable(): Enables a hardware timer - * timer: timer to be enabled - */ -void Timer_Enable(uint32_t timer) -{ - /* The timer has to be contained in a valid range */ - if (timer < NUM_TIMERS) { - /* Timer has to be already initialized */ - if (Timers[timer].state == TIMER_INITIALIZED) { - /* Disable Timer */ - (Timers[timer].timerN)->CTRL = 0x0; - /* Reload Value */ - (Timers[timer].timerN)->RELOAD = Timers[timer].timerReload; - /* Enable Interrupt */ - (Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk; - /* Enable Counter */ - (Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; - /* Change timer state */ - Timers[timer].state |= TIMER_ENABLED; - } - } -} - -/* - * Timer_Disable(): Disables a hardware timer - * timer: timer to be disabled - */ -void Timer_Disable(uint32_t timer) -{ - /* The timer has to be contained in a valid range */ - if (timer < NUM_TIMERS) { - /* Timer has to be already initialized and enabled */ - if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) { - /* Disable Timer */ - (Timers[timer].timerN)->CTRL = 0x0; - /* Change timer state */ - Timers[timer].state = TIMER_INITIALIZED; - } - } -} - -/* - * Timer_isEnabled(): verifies if a timer is enabled - * timer: timer to be verified - * @return: 0 disabled - 1 enabled - */ -uint32_t Timer_isEnabled(uint32_t timer) -{ - /* The timer has to be contained in a valid range */ - if (timer < NUM_TIMERS) { - /* Timer has to be already initialized and enabled */ - if (Timers[timer].state == (TIMER_INITIALIZED | TIMER_ENABLED)) { - return 1; - } - } - - return 0; -} - -/* - * Timer_Read(): provides timer VALUE - * timer: timer to be read - * @return: timer VALUE us - */ -uint32_t Timer_Read(uint32_t timer) -{ - uint32_t return_value = 0; - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - return_value = (Timers[timer].timerReload - - (Timers[timer].timerN)->VALUE) / TIMER_TICKS_US; - } - - return return_value; -} - -/* - * Timer_SetInterrupt(): sets timer Interrupt - * timer: timer on which interrupt is set - * time_us: reloading time in us - */ -void Timer_SetInterrupt(uint32_t timer, uint32_t time_us) -{ - uint32_t load_time_us = 0; - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - /* Disable Timer */ - Timer_Disable(timer); - /* Enable Interrupt */ - (Timers[timer].timerN)->CTRL = CMSDK_TIMER_CTRL_IRQEN_Msk; - - /* Check time us condition */ - if (time_us == TIMER_DEFAULT_RELOAD) { - load_time_us = TIMER_MAX_VALUE; - } else { - load_time_us = time_us * TIMER_TICKS_US; - } - - /* Initialize Timer Value */ - Timers[timer].timerReload = load_time_us; - (Timers[timer].timerN)->RELOAD = Timers[timer].timerReload; - (Timers[timer].timerN)->VALUE = Timers[timer].timerReload; - /* Enable Counter */ - (Timers[timer].timerN)->CTRL |= CMSDK_TIMER_CTRL_EN_Msk; - /* Change timer state */ - Timers[timer].state |= TIMER_ENABLED; - } -} - -/* - * Timer_DisableInterrupt(): disables timer interrupt - * timer: timer on which interrupt is disabled - */ -void Timer_DisableInterrupt(uint32_t timer) -{ - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - /* Disable Interrupt */ - (Timers[timer].timerN)->CTRL &= CMSDK_TIMER_CTRL_EN_Msk; - } -} - -/* - * Timer_ClearInterrupt(): clear timer interrupt - * timer: timer on which interrupt needs to be cleared - */ -void Timer_ClearInterrupt(uint32_t timer) -{ - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - /* Clear Interrupt */ - (Timers[timer].timerN)->INTCLEAR = CMSDK_TIMER_INTCLEAR_Msk; - } -} - -/* - * Timer_GetIRQn(): returns IRQn of a Timer - * timer: timer on which IRQn is defined - 0 if it is not defined - */ -uint32_t Timer_GetIRQn(uint32_t timer) -{ - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - return Timers[timer].timerIRQn; - } - return 0; -} - -/* - * Timer_GetTicksUS(): returns the number of Ticks per us - * timer: timer associated with the Ticks per us - * @return: Ticks per us - 0 if the timer is disables - */ -uint32_t Timer_GetTicksUS(uint32_t timer) -{ - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - return TIMER_TICKS_US; - } - return 0; -} - -/* - * Timer_GetReloadValue(): returns the load value of the selected - * timer. - * timer: timer associated with the Ticks per us - * @return: reload value of the selected singletimer - */ -uint32_t Timer_GetReloadValue(uint32_t timer) -{ - /* Verify if the Timer is enabled */ - if (Timer_isEnabled(timer) == 1) { - if (timer == TIMER1) { - return Timers[timer].timerReload / TIMER_TICKS_US; - } else { - return Timers[timer].timerReload / TIMER_TICKS_US; - } - } - return 0; -} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.h deleted file mode 100644 index 715f6983f8..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/apb_timer.h +++ /dev/null @@ -1,111 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This file is derivative of apb_timer.h from BEETLE */ - -#ifndef _APB_TIMER_DRV_H -#define _APB_TIMER_DRV_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Supported Number of Timers */ -#define NUM_TIMERS 2 -#define TIMER0 0 -#define TIMER1 1 - -/* Default reload */ -#define TIMER_DEFAULT_RELOAD 0xFFFFFFFF - -/* - * Timer_Initialize(): Initializes an hardware timer - * timer: timer to be Initialized - * time_us: timer reload value in us - 0 to reload to timer max value - * time_us = tick_value / TIMER_TICK_US - */ -void Timer_Initialize(uint32_t timer, uint32_t time_us); - -/* - * Timer_Enable(): Enables an hardware timer - * timer: timer to be enabled - */ -void Timer_Enable(uint32_t timer); - -/* - * Timer_Disable(): Disables an hardware timer - * timer: timer to be disabled - */ -void Timer_Disable(uint32_t timer); - -/* - * Timer_isEnabled(): verifies if a timer is enabled - * timer: timer to be verified - * @return: 0 disabled - 1 enabled - */ -uint32_t Timer_isEnabled(uint32_t timer); - -/* - * Timer_Read(): provides timer VALUE - * timer: timer to be read - * @return: timer VALUE - */ -uint32_t Timer_Read(uint32_t timer); - -/* - * Timer_SetInterrupt(): sets timer Interrupt - * timer: timer on which interrupt is set - * time_us: reloading time in us - */ -void Timer_SetInterrupt(uint32_t timer, uint32_t time_us); - -/* - * Timer_DisableInterrupt(): disables timer interrupt - * timer: timer on which interrupt is disabled - */ -void Timer_DisableInterrupt(uint32_t timer); - -/* - * Timer_ClearInterrupt(): clear timer interrupt - * timer: timer on which interrupt needs to be cleared - */ -void Timer_ClearInterrupt(uint32_t timer); - -/* - * Timer_GetIRQn(): returns IRQn of a Timer - * timer: timer on which IRQn is defined - 0 if it is not defined - */ -uint32_t Timer_GetIRQn(uint32_t timer); - -/* - * Timer_GetTicksUS(): returns the number of Ticks per us - * timer: timer associated with the Ticks per us - * @return: Ticks per us - 0 if the timer is disables - */ -uint32_t Timer_GetTicksUS(uint32_t timer); - -/* - * Timer_GetReloadValue(): returns the load value of the selected - * timer. - * timer: timer associated with the Ticks per us - * @return: reload value of the selected singletimer - */ -uint32_t Timer_GetReloadValue(uint32_t timer); - -#ifdef __cplusplus -} -#endif -#endif /* _APB_TIMER_DRV_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/cmsis.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/cmsis.h index 4fa14aa6b5..2bd8cd843e 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/cmsis.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/cmsis.h @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2015-2017 ARM Limited + * Copyright (c) 2015-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,5 @@ #include "SMM_MPS2.h" /* NVIC Driver */ #include "cmsis_nvic.h" -/* APB Timer */ -#include "apb_timer.h" #endif /* MBED_CMSIS_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h new file mode 100755 index 0000000000..f82d9e3213 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ARM_LTD_DEVICE_CFG_H__ +#define __ARM_LTD_DEVICE_CFG_H__ + +/** + * \file device_cfg.h + * \brief + * This is the default device configuration file with all peripherals + * defined and configured to be used via the non-secure base address. + * This file is an example of how to define your own configuration file + * with the peripherals required for your application. + */ + +/* CMSDK Timers */ +#define ARM_CMSDK_TIMER0 +#define ARM_CMSDK_TIMER1 + +#endif /* __ARM_LTD_DEVICE_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.c new file mode 100644 index 0000000000..f9ab100759 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_cmsdk_drv.c + * \brief Generic driver for CMSDK APB Timers. + * The timer is a 32-bit down-counter with the following features: + * - optional programmable external clock source + * - programmable interrupt source, triggered if counter reaches 0 + * - automatic reload if counter reaches 0 + */ + +#include "timer_cmsdk_drv.h" + +/** Setter bit manipulation macro */ +#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX))) +/** Clearing bit manipulation macro */ +#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX))) +/** Getter bit manipulation macro */ +#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX)))) + +/** + * \brief Timer register map structure + * + */ +struct timer_cmsdk_reg_map_t { + volatile uint32_t ctrl; /* Offset: 0x000 (R/W) control register */ + volatile uint32_t value; /* Offset: 0x004 (R/W) current value register */ + volatile uint32_t reload; /* Offset: 0x008 (R/W) reload value register */ + union { + volatile uint32_t intstatus; /* Offset: 0x00C (R/ ) interrupt + * status register */ + volatile uint32_t intclear; /* Offset: 0x00C ( /W) interrupt + * clear register */ + }intreg; +}; + +/** + * \brief CTRL register bit definitions + * + */ +enum ctrl_reg_bits_t{ + CTRL_REG_ENUM_ENABLE_INDEX = 0, + CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1, + CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2, + CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3 +}; + +/** + * \brief INTSTATUS/INTCLEAR register bit definitions + * + */ +enum interrupt_reg_bits_t{ + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0 +}; + +void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + + if (dev->data->is_initialized == 0) { + register_map->ctrl = 0; + register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD; + dev->data->is_initialized = 1; + } +} + +bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev) +{ + return dev->data->is_initialized; +} + +void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, + CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX); +} + +void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, + CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX); +} + +void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX); +} + +void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX); +} + +bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return GET_BIT(register_map->intreg.intstatus, + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX); +} + +void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + SET_BIT(register_map->intreg.intclear, + INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX); +} + +uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->value; +} + +void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev, + uint32_t reload) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + register_map->reload = reload; +} + +void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + register_map->value = register_map->reload; +} + +uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->reload; +} + +uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev) +{ + struct timer_cmsdk_reg_map_t* register_map = + (struct timer_cmsdk_reg_map_t*)dev->cfg->base; + return register_map->reload - register_map->value; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.h new file mode 100644 index 0000000000..c84d771877 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/timer_cmsdk/timer_cmsdk_drv.h @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file timer_cmsdk_drv.h + * \brief Generic driver for CMSDK APB Timers. + * The timer is a 32-bit down-counter with the following features: + * - optional programmable external clock source + * - programmable interrupt source, triggered if counter reaches 0 + * - automatic reload if counter reaches 0 + */ + +#ifndef __TIMER_CMSDK_DRV_H__ +#define __TIMER_CMSDK_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Maximum reload value */ +#define TIMER_CMSDK_MAX_RELOAD UINT32_MAX /* max of 32-bit */ +#define TIMER_CMSDK_DEFAULT_RELOAD TIMER_CMSDK_MAX_RELOAD + +/** CMSDK timer device configuration structure */ +struct timer_cmsdk_dev_cfg_t { + const uintptr_t base; /*!< Timer base address */ +}; + +/** CMSDK timer device data structure */ +struct timer_cmsdk_dev_data_t { + bool is_initialized; /*!< Indicates if the timer is initialized */ +}; + +/* CMSDK timer device structure */ +struct timer_cmsdk_dev_t { + const struct timer_cmsdk_dev_cfg_t* const cfg; /*!< Timer configuration */ + struct timer_cmsdk_dev_data_t* const data; /*!< Timer data */ +}; + +/** + * \brief Initializes timer to a known default state, which is: + * - timer disabled + * - timer interrupt disabled + * - clock source set to internal + * - external input disabled + * - reload value maxed out + * Init should be called prior to any other process and + * it's the caller's responsibility to follow proper call order. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer is initialized. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if initialized, false otherwise + */ +bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables external input, which could be used as clock source + * by calling \ref timer_cmsdk_set_clock_to_external. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables external input. + * Make sure if the timer is explicitly wanted to be stopped or set + * the clock source to internal by \ref timer_cmsdk_set_clock_to_internal. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if external input is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the clock source to internal. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the clock source to external. + * Make sure external input is enabled correspondingly + * by \ref timer_cmsdk_enable_external_input. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if clock source is external input. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if external, false if internal + */ +bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables timer operation. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables the given hardware timer. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Enables timer interrupt. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Disables timer interrupt. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Checks if a timer interrupt is enabled. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return true if enabled, false otherwise + */ +bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Gets timer interrupt status + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * * \return true if active, false otherwise + */ +bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Clears timer interrupt + * The interrupt request is held until it is cleared. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Reads timer current value. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Timer value + */ +uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Sets the reload value of the selected timer. + * + * New reload value takes effect when: + * - timer is restarted + * - on timer underflow + * - when timer_cmsdk_reset is called + * + * \note In r1p0 technical reference manual it's incorrectly stated + * writing the reload value automatically sets the current value also. + * r1p1 technical reference manual includes the fix. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * \param[in] reload Timer reload value to set. + * This is the start value of the 32-bit down counter, + * which automatically reloaded if 0 is reached. + */ +void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev, + uint32_t reload); + +/** + * \brief Resets the timer counter to the reload value instantly + * (i.e. without waiting for underflow). + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + */ +void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Gets the reload value of the selected timer. + * This is the start value of the 32-bit down counter, + * which is automatically reloaded if 0 is reached by the counter. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Reload value of the selected timer. + */ +uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev); + +/** + * \brief Reads the number of ticks elapsed in the current cycle. + * + * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t + * + * \return Get elapsed number of ticks since last reload was set. + * Elapsed = (Reload value - Current value) + */ +uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __TIMER_CMSDK_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c new file mode 100755 index 0000000000..566351a261 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2017-2018 ARM Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "platform_devices.h" +#include "SMM_MPS2.h" + +/* ARM CMSDK Timer driver structures */ +#ifdef ARM_CMSDK_TIMER0 +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER0_DEV_CFG = { + .base = CMSDK_TIMER0_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER0_DEV_DATA = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV = {&(CMSDK_TIMER0_DEV_CFG), + &(CMSDK_TIMER0_DEV_DATA)}; +#endif + +#ifdef ARM_CMSDK_TIMER1 +static const struct timer_cmsdk_dev_cfg_t CMSDK_TIMER1_DEV_CFG = { + .base = CMSDK_TIMER1_BASE}; +static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA = { + .is_initialized = 0}; +struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV = {&(CMSDK_TIMER1_DEV_CFG), + &(CMSDK_TIMER1_DEV_DATA)}; +#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h new file mode 100755 index 0000000000..001d848fd2 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2018 ARM Limited + * + * Licensed under the Apache License Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing software + * distributed under the License is distributed on an "AS IS" BASIS + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __ARM_LTD_PLATFORM_DEVICES_H__ +#define __ARM_LTD_PLATFORM_DEVICES_H__ + +#include "device_cfg.h" + +/* ======= Includes generic driver headers ======= */ +#include "timer_cmsdk_drv.h" + +/* ======= Defines peripheral configuration structures ======= */ + +/* ARM CMSDK Timer driver structures */ +#ifdef ARM_CMSDK_TIMER0 +extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV; +#endif + +#ifdef ARM_CMSDK_TIMER1 +extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV; +#endif + +#endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c new file mode 100644 index 0000000000..26d12b83a5 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/lp_ticker.c @@ -0,0 +1,113 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + /** + * Low-power elapsed time measure and interval timer in micro-secundum, + * servicing \ref lp_ticker_api.h, using CMSDK Timer1 \ref CMSDK_TIMER1_DEV. + */ + +#include + +#include "cmsdk_ticker.h" +#include "lp_ticker_api.h" +#include "platform_devices.h" + +/** + * \brief Calculate clocks to us + * + * \param[in] tick Number of clock ticks + * + * \return Number of usec, relative to the timer frequency, + * that a given ammount of ticks equates to. + */ + static uint32_t convert_tick_to_us(uint32_t tick) + { + return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER)); + } + +/** + * \brief Calculate us to clock ticks + * + * \param[in] us Time to convert to clock ticks + * + * \return Number of clock ticks relative to the timer frequency, + * that a given period of usec equates to. + */ + static uint32_t convert_us_to_tick(uint32_t us) + { + return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER)); + } + +static const struct tick_cfg_t cfg = +{ + .timer_driver = &CMSDK_TIMER1_DEV, + .irq_n = TIMER1_IRQn, + .interval_callback = &lp_ticker_irq_handler, + .convert_tick_to_time = &convert_tick_to_us, + .convert_time_to_tick = &convert_us_to_tick +}; + +static struct tick_data_t data = +{ + .is_initialized = false, + .cumulated_time = 0, + .max_interval_time = 0, + .reload_time = 0, + .interval_callback_enabled = false, + .previous_cumulated_time = 0, + .previous_elapsed = 0 +}; + +static struct tick_drv_data_t timer_data = +{ + .cfg = &cfg, + .data = &data +}; + +void lp_ticker_init(void) +{ + cmsdk_ticker_init(&timer_data); +} + +uint32_t lp_ticker_read() +{ + return cmsdk_ticker_read(&timer_data); +} + +void lp_ticker_set_interrupt(timestamp_t timestamp) +{ + cmsdk_ticker_set_interrupt(&timer_data, timestamp); +} + +void lp_ticker_disable_interrupt(void) +{ + cmsdk_ticker_disable_interrupt(&timer_data); +} + +void lp_ticker_clear_interrupt(void) +{ + cmsdk_ticker_clear_interrupt(&timer_data); +} + +void lp_ticker_fire_interrupt(void) +{ + cmsdk_ticker_fire_interrupt(&timer_data); +} + +void TIMER1_IRQHandler(void) +{ + cmsdk_ticker_irq_handler(&timer_data); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c index dffd8d3b2f..3f90820686 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/us_ticker.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2015 ARM Limited + * Copyright (c) 2017-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,125 +14,98 @@ * limitations under the License. */ -/* This file is derivative of us_ticker.c from BEETLE */ +/** + * Elapsed time measure and interval timer in micro-secundum, + * servicing \ref us_ticker_api.h, using CMSDK Timer0 \ref CMSDK_TIMER0_DEV. + */ -#include -#include "cmsis.h" +#include "cmsdk_ticker.h" #include "us_ticker_api.h" -#include "PeripheralNames.h" +#include "platform_devices.h" -#define TIMER_MAX_VALUE 0 - -/* Private data */ -struct us_ticker_drv_data_t { - uint32_t inited; /* us ticker initialized */ - uint32_t overflow_delta; /* us ticker overflow */ - uint32_t overflow_limit; /* us ticker overflow limit */ -}; - -static struct us_ticker_drv_data_t us_ticker_drv_data = { - .inited = 0, - .overflow_delta = 0, - .overflow_limit = 0 -}; - - -void __us_ticker_irq_handler(void) +/** + * \brief Convert clocks to us + * + * \param[in] tick Number of clocks + * + * \return Number of usec, relative to the timer frequency, + * that a given ammount of ticks equates to. + */ +static uint32_t convert_tick_to_us(uint32_t tick) { - Timer_ClearInterrupt(TIMER1); - /* - * For each overflow event adds the timer max represented value to - * the delta. This allows the us_ticker to keep track of the elapsed - * time: - * elapsed_time = (num_overflow * overflow_limit) + current_time - */ - us_ticker_drv_data.overflow_delta += us_ticker_drv_data.overflow_limit; + return (tick / (SystemCoreClock / SEC_TO_USEC_MULTIPLIER)); } +/** + * \brief Convert us to clock ticks + * + * \param[in] us Time to convert to clock ticks + * + * \return Number of clock ticks relative to the timer frequency, + * that a given period of usec equates to. + */ +static uint32_t convert_us_to_tick(uint32_t us) +{ + return (us * (SystemCoreClock / SEC_TO_USEC_MULTIPLIER)); +} + +static const struct tick_cfg_t cfg = +{ + .timer_driver = &CMSDK_TIMER0_DEV, + .irq_n = TIMER0_IRQn, + .interval_callback = &us_ticker_irq_handler, + .convert_tick_to_time = &convert_tick_to_us, + .convert_time_to_tick = &convert_us_to_tick +}; + +static struct tick_data_t data = +{ + .is_initialized = false, + .cumulated_time = 0, + .max_interval_time = 0, + .reload_time = 0, + .interval_callback_enabled = false, + .previous_cumulated_time = 0, + .previous_elapsed = 0 +}; + +static struct tick_drv_data_t timer_data = +{ + .cfg = &cfg, + .data = &data +}; + void us_ticker_init(void) { - uint32_t us_ticker_irqn0 = 0; - uint32_t us_ticker_irqn1 = 0; - - if (us_ticker_drv_data.inited) { - return; - } - - us_ticker_drv_data.inited = 1; - - /* Initialize Timer 0 */ - Timer_Initialize(TIMER0, TIMER_MAX_VALUE); - /* Enable Timer 0 */ - Timer_Enable(TIMER0); - - /* Initialize Timer 1 */ - Timer_Initialize(TIMER1, TIMER_MAX_VALUE); - /* Enable Timer 1 */ - Timer_Enable(TIMER1); - - /* Timer 0 get IRQn */ - us_ticker_irqn0 = Timer_GetIRQn(TIMER0); - NVIC_SetVector((IRQn_Type)us_ticker_irqn0, (uint32_t)us_ticker_irq_handler); - NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn0); - - /* Timer 1 get IRQn */ - us_ticker_irqn1 = Timer_GetIRQn(TIMER1); - NVIC_SetVector((IRQn_Type)us_ticker_irqn1, (uint32_t)__us_ticker_irq_handler); - NVIC_EnableIRQ((IRQn_Type)us_ticker_irqn1); - - /* Timer set interrupt on TIMER1 */ - Timer_SetInterrupt(TIMER1, TIMER_DEFAULT_RELOAD); - - /* - * Set us_ticker Overflow limit. The us_ticker overflow limit is required - * to calculated the return value of the us_ticker read function in us - * on 32bit. - * A 32bit us value cannot be represented directly in the Timer Load - * register if it is greater than (0xFFFFFFFF ticks)/TIMER_DIVIDER_US. - */ - us_ticker_drv_data.overflow_limit = Timer_GetReloadValue(TIMER1); + cmsdk_ticker_init(&timer_data); } uint32_t us_ticker_read() { - uint32_t return_value = 0; - - if (!us_ticker_drv_data.inited) { - us_ticker_init(); - } - - return_value = us_ticker_drv_data.overflow_delta + Timer_Read(TIMER1); - - return return_value; + return cmsdk_ticker_read(&timer_data); } void us_ticker_set_interrupt(timestamp_t timestamp) { - uint32_t delta = 0; - - if (!us_ticker_drv_data.inited) { - us_ticker_init(); - } - - delta = timestamp - us_ticker_read(); - - /* If the event was not in the past enable interrupt */ - Timer_SetInterrupt(TIMER0, delta); - -} - -void us_ticker_fire_interrupt(void) -{ - uint32_t us_ticker_irqn1 = Timer_GetIRQn(TIMER1); - NVIC_SetPendingIRQ((IRQn_Type)us_ticker_irqn1); + cmsdk_ticker_set_interrupt(&timer_data, timestamp); } void us_ticker_disable_interrupt(void) { - Timer_DisableInterrupt(TIMER0); + cmsdk_ticker_disable_interrupt(&timer_data); } void us_ticker_clear_interrupt(void) { - Timer_ClearInterrupt(TIMER0); + cmsdk_ticker_clear_interrupt(&timer_data); +} + +void us_ticker_fire_interrupt(void) +{ + cmsdk_ticker_fire_interrupt(&timer_data); +} + +void TIMER0_IRQHandler(void) +{ + cmsdk_ticker_irq_handler(&timer_data); } diff --git a/targets/targets.json b/targets/targets.json index c6ec92649a..26fde20615 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -2652,7 +2652,7 @@ "supported_toolchains": ["ARM", "GCC_ARM", "IAR"], "extra_labels": ["ARM_SSG", "CM3DS_MPS2"], "macros": ["CMSDK_CM3DS"], - "device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC"], + "device_has": ["ANALOGIN", "ETHERNET", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "SERIAL", "SPI", "RTC", "LOWPOWERTIMER"], "release_versions": ["2", "5"], "copy_method": "mps2", "reset_method": "reboot.txt" From 3abc3faba22f5b99dc9e07f063518e75227c95c3 Mon Sep 17 00:00:00 2001 From: "Galanakis, Minos" Date: Wed, 13 Dec 2017 13:28:54 +0000 Subject: [PATCH 2/4] CM3DS: update GPIO, IRQ and port implementation This commit adds the GPIO drivers. The HAL implementations (gpio_api.c, gpio_irq_api.c, port_api.c) now call these drivers. Legacy definitions have been removed. Serial HAL implementation has been changed to compile at this stage. Change-Id: Ib76a3186358f5029ed350da671132e8aa11194f7 Signed-off-by: Galanakis, Minos --- .../TARGET_CM3DS_MPS2/PeripheralNames.h | 2 +- .../TARGET_CM3DS_MPS2/PinNames.h | 2 +- .../TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h | 168 ------ .../TARGET_CM3DS_MPS2/device/device_cfg.h | 12 + .../device/drivers/arm_gpio_drv.c | 316 +++++++++++ .../device/drivers/arm_gpio_drv.h | 221 ++++++++ .../device/drivers/arm_mps2_io_drv.c | 189 +++++++ .../device/drivers/arm_mps2_io_drv.h | 102 ++++ .../device/platform_devices.c | 62 +++ .../device/platform_devices.h | 26 + .../TARGET_CM3DS_MPS2/gpio_api.c | 333 +++++++----- .../TARGET_CM3DS_MPS2/gpio_irq_api.c | 505 +++++------------- .../TARGET_CM3DS_MPS2/gpio_object.h | 56 -- .../TARGET_CM3DS_MPS2/gpio_objects.h | 56 ++ .../TARGET_CM3DS_MPS2/objects.h | 32 +- .../TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c | 72 ++- .../TARGET_CM3DS_MPS2/port_api.c | 104 ++-- .../TARGET_CM3DS_MPS2/serial_api.c | 8 +- 18 files changed, 1443 insertions(+), 823 deletions(-) create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.c create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.h create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.c create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.h delete mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_object.h create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_objects.h mode change 100644 => 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h index b4b9fc4c7d..c442b5868f 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PinNames.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PinNames.h index 7cbff11502..86013fb904 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PinNames.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PinNames.h @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h index 06c9a930fd..ebbd7b02a8 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h @@ -202,168 +202,6 @@ typedef struct #define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */ #define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */ -/*-------------------- General Purpose Input Output (GPIO) -------------------*/ -typedef struct -{ - __IO uint32_t DATA; /* Offset: 0x000 (R/W) DATA Register */ - __IO uint32_t DATAOUT; /* Offset: 0x004 (R/W) Data Output Latch Register */ - uint32_t RESERVED0[2]; - __IO uint32_t OUTENABLESET; /* Offset: 0x010 (R/W) Output Enable Set Register */ - __IO uint32_t OUTENABLECLR; /* Offset: 0x014 (R/W) Output Enable Clear Register */ - __IO uint32_t ALTFUNCSET; /* Offset: 0x018 (R/W) Alternate Function Set Register */ - __IO uint32_t ALTFUNCCLR; /* Offset: 0x01C (R/W) Alternate Function Clear Register */ - __IO uint32_t INTENSET; /* Offset: 0x020 (R/W) Interrupt Enable Set Register */ - __IO uint32_t INTENCLR; /* Offset: 0x024 (R/W) Interrupt Enable Clear Register */ - __IO uint32_t INTTYPESET; /* Offset: 0x028 (R/W) Interrupt Type Set Register */ - __IO uint32_t INTTYPECLR; /* Offset: 0x02C (R/W) Interrupt Type Clear Register */ - __IO uint32_t INTPOLSET; /* Offset: 0x030 (R/W) Interrupt Polarity Set Register */ - __IO uint32_t INTPOLCLR; /* Offset: 0x034 (R/W) Interrupt Polarity Clear Register */ - union { - __I uint32_t INTSTATUS; /* Offset: 0x038 (R/ ) Interrupt Status Register */ - __O uint32_t INTCLEAR; /* Offset: 0x038 ( /W) Interrupt Clear Register */ - }; - uint32_t RESERVED1[241]; - __IO uint32_t LB_MASKED[256]; /* Offset: 0x400 - 0x7FC Lower byte Masked Access Register (R/W) */ - __IO uint32_t UB_MASKED[256]; /* Offset: 0x800 - 0xBFC Upper byte Masked Access Register (R/W) */ -} CMSDK_GPIO_TypeDef; - -#define CMSDK_GPIO_DATA_Pos 0 /* CMSDK_GPIO DATA: DATA Position */ -#define CMSDK_GPIO_DATA_Msk (0xFFFFul << CMSDK_GPIO_DATA_Pos) /* CMSDK_GPIO DATA: DATA Mask */ - -#define CMSDK_GPIO_DATAOUT_Pos 0 /* CMSDK_GPIO DATAOUT: DATAOUT Position */ -#define CMSDK_GPIO_DATAOUT_Msk (0xFFFFul << CMSDK_GPIO_DATAOUT_Pos) /* CMSDK_GPIO DATAOUT: DATAOUT Mask */ - -#define CMSDK_GPIO_OUTENSET_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */ -#define CMSDK_GPIO_OUTENSET_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */ - -#define CMSDK_GPIO_OUTENCLR_Pos 0 /* CMSDK_GPIO OUTEN: OUTEN Position */ -#define CMSDK_GPIO_OUTENCLR_Msk (0xFFFFul << CMSDK_GPIO_OUTEN_Pos) /* CMSDK_GPIO OUTEN: OUTEN Mask */ - -#define CMSDK_GPIO_ALTFUNCSET_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */ -#define CMSDK_GPIO_ALTFUNCSET_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */ - -#define CMSDK_GPIO_ALTFUNCCLR_Pos 0 /* CMSDK_GPIO ALTFUNC: ALTFUNC Position */ -#define CMSDK_GPIO_ALTFUNCCLR_Msk (0xFFFFul << CMSDK_GPIO_ALTFUNC_Pos) /* CMSDK_GPIO ALTFUNC: ALTFUNC Mask */ - -#define CMSDK_GPIO_INTENSET_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */ -#define CMSDK_GPIO_INTENSET_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */ - -#define CMSDK_GPIO_INTENCLR_Pos 0 /* CMSDK_GPIO INTEN: INTEN Position */ -#define CMSDK_GPIO_INTENCLR_Msk (0xFFFFul << CMSDK_GPIO_INTEN_Pos) /* CMSDK_GPIO INTEN: INTEN Mask */ - -#define CMSDK_GPIO_INTTYPESET_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */ -#define CMSDK_GPIO_INTTYPESET_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */ - -#define CMSDK_GPIO_INTTYPECLR_Pos 0 /* CMSDK_GPIO INTTYPE: INTTYPE Position */ -#define CMSDK_GPIO_INTTYPECLR_Msk (0xFFFFul << CMSDK_GPIO_INTTYPE_Pos) /* CMSDK_GPIO INTTYPE: INTTYPE Mask */ - -#define CMSDK_GPIO_INTPOLSET_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */ -#define CMSDK_GPIO_INTPOLSET_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */ - -#define CMSDK_GPIO_INTPOLCLR_Pos 0 /* CMSDK_GPIO INTPOL: INTPOL Position */ -#define CMSDK_GPIO_INTPOLCLR_Msk (0xFFFFul << CMSDK_GPIO_INTPOL_Pos) /* CMSDK_GPIO INTPOL: INTPOL Mask */ - -#define CMSDK_GPIO_INTSTATUS_Pos 0 /* CMSDK_GPIO INTSTATUS: INTSTATUS Position */ -#define CMSDK_GPIO_INTSTATUS_Msk (0xFFul << CMSDK_GPIO_INTSTATUS_Pos) /* CMSDK_GPIO INTSTATUS: INTSTATUS Mask */ - -#define CMSDK_GPIO_INTCLEAR_Pos 0 /* CMSDK_GPIO INTCLEAR: INTCLEAR Position */ -#define CMSDK_GPIO_INTCLEAR_Msk (0xFFul << CMSDK_GPIO_INTCLEAR_Pos) /* CMSDK_GPIO INTCLEAR: INTCLEAR Mask */ - -#define CMSDK_GPIO_MASKLOWBYTE_Pos 0 /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Position */ -#define CMSDK_GPIO_MASKLOWBYTE_Msk (0x00FFul << CMSDK_GPIO_MASKLOWBYTE_Pos) /* CMSDK_GPIO MASKLOWBYTE: MASKLOWBYTE Mask */ - -#define CMSDK_GPIO_MASKHIGHBYTE_Pos 0 /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Position */ -#define CMSDK_GPIO_MASKHIGHBYTE_Msk (0xFF00ul << CMSDK_GPIO_MASKHIGHBYTE_Pos) /* CMSDK_GPIO MASKHIGHBYTE: MASKHIGHBYTE Mask */ - -/* GPIO Alternate function pin numbers */ -#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX 0 /* Shield 0 UART 2 Rx */ -#define CMSDK_GPIO_ALTFUNC_SH0_UART2_RX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX % 16) -#define CMSDK_GPIO_SH0_UART2_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_RX / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX 4 /* Shield 0 UART 2 Tx */ -#define CMSDK_GPIO_ALTFUNC_SH0_UART2_TX_SET (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX % 16) -#define CMSDK_GPIO_SH0_UART2_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_UART2_TX / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX 26 /* Shield 1 UART 3 Rx */ -#define CMSDK_GPIO_ALTFUNC_SH1_UART3_RX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX % 16) -#define CMSDK_GPIO_SH1_UART3_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_RX / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX 30 /* Shield 1 UART 3 Tx */ -#define CMSDK_GPIO_ALTFUNC_SH1_UART3_TX_SET (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX % 16) -#define CMSDK_GPIO_SH1_UART3_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_UART3_TX / 16) - -#define CMSDK_GPIO_ALTFUNC_UART4_RX 23 /* UART 4 Rx */ -#define CMSDK_GPIO_ALTFUNC_UART4_RX_SET (CMSDK_GPIO_ALTFUNC_UART4_RX % 16) -#define CMSDK_GPIO_UART4_RX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_RX / 16) - -#define CMSDK_GPIO_ALTFUNC_UART4_TX 24 /* UART 4 Tx */ -#define CMSDK_GPIO_ALTFUNC_UART4_TX_SET (CMSDK_GPIO_ALTFUNC_UART4_TX % 16) -#define CMSDK_GPIO_UART4_TX_GPIO_NUM (CMSDK_GPIO_ALTFUNC_UART4_TX / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C 5 /* Shield 0 SCL I2S */ -#define CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C % 16) -#define CMSDK_GPIO_SH0_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCL_I2C / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C 15 /* Shield 0 SDA I2S */ -#define CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C % 16) -#define CMSDK_GPIO_SH0_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SDA_I2C / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C 31 /* Shield 1 SCL I2S */ -#define CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C % 16) -#define CMSDK_GPIO_SH1_SCL_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCL_I2C / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C 41 /* Shield 1 SDA I2S */ -#define CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C_SET (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C % 16) -#define CMSDK_GPIO_SH1_SDA_I2C_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SDA_I2C / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI 11 /* Shield 0 SCK SPI */ -#define CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI % 16) -#define CMSDK_GPIO_SH0_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_SCK_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI 12 /* Shield 0 CS SPI */ -#define CMSDK_GPIO_ALTFUNC_SH0_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI % 16) -#define CMSDK_GPIO_SH0_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_CS_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI 13 /* Shield 0 MOSI SPI */ -#define CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI % 16) -#define CMSDK_GPIO_SH0_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MOSI_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI 14 /* Shield 0 MISO SPI */ -#define CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI % 16) -#define CMSDK_GPIO_SH0_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH0_MISO_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI 44 /* Shield 1 SCK SPI */ -#define CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI % 16) -#define CMSDK_GPIO_SH1_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_SCK_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI 38 /* Shield 1 CS SPI */ -#define CMSDK_GPIO_ALTFUNC_SH1_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI % 16) -#define CMSDK_GPIO_SH1_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_CS_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI 39 /* Shield 1 MOSI SPI */ -#define CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI % 16) -#define CMSDK_GPIO_SH1_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MOSI_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI 40 /* Shield 1 MISO SPI */ -#define CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI % 16) -#define CMSDK_GPIO_SH1_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_SH1_MISO_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI 19 /* Shield ADC SCK SPI */ -#define CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI % 16) -#define CMSDK_GPIO_ADC_SCK_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_SCK_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI 16 /* Shield ADC CS SPI */ -#define CMSDK_GPIO_ALTFUNC_ADC_CS_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI % 16) -#define CMSDK_GPIO_ADC_CS_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_CS_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI 18 /* Shield ADC MOSI SPI */ -#define CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI % 16) -#define CMSDK_GPIO_ADC_MOSI_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MOSI_SPI / 16) - -#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI 17 /* Shield ADC MISO SPI */ -#define CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI_SET (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI % 16) -#define CMSDK_GPIO_ADC_MISO_SPI_GPIO_NUM (CMSDK_GPIO_ALTFUNC_ADC_MISO_SPI / 16) - /*------------- System Control (SYSCON) --------------------------------------*/ typedef struct { @@ -577,12 +415,6 @@ typedef struct #define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE ) #define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE ) #define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE ) -#define CMSDK_GPIO0 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO0_BASE ) -#define CMSDK_GPIO1 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO1_BASE ) -#define CMSDK_GPIO2 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO2_BASE ) -#define CMSDK_GPIO3 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO3_BASE ) -#define CMSDK_GPIO4 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO4_BASE ) -#define CMSDK_GPIO5 ((CMSDK_GPIO_TypeDef *) CMSDK_GPIO5_BASE ) #define CMSDK_SYSCON ((CMSDK_SYSCON_TypeDef *) CMSDK_SYSCTRL_BASE ) #ifdef __cplusplus diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h index f82d9e3213..a51767f35f 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h @@ -30,4 +30,16 @@ #define ARM_CMSDK_TIMER0 #define ARM_CMSDK_TIMER1 +/* ARM GPIO */ +#define ARM_GPIO0 +#define ARM_GPIO1 +#define ARM_GPIO2 +#define ARM_GPIO3 + +/* ARM MPS2 IO FPGAIO */ +#define ARM_MPS2_IO_FPGAIO + +/* ARM MPS2 IO SCC */ +#define ARM_MPS2_IO_SCC + #endif /* __ARM_LTD_DEVICE_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.c new file mode 100644 index 0000000000..e48ec7d7d2 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.c @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arm_gpio_drv.h" + +#include + +/* GPIO state definitions */ +#define ARM_GPIO_INITIALIZED (1 << 0) + +#define MAX_PIN_NBR 16 + +/* GPIO register map structure */ +struct arm_gpio_reg_map_t { + volatile uint32_t data; /* Offset: 0x000 (R/W) Data register */ + volatile uint32_t dataout; /* Offset: 0x004 (R/W) Data output + * latch register */ + volatile uint32_t reserved0[2]; + volatile uint32_t outenableset; /* Offset: 0x010 (R/W) Output enable + * set register */ + volatile uint32_t outenableclr; /* Offset: 0x014 (R/W) Output enable + * clear register */ + volatile uint32_t altfuncset; /* Offset: 0x018 (R/W) Alternate function + * set register */ + volatile uint32_t altfuncclr; /* Offset: 0x01C (R/W) Alternate function + * clear register */ + volatile uint32_t intenset; /* Offset: 0x020 (R/W) Interrupt enable + * set register */ + volatile uint32_t intenclr; /* Offset: 0x024 (R/W) Interrupt enable + * clear register */ + volatile uint32_t inttypeset; /* Offset: 0x028 (R/W) Interrupt type + * set register */ + volatile uint32_t inttypeclr; /* Offset: 0x02C (R/W) Interrupt type + * clear register */ + volatile uint32_t intpolset; /* Offset: 0x030 (R/W) Interrupt polarity + * set register */ + volatile uint32_t intpolclr; /* Offset: 0x034 (R/W) Interrupt polarity + * clear register */ + union { + volatile uint32_t intstatus; /* Offset: 0x038 (R/ ) Interrupt status + * register */ + volatile uint32_t intclear; /* Offset: 0x038 ( /W) Interrupt clear + * register */ + }intreg; + volatile uint32_t reserved1[241]; + volatile uint32_t lb_masked[256]; /* Offset: 0x400 - 0x7FC (R/W) + * Lower byte masked access register */ + volatile uint32_t ub_masked[256]; /* Offset: 0x800 - 0xBFC (R/W) + * Upper byte masked access register */ +}; + +/* + * \brief Configures the pin or port. + * + * \param[in] p_gpio_port GPIO port to configure \ref ahbarm_gpio_reg_map_t + * \param[in] mask Pin bit mask. + * \param[in] flags Pin flags. + */ +static void set_port_config(struct arm_gpio_reg_map_t* p_gpio_port, + uint32_t mask, + uint32_t flags) +{ + if(flags & ARM_GPIO_PIN_DISABLE) { + p_gpio_port->altfuncset = mask; + return; + } + + if(flags & ARM_GPIO_OUTPUT) { + p_gpio_port->outenableset = mask; + } else if(flags & ARM_GPIO_INPUT) { + p_gpio_port->outenableclr = mask; + } + + /* Sets interrupt configuration */ + if(flags & ARM_GPIO_IRQ) { + /* Interrupt type: EDGE = 1 - LEVEL = 0 */ + if(flags & ARM_GPIO_IRQ_EDGE) { + p_gpio_port->inttypeset = mask; + } else if(flags & ARM_GPIO_IRQ_LEVEL) { + p_gpio_port->inttypeclr = mask; + } + + /* Interrupt polarity */ + if(flags & ARM_GPIO_IRQ_ACTIVE_LOW) { + p_gpio_port->intpolclr = mask; + } else if(flags & ARM_GPIO_IRQ_ACTIVE_HIGH) { + p_gpio_port->intpolset = mask; + } + } + + if(flags & ARM_GPIO_PIN_ENABLE) { + p_gpio_port->altfuncclr = mask; + } +} + +void arm_gpio_init(struct arm_gpio_dev_t* dev) +{ + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(dev->data->state != ARM_GPIO_INITIALIZED) { + /* Disables all pins in this port */ + set_port_config(p_gpio_port, DEFAULT_PORT_MASK, ARM_GPIO_PIN_DISABLE); + + dev->data->port_mask = DEFAULT_PORT_MASK; + dev->data->state = ARM_GPIO_INITIALIZED; + } +} + +enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t flags) +{ + uint32_t pin_mask; + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(dev->data->state != ARM_GPIO_INITIALIZED) { + return ARM_GPIO_ERR_PORT_NOT_INIT; + } + + if(pin_num >= MAX_PIN_NBR) { + return ARM_GPIO_ERR_INVALID_ARG; + } + + switch(access) { + case ARM_GPIO_ACCESS_PIN: + pin_mask = (1UL << pin_num); + set_port_config(p_gpio_port, pin_mask, flags); + break; + case ARM_GPIO_ACCESS_PORT: + set_port_config(p_gpio_port, dev->data->port_mask, flags); + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ + } + + return ARM_GPIO_ERR_NONE; +} + +enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t value) +{ + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(pin_num >= MAX_PIN_NBR) { + return ARM_GPIO_ERR_INVALID_ARG; + } + + /* As ARM is a read-modify-write architecture, before set a + * value on a GPIO register it is required to disable the + * interrupts to prevent problems in a multitasking + * environment */ + switch(access) { + case ARM_GPIO_ACCESS_PIN: + if(value) { + /* Sets the pin */ + p_gpio_port->dataout |= (1UL << pin_num); + } else { + /* Clears the pin */ + p_gpio_port->dataout &= ~(1UL << pin_num); + } + break; + case ARM_GPIO_ACCESS_PORT: + if(value) { + /* Sets masked pins */ + p_gpio_port->dataout |= dev->data->port_mask; + } else { + /* Clears masked pins */ + p_gpio_port->dataout &= ~(dev->data->port_mask); + } + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch. */ + } + + return ARM_GPIO_ERR_NONE; +} + +int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access, + uint8_t pin_num) +{ + uint32_t value; + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + value = p_gpio_port->data; + + if(access == ARM_GPIO_ACCESS_PIN) { + if(pin_num >= MAX_PIN_NBR) { + return -1; + } + value = ((value >> pin_num) & 1UL); + } else { + value &= dev->data->port_mask; + } + + return (int32_t)value; +} + +enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + enum arm_gpio_irq_status_t status) +{ + uint32_t mask = 0; + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(dev->data->state != ARM_GPIO_INITIALIZED) { + return ARM_GPIO_ERR_PORT_NOT_INIT; + } + + if(pin_num >= MAX_PIN_NBR) { + return ARM_GPIO_ERR_INVALID_ARG; + } + + switch(access) { + case ARM_GPIO_ACCESS_PIN: + mask = (1UL << pin_num); + break; + case ARM_GPIO_ACCESS_PORT: + mask = dev->data->port_mask; + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ + } + + if(status == ARM_GPIO_IRQ_ENABLE) { + p_gpio_port->intenset = mask; + } else { + p_gpio_port->intenclr = mask; + } + + return ARM_GPIO_ERR_NONE; +} + +enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t* status) +{ + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(dev->data->state != ARM_GPIO_INITIALIZED) { + return ARM_GPIO_ERR_PORT_NOT_INIT; + } + + if(pin_num >= MAX_PIN_NBR) { + return ARM_GPIO_ERR_INVALID_ARG; + } + + *status = p_gpio_port->intreg.intstatus; + + if(access == ARM_GPIO_ACCESS_PIN) { + *status = ((*status >> pin_num) & 1UL); + } else { + *status &= dev->data->port_mask; + } + + return ARM_GPIO_ERR_NONE; +} + +enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev, + uint8_t pin_num) +{ + struct arm_gpio_reg_map_t* p_gpio_port = + (struct arm_gpio_reg_map_t*)dev->cfg->base; + + if(dev->data->state != ARM_GPIO_INITIALIZED) { + return ARM_GPIO_ERR_PORT_NOT_INIT; + } + + if(pin_num >= MAX_PIN_NBR) { + return ARM_GPIO_ERR_INVALID_ARG; + } + + p_gpio_port->intreg.intstatus = (1UL << pin_num); + + return ARM_GPIO_ERR_NONE; +} + +void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask) +{ + dev->data->port_mask = (port_mask & DEFAULT_PORT_MASK); +} + +uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev) +{ + if(dev->data->state != ARM_GPIO_INITIALIZED) { + return 0; + } + + return (dev->data->port_mask & DEFAULT_PORT_MASK); +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.h new file mode 100644 index 0000000000..713d8db9f2 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_gpio_drv.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file arm_gpio_drv.h + * \brief Generic driver for ARM GPIO. + */ + +#ifndef __ARM_GPIO_DRV_H__ +#define __ARM_GPIO_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DEFAULT_PORT_MASK 0xFFFF /* Default port mask */ + +/* GPIO flags */ +#define ARM_GPIO_PIN_DISABLE (1 << 0) +#define ARM_GPIO_PIN_ENABLE (1 << 1) +#define ARM_GPIO_OUTPUT (1 << 2) +#define ARM_GPIO_INPUT (1 << 3) +#define ARM_GPIO_IRQ (1 << 4) +#define ARM_GPIO_IRQ_EDGE (1 << 5) +#define ARM_GPIO_IRQ_LEVEL (1 << 6) +#define ARM_GPIO_IRQ_ACTIVE_LOW (1 << 7) +#define ARM_GPIO_IRQ_ACTIVE_HIGH (1 << 8) + +/* ARM GPIO enumeration types */ +enum arm_gpio_access_t { + ARM_GPIO_ACCESS_PIN = 0, /*!< Pin access to GPIO */ + ARM_GPIO_ACCESS_PORT /*!< Port access to GPIO */ +}; + +enum arm_gpio_irq_status_t { + ARM_GPIO_IRQ_DISABLE = 0, /*!< Disable interruptions */ + ARM_GPIO_IRQ_ENABLE /*!< Enable interruptions */ +}; + +enum arm_gpio_error_t { + ARM_GPIO_ERR_NONE = 0, /*!< No error */ + ARM_GPIO_ERR_INVALID_ARG, /*!< Error invalid input argument */ + ARM_GPIO_ERR_PORT_NOT_INIT /*!< Error GPIO port not initialized */ +}; + +/* ARM GPIO device configuration structure */ +struct arm_gpio_dev_cfg_t { + const uint32_t base; /*!< GPIO base address */ +}; + +/* ARM GPIO device data structure */ +struct arm_gpio_dev_data_t { + uint32_t state; /*!< Indicates if the gpio driver + is initialized and enabled */ + uint32_t port_mask; /*!< Port mask used for any port access */ +}; + +/* ARM GPIO device structure */ +struct arm_gpio_dev_t { + const struct arm_gpio_dev_cfg_t* const cfg; /*!< GPIO configuration */ + struct arm_gpio_dev_data_t* const data; /*!< GPIO data */ +}; + +/* ARM GPIO pin structure */ +struct arm_gpio_pin_t { + uint32_t number; /*!< Pin number */ + enum arm_gpio_access_t access_type; /*!< Type of access in the + GPIO block */ +}; + +/** + * \brief Initializes GPIO port. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void arm_gpio_init(struct arm_gpio_dev_t* dev); + +/** + * \brief Configurates pin or port. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] access Access type \ref arm_gpio_access_t + * \param[in] pin_num Pin number. + * \param[in] flags Pin flags \ref arm_gpio_flags_t + * + * \return Returns error code as specified in \ref arm_gpio_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_gpio_error_t arm_gpio_config(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t flags); + +/** + * \brief Writes to output pin or port. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] access Access type \ref arm_gpio_access_t + * \param[in] pin_num Pin number. + * \param[in] value Value(s) to set. + * + * \return Returns error code as specified in \ref arm_gpio_error_t + * + * \note This function doesn't check if dev is NULL. + * \note As ARM is a read-modify-write architecture, before writing a + * value on a GPIO pin it is required to disable the + * interrupts to prevent problems in a multitasking + * environment. + */ +enum arm_gpio_error_t arm_gpio_write(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t value); + +/** + * \brief Reads the pin or port status. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] access Access type \ref arm_gpio_access_t + * \param[in] pin_num Pin number. + * \param[in] value Value of input pin(s). + * + * \return Returns bit value for Pin access or port value for port access. + * Negative value for error. + * \note This function doesn't check if dev is NULL. + */ +int32_t arm_gpio_read(struct arm_gpio_dev_t* dev, enum arm_gpio_access_t access, + uint8_t pin_num); + +/** + * \brief Sets interrupt status for the given pin or port. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] access Access type \ref arm_gpio_access_t + * \param[in] pin_num Pin number. + * \param[in] status Interrupt status \ref arm_gpio_irq_status + * + * \return Returns error code as specified in \ref arm_gpio_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_gpio_error_t arm_gpio_set_interrupt(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + enum arm_gpio_irq_status_t status); + +/** + * \brief Gets interrupt status for the given pin or port. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] access Access type \ref arm_gpio_access_t + * \param[in] pin_num Pin number. + * \param[out] status Interrupt status values. If the access is by pin, then + * the status will be 0 or 1. + * + * \return Returns error code as specified in \ref arm_gpio_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_gpio_error_t arm_gpio_get_irq_status(struct arm_gpio_dev_t* dev, + enum arm_gpio_access_t access, + uint8_t pin_num, + uint32_t* status); + +/** + * \brief Clears gpio interrupt. + * + * \param[in] dev GPIO port to initalize \ref arm_gpio_dev_t + * \param[in] pin_num Pin number. + * + * \return Returns error code as specified in \ref arm_gpio_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_gpio_error_t arm_gpio_clear_interrupt(struct arm_gpio_dev_t* dev, + uint8_t pin_num); + +/** + * \brief Sets gpio mask for port access. + * + * \param[in] dev GPIO port \ref arm_gpio_dev_t + * \param[in] port_mask New port mask to set, only the 16 LSb are taken into + * account + * + * \note This function doesn't check if dev is NULL. + */ +void arm_gpio_set_port_mask(struct arm_gpio_dev_t* dev, uint32_t port_mask); + +/** + * \brief Gets gpio mask for port access. + * + * \param[in] dev GPIO port \ref arm_gpio_dev_t + * + * \return Returns the current port mask + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_gpio_get_port_mask(struct arm_gpio_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __ARM_GPIO_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.c new file mode 100644 index 0000000000..0885f2a6d9 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arm_mps2_io_drv.h" + +/* There is at most 8 LEDs and switches on MPS2 SCC and 2 on FPGA IO */ +#define MAX_PIN_NBR_SCC 8 +#define MAX_PIN_NBR_FPGAIO 2 + +/* Mask to 1 the first X bits */ +#define MASK(X) ((1 << (X)) - 1) + +/* MPS2 IO register map structure */ +struct arm_mps2_io_reg_map_t { + union { + volatile uint32_t scc_leds; /* Offset: 0x000 (R/W) Controls the MCC + * user LEDs + * [31:8] : Reserved + * [7:0] : MCC LEDs */ + volatile uint32_t fpgaio_leds; /* Offset: 0x000 (R/W) LED connections + * [31:2] : Reserved + * [1:0] : FPGAIO LEDs */ + } led_reg; + volatile uint32_t reserved[1]; + union { + volatile uint32_t scc_switches; /* Offset: 0x008 (R/ ) Denotes the + * state of the MCC + * user switches + * [31:8] : Reserved + * [7:0] : State of the MCC + * switches */ + volatile uint32_t fpgaio_buttons;/* Offset: 0x008 (R/ ) Buttons + * [31:2] : Reserved + * [1:0] : Buttons */ + } button_reg; +}; + +void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num, + uint32_t value) +{ + struct arm_mps2_io_reg_map_t* p_mps2_io_port = + (struct arm_mps2_io_reg_map_t*)dev->cfg->base; + /* Mask of involved bits */ + uint32_t write_mask = 0; + + switch (dev->cfg->type) { + case ARM_MPS2_IO_TYPE_SCC: + if (pin_num >= MAX_PIN_NBR_SCC) { + return; + } + + switch (access) { + case ARM_MPS2_IO_ACCESS_PIN: + write_mask = (1UL << pin_num); + break; + case ARM_MPS2_IO_ACCESS_PORT: + write_mask = MASK(MAX_PIN_NBR_SCC); + break; + /* + * default: explicitely not used to force to cover all enumeration + * cases + */ + } + + if (value) { + p_mps2_io_port->led_reg.scc_leds |= write_mask; + } else { + p_mps2_io_port->led_reg.scc_leds &= ~write_mask; + } + + break; + case ARM_MPS2_IO_TYPE_FPGAIO: + if (pin_num >= MAX_PIN_NBR_FPGAIO) { + return; + } + + switch (access) { + case ARM_MPS2_IO_ACCESS_PIN: + write_mask = (1UL << pin_num); + break; + case ARM_MPS2_IO_ACCESS_PORT: + write_mask = MASK(MAX_PIN_NBR_FPGAIO); + break; + /* + * default: explicitely not used to force to cover all enumeration + * cases + */ + } + + if (value) { + p_mps2_io_port->led_reg.fpgaio_leds |= write_mask; + } else { + p_mps2_io_port->led_reg.fpgaio_leds &= ~write_mask; + } + + break; + /* default: explicitely not used to force to cover all enumeration cases */ + } +} + +uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num) +{ + struct arm_mps2_io_reg_map_t* p_mps2_io_port = + (struct arm_mps2_io_reg_map_t*)dev->cfg->base; + uint32_t value = 0; + + switch (dev->cfg->type) { + case ARM_MPS2_IO_TYPE_SCC: + if (pin_num >= MAX_PIN_NBR_SCC) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps2_io_port->button_reg.scc_switches & MASK(MAX_PIN_NBR_SCC); + + break; + case ARM_MPS2_IO_TYPE_FPGAIO: + if (pin_num >= MAX_PIN_NBR_FPGAIO) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps2_io_port->button_reg.fpgaio_buttons & + MASK(MAX_PIN_NBR_FPGAIO); + + break; + /* default: explicitely not used to force to cover all enumeration cases */ + } + + if (access == ARM_MPS2_IO_ACCESS_PIN) { + value = ((value >> pin_num) & 1UL); + } + + return value; +} + +uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num) +{ + struct arm_mps2_io_reg_map_t* p_mps2_io_port = + (struct arm_mps2_io_reg_map_t*)dev->cfg->base; + uint32_t value = 0; + + switch (dev->cfg->type) { + case ARM_MPS2_IO_TYPE_SCC: + if (pin_num >= MAX_PIN_NBR_SCC) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps2_io_port->led_reg.scc_leds & MASK(MAX_PIN_NBR_SCC); + + break; + case ARM_MPS2_IO_TYPE_FPGAIO: + if (pin_num >= MAX_PIN_NBR_FPGAIO) { + return 0; + } + + /* Only read significant bits from this register */ + value = p_mps2_io_port->led_reg.fpgaio_leds & MASK(MAX_PIN_NBR_FPGAIO); + + break; + /* default: explicitely not used to force to cover all enumeration cases */ + } + + if (access == ARM_MPS2_IO_ACCESS_PIN) { + value = ((value >> pin_num) & 1UL); + } + + return value; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.h new file mode 100644 index 0000000000..6657114fb4 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_mps2_io_drv.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file arm_mps2_io_drv.h + * \brief Generic driver for ARM MPS2 IO. + */ + +#ifndef __ARM_MPS2_IO_DRV_H__ +#define __ARM_MPS2_IO_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ARM MPS2 IO enumeration types */ +enum arm_mps2_io_access_t { + ARM_MPS2_IO_ACCESS_PIN = 0, /*!< Pin access to MPS2 IO */ + ARM_MPS2_IO_ACCESS_PORT /*!< Port access to MPS2 IO */ +}; + +enum arm_mps2_io_type_t { + ARM_MPS2_IO_TYPE_SCC = 0, /*!< Use the SCC IO device */ + ARM_MPS2_IO_TYPE_FPGAIO /*!< Use the FPGA IO device */ +}; + +/* ARM MPS2 IO device configuration structure */ +struct arm_mps2_io_dev_cfg_t { + const uint32_t base; /*!< MPS2 IO base address */ + const enum arm_mps2_io_type_t type; /*!< SCC or FPGAIO */ +}; + +/* ARM MPS2 IO device structure */ +struct arm_mps2_io_dev_t { + const struct arm_mps2_io_dev_cfg_t* const cfg; /*!< MPS2 IO configuration */ +}; + +/** + * \brief Writes to output LEDs. + * + * \param[in] dev MPS2 IO device where to write \ref arm_mps2_io_dev_t + * \param[in] access Access type \ref arm_mps2_io_access_t + * \param[in] pin_num Pin number. + * \param[in] value Value(s) to set. + * + * \note This function doesn't check if dev is NULL. + */ +void arm_mps2_io_write_leds(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num, + uint32_t value); + +/** + * \brief Reads the buttons status. + * + * \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t + * \param[in] access Access type \ref arm_mps2_io_access_t + * \param[in] pin_num Pin number. + * + * \return Returns bit value for Pin access or port value for port access. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_mps2_io_read_buttons(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num); + +/** + * \brief Reads the LED status. + * + * \param[in] dev MPS2 IO device where to read \ref arm_mps2_io_dev_t + * \param[in] access Access type \ref arm_mps2_io_access_t + * \param[in] pin_num Pin number. + * + * \return Returns bit value for Pin access or port value for port access. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_mps2_io_read_leds(struct arm_mps2_io_dev_t* dev, + enum arm_mps2_io_access_t access, + uint8_t pin_num); + +#ifdef __cplusplus +} +#endif + +#endif /* __ARM_MPS2_IO_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c index 566351a261..a39f7c94db 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c @@ -35,3 +35,65 @@ static struct timer_cmsdk_dev_data_t CMSDK_TIMER1_DEV_DATA = { struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV = {&(CMSDK_TIMER1_DEV_CFG), &(CMSDK_TIMER1_DEV_DATA)}; #endif + +/* ARM GPIO driver structures */ +#ifdef ARM_GPIO0 +static const struct arm_gpio_dev_cfg_t ARM_GPIO0_DEV_CFG = { + .base = CMSDK_GPIO0_BASE}; +static struct arm_gpio_dev_data_t ARM_GPIO0_DEV_DATA = { + .state = 0, + .port_mask = DEFAULT_PORT_MASK}; +struct arm_gpio_dev_t ARM_GPIO0_DEV = {&(ARM_GPIO0_DEV_CFG), + &(ARM_GPIO0_DEV_DATA)}; +#endif /* ARM_GPIO0 */ + +#ifdef ARM_GPIO1 +static const struct arm_gpio_dev_cfg_t ARM_GPIO1_DEV_CFG = { + .base = CMSDK_GPIO1_BASE}; +static struct arm_gpio_dev_data_t ARM_GPIO1_DEV_DATA = { + .state = 0, + .port_mask = DEFAULT_PORT_MASK}; +struct arm_gpio_dev_t ARM_GPIO1_DEV = {&(ARM_GPIO1_DEV_CFG), + &(ARM_GPIO1_DEV_DATA)}; +#endif /* ARM_GPIO1 */ + +#ifdef ARM_GPIO2 +static const struct arm_gpio_dev_cfg_t ARM_GPIO2_DEV_CFG = { + .base = CMSDK_GPIO2_BASE}; +static struct arm_gpio_dev_data_t ARM_GPIO2_DEV_DATA = { + .state = 0, + .port_mask = DEFAULT_PORT_MASK}; +struct arm_gpio_dev_t ARM_GPIO2_DEV = {&(ARM_GPIO2_DEV_CFG), + &(ARM_GPIO2_DEV_DATA)}; +#endif /* ARM_GPIO2 */ + +#ifdef ARM_GPIO3 +static const struct arm_gpio_dev_cfg_t ARM_GPIO3_DEV_CFG = { + .base = CMSDK_GPIO3_BASE}; +static struct arm_gpio_dev_data_t ARM_GPIO3_DEV_DATA = { + .state = 0, + .port_mask = DEFAULT_PORT_MASK}; +struct arm_gpio_dev_t ARM_GPIO3_DEV = {&(ARM_GPIO3_DEV_CFG), + &(ARM_GPIO3_DEV_DATA)}; +#endif /* ARM_GPIO3 */ + +/* ARM MPS2 IO FPGAIO driver structures */ +#ifdef ARM_MPS2_IO_FPGAIO +static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_FPGAIO_DEV_CFG = { + .base = MPS2_FPGAIO_BASE, + .type = ARM_MPS2_IO_TYPE_FPGAIO}; +struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV = + {&(ARM_MPS2_IO_FPGAIO_DEV_CFG)}; +#endif /* ARM_MPS2_IO_FPGAIO */ + +/* ARM MPS2 IO SCC driver structures */ +#ifdef ARM_MPS2_IO_SCC +static const struct arm_mps2_io_dev_cfg_t ARM_MPS2_IO_SCC_DEV_CFG = { + /* + * MPS2 IO SCC and FPGAIO registers have similar structure + * with 4 byte offset addresses. + */ + .base = MPS2_SCC_BASE + 4, + .type = ARM_MPS2_IO_TYPE_SCC}; +struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV = {&(ARM_MPS2_IO_SCC_DEV_CFG)}; +#endif /* ARM_MPS2_IO_SCC */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h index 001d848fd2..c508cb3a8a 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h @@ -21,6 +21,8 @@ /* ======= Includes generic driver headers ======= */ #include "timer_cmsdk_drv.h" +#include "arm_gpio_drv.h" +#include "arm_mps2_io_drv.h" /* ======= Defines peripheral configuration structures ======= */ @@ -33,4 +35,28 @@ extern struct timer_cmsdk_dev_t CMSDK_TIMER0_DEV; extern struct timer_cmsdk_dev_t CMSDK_TIMER1_DEV; #endif +/* ARM GPIO driver structures */ +#ifdef ARM_GPIO0 +extern struct arm_gpio_dev_t ARM_GPIO0_DEV; +#endif +#ifdef ARM_GPIO1 +extern struct arm_gpio_dev_t ARM_GPIO1_DEV; +#endif +#ifdef ARM_GPIO2 +extern struct arm_gpio_dev_t ARM_GPIO2_DEV; +#endif +#ifdef ARM_GPIO3 +extern struct arm_gpio_dev_t ARM_GPIO3_DEV; +#endif + +/* ARM MPS2 IO FPGAIO driver structures */ +#ifdef ARM_MPS2_IO_FPGAIO +extern struct arm_mps2_io_dev_t ARM_MPS2_IO_FPGAIO_DEV; +#endif + +/* ARM MPS2 IO SCC driver structures */ +#ifdef ARM_MPS2_IO_SCC +extern struct arm_mps2_io_dev_t ARM_MPS2_IO_SCC_DEV; +#endif + #endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_api.c index 11e4d44e1d..914843cdee 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_api.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,177 +17,236 @@ #include #include "gpio_api.h" #include "pinmap.h" +#include "objects.h" +#include "mbed_error.h" -#define GPIO_PIN_POS_MASK 0x0F /* pin % 16 */ -#define RESERVED_MISC_PIN 7 +enum io_type { + GPIO_DEVICE, + MPS2_IO_DEVICE, + DEVICE_UNKNOWN +}; -/* \brief Gets the FPGA MISC (Miscellaneous control) bit position for the given - * pin name - * - * FPGA MISC bit mapping: - * [31:7] Reserved - * [6] CLCD_BL_CTRL - * [5] CLCD_RD - * [4] CLCD_RS - * [3] CLCD_RESET - * [2] Reserved - * [1] SPI_nSS - * [0] CLCD_CS - * - * \param[in] pin MISC pin name - * - * \return FPGA MISC bit position - */ -static uint8_t get_fpga_misc_pin_pos(PinName pin) +/* Tell if the gpio is from GPIO device or MPS2 IO */ +static enum io_type io_type(gpio_t *obj) { - uint8_t pin_position = RESERVED_MISC_PIN; - - if (pin == SPI_SCLK) { - pin_position = 0; - } else if (pin == CLCD_SSEL) { - pin_position = 1; - } else if (pin == CLCD_RESET) { - pin_position = 3; - } else if (pin == CLCD_RS) { - pin_position = 4; - } else if (pin == CLCD_RD) { - pin_position = 5; - } else if (pin == CLCD_BL_CTRL){ - pin_position = 6; + if (obj->gpio_dev != NULL && obj->mps2_io_dev == NULL) { + return GPIO_DEVICE; } - - return pin_position; + if (obj->gpio_dev == NULL && obj->mps2_io_dev != NULL) { + return MPS2_IO_DEVICE; + } + return DEVICE_UNKNOWN; } +/* Return the correct mask of the given PIN */ uint32_t gpio_set(PinName pin) { - uint8_t pin_position; + pin_function(pin, (int)GPIO_FUNC); - if (pin >=EXP0 && pin <= EXP51) { - /* Set pin functinality as GPIO. pin_function asserts if pin == NC */ - pin_function(pin, GPIO_FUNC); + if (pin >= EXP0 && pin <= EXP51) { + /* GPIO pins */ + return (1 << GPIO_PIN_NUMBER(pin)); + } else if (pin == USERLED1 || pin == USERLED2) { + /* User LEDs */ + return (1 << (pin - USERLED1)); + } else if (pin == USERSW1 || pin == USERSW2) { + /* User Push buttons */ + return (1 << (pin - USERSW1)); + } else if (pin >= LED1 && pin <= LED8) { + /* MCC LEDs */ + return (1 << (pin - LED1)); + } else if (pin >= SW1 && pin <= SW8) { + /* MCC Switches */ + return (1 << (pin - SW1)); } else { - /* Check if pin is a MISC pin */ - pin_position = get_fpga_misc_pin_pos(pin); - if (pin_position != RESERVED_MISC_PIN) { - return (1 << pin_position); - } + return 0; } - - /* Return pin mask */ - return (1 << (pin & 0xFF)); } void gpio_init(gpio_t *obj, PinName pin) { - uint8_t pin_position; + struct arm_gpio_dev_t *gpio_dev; - if (pin == NC) { - return; - } - - obj->pin = pin; - obj->pin_number = pin; - - if (pin <= EXP15) { - obj->reg_data = &CMSDK_GPIO0->DATAOUT; - obj->reg_in = &CMSDK_GPIO0->DATA; - obj->reg_dir = &CMSDK_GPIO0->OUTENABLESET; - obj->reg_dirclr = &CMSDK_GPIO0->OUTENABLECLR; - /* Set pin function as a GPIO */ - pin_function(pin, GPIO_FUNC); - pin_position = pin; - } else if (pin >= EXP16 && pin <= EXP31) { - obj->reg_data = &CMSDK_GPIO1->DATAOUT; - obj->reg_in = &CMSDK_GPIO1->DATA; - obj->reg_dir = &CMSDK_GPIO1->OUTENABLESET; - obj->reg_dirclr = &CMSDK_GPIO1->OUTENABLECLR; - /* Set pin function as a GPIO */ - pin_function(pin, GPIO_FUNC); - pin_position = (pin & GPIO_PIN_POS_MASK); - } else if (pin >= EXP32 && pin <= EXP47) { - obj->reg_data = &CMSDK_GPIO2->DATAOUT; - obj->reg_in = &CMSDK_GPIO2->DATA; - obj->reg_dir = &CMSDK_GPIO2->OUTENABLESET; - obj->reg_dirclr = &CMSDK_GPIO2->OUTENABLECLR; - /* Set pin function as a GPIO */ - pin_function(pin, GPIO_FUNC); - pin_position = (pin & GPIO_PIN_POS_MASK); - } else if (pin >= EXP48 && pin <= EXP51) { - obj->reg_data = &CMSDK_GPIO3->DATAOUT; - obj->reg_in = &CMSDK_GPIO3->DATA; - obj->reg_dir = &CMSDK_GPIO3->OUTENABLESET; - obj->reg_dirclr = &CMSDK_GPIO3->OUTENABLECLR; - /* Set pin function as a GPIO */ - pin_function(pin, GPIO_FUNC); - pin_position = (pin & GPIO_PIN_POS_MASK); - } else if (pin == 100 || pin == 101) { - /* User LEDs */ - pin_position = (pin - 100); - obj->reg_data = &MPS2_FPGAIO->LED; - obj->reg_in = &MPS2_FPGAIO->LED; - obj->reg_dir = NULL; - obj->reg_dirclr = NULL; - } else if (pin == 110 || pin == 111) { - /* User buttons */ - pin_position = (pin - 110); - obj->reg_data = &MPS2_FPGAIO->BUTTON; - obj->reg_in = &MPS2_FPGAIO->BUTTON; - obj->reg_dir = NULL; - obj->reg_dirclr = NULL; - } else if (pin >= 200 && pin <= 207) { - /* MCC LEDs */ - pin_position = (pin - 200); - obj->reg_data = &MPS2_SCC->LEDS; - obj->reg_in = &MPS2_SCC->LEDS; - obj->reg_dir = NULL; - obj->reg_dirclr = NULL; - } else if (pin >= 210 && pin <= 217) { - /* MCC switches */ - pin_position = (pin - 210); - obj->reg_in = &MPS2_SCC->SWITCHES; - obj->reg_data = NULL; - obj->reg_dir = NULL; - obj->reg_dirclr = NULL; - } else { - /* Check if pin is a MISC pin */ - pin_position = get_fpga_misc_pin_pos(pin); - if (pin_position != RESERVED_MISC_PIN) { - obj->reg_data = &MPS2_FPGAIO->MISC; - } else { - pin_position = 0; + if (pin >= EXP0 && pin <= EXP51) { + /* GPIO pins */ + switch (GPIO_DEV_NUMBER(pin)) { +#ifdef ARM_GPIO0 + case GPIO0_NUMBER: + gpio_dev = &ARM_GPIO0_DEV; + break; +#endif /* ARM_GPIO0 */ +#ifdef ARM_GPIO1 + case GPIO1_NUMBER: + gpio_dev = &ARM_GPIO1_DEV; + break; +#endif /* ARM_GPIO1 */ +#ifdef ARM_GPIO2 + case GPIO2_NUMBER: + gpio_dev = &ARM_GPIO2_DEV; + break; +#endif /* ARM_GPIO2 */ +#ifdef ARM_GPIO3 + case GPIO3_NUMBER: + gpio_dev = &ARM_GPIO3_DEV; + break; +#endif /* ARM_GPIO3 */ + default: + error("GPIO %d, associated with expansion pin %d, is disabled", + GPIO_DEV_NUMBER(pin), pin); + return; } + + arm_gpio_init(gpio_dev); + + obj->gpio_dev = gpio_dev; + obj->mps2_io_dev = NULL; + obj->pin_number = GPIO_PIN_NUMBER(pin); + /* GPIO is input by default */ + obj->direction = PIN_INPUT; + return; } - /* Set pin mask */ - obj->mask = (1 << pin_position); +#ifdef ARM_MPS2_IO_FPGAIO + if (pin == USERLED1 || pin == USERLED2) { + /* User LEDs */ + obj->gpio_dev = NULL; + obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV; + obj->pin_number = pin - USERLED1; + obj->direction = PIN_OUTPUT; + return; + } else if (pin == USERSW1 || pin == USERSW2) { + /* User Push buttons */ + obj->gpio_dev = NULL; + obj->mps2_io_dev = &ARM_MPS2_IO_FPGAIO_DEV; + obj->pin_number = pin - USERSW1; + obj->direction = PIN_INPUT; + return; + } +#endif /* ARM_MPS2_IO_FPGAIO */ + +#ifdef ARM_MPS2_IO_SCC + if (pin >= LED1 && pin <= LED8) { + /* MCC LEDs */ + obj->gpio_dev = NULL; + obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV; + obj->pin_number = pin - LED1; + obj->direction = PIN_OUTPUT; + return; + } else if (pin >= SW1 && pin <= SW8) { + /* MCC Switches */ + obj->gpio_dev = NULL; + obj->mps2_io_dev = &ARM_MPS2_IO_SCC_DEV; + obj->pin_number = pin - SW1; + obj->direction = PIN_INPUT; + return; + } +#endif /* ARM_MPS2_IO_SCC */ + + error("pin %d is not a GPIO", pin); } void gpio_mode(gpio_t *obj, PinMode mode) { - pin_mode(obj->pin, mode); + /* PinMode is not supported */ } void gpio_dir(gpio_t *obj, PinDirection direction) { - if (obj->pin >= EXP0 && obj->pin <= EXP51) { + uint32_t flags = ARM_GPIO_PIN_ENABLE; + + obj->direction = direction; + + switch (io_type(obj)) { + case GPIO_DEVICE: switch (direction) { - case PIN_INPUT : - *obj->reg_dirclr = obj->mask; - break; - case PIN_OUTPUT: - *obj->reg_dir |= obj->mask; - break; + case PIN_INPUT: + flags |= ARM_GPIO_INPUT; + break; + case PIN_OUTPUT: + flags |= ARM_GPIO_OUTPUT; + break; + /* default: not added to force to cover all enumeration cases */ } + + (void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, + obj->pin_number, flags); + return; + case MPS2_IO_DEVICE: + /* Do nothing as MPS2 IO direction can not be changed */ + return; + case DEVICE_UNKNOWN: + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ } + + error("can not change the direction of pin"); } int gpio_is_connected(const gpio_t *obj) { - if (obj->pin != (PinName)NC) { + if (obj->pin_number == (uint32_t)NC) { + return 0; + } else { return 1; } - - return 0; } +void gpio_write(gpio_t *obj, int value) +{ + switch (io_type(obj)) { + case GPIO_DEVICE: + (void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, + obj->pin_number, (uint32_t)value); + return; + case MPS2_IO_DEVICE: + if (obj->direction == PIN_INPUT) { + /* + * If the given gpio is in fact a button, ignore the call to not + * write to the corresponding LED instead. + */ + return; + } + arm_mps2_io_write_leds(obj->mps2_io_dev, ARM_MPS2_IO_ACCESS_PIN, + obj->pin_number, (uint32_t)value); + return; + case DEVICE_UNKNOWN: + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ + } + + error("can not write pin"); +} + +int gpio_read(gpio_t *obj) +{ + switch (io_type(obj)) { + case GPIO_DEVICE: + return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, + obj->pin_number); + case MPS2_IO_DEVICE: + switch (obj->direction) { + case PIN_INPUT: + + return (int)arm_mps2_io_read_buttons(obj->mps2_io_dev, + ARM_MPS2_IO_ACCESS_PIN, + obj->pin_number); + case PIN_OUTPUT: + return (int)arm_mps2_io_read_leds(obj->mps2_io_dev, + ARM_MPS2_IO_ACCESS_PIN, + obj->pin_number); + } + + case DEVICE_UNKNOWN: + break; + /* default: The default is not defined intentionally to force the + * compiler to check that all the enumeration values are + * covered in the switch.*/ + } + + error("can not read pin"); + return 0; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_irq_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_irq_api.c index 06d12ff6ca..ad8740c00a 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_irq_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_irq_api.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,425 +14,192 @@ * limitations under the License. */ #include -#include "cmsis.h" +#include "objects.h" #include "gpio_irq_api.h" #include "mbed_error.h" -#define CHANNEL_NUM 32 -#define CMSDK_GPIO_0 CMSDK_GPIO0 -#define CMSDK_GPIO_1 CMSDK_GPIO1 -#define PININT_IRQ 0 +#define ERROR_BIT_NUMBER 0xFF -static uint32_t channel_ids[CHANNEL_NUM] = {0}; -static gpio_irq_handler irq_handler; +struct gpio_irq_handler_t { + gpio_irq_handler handler; + gpio_irq_event event; + uint32_t id; +}; -static inline void handle_interrupt_in(uint32_t channel) +/* Handlers registered */ +static struct gpio_irq_handler_t gpio_irq[PINS_NUMBER]; + +/* + * Return the bit number of the lowest significant bit set to 1 or + * ERROR_BIT_NUMBER if there is no bit set. + */ +static uint8_t find_first_set_bit(uint32_t word) { - uint32_t ch_bit = (1 << channel); - // Return immediately if: - // * The interrupt was already served - // * There is no user handler - // * It is a level interrupt, not an edge interrupt - if (ch_bit < 16) { - if (((CMSDK_GPIO_0->INTSTATUS) == 0) - || (channel_ids[channel] == 0) - || ((CMSDK_GPIO_0->INTTYPESET) == 0) ) { - return; - } + uint8_t bit_number = 0; - if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && (CMSDK_GPIO_0->INTPOLSET & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_RISE); - CMSDK_GPIO_0->INTPOLSET = ch_bit; - } - if ((CMSDK_GPIO_0->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_0->INTPOLSET & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_FALL); - } - - CMSDK_GPIO_0->INTCLEAR = ch_bit; - } else { - if (((CMSDK_GPIO_1->INTSTATUS) == 0) - || (channel_ids[channel] == 0) - || ((CMSDK_GPIO_1->INTTYPESET) == 0)) { - return; - } - - if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && (CMSDK_GPIO_1->INTPOLSET & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_RISE); - CMSDK_GPIO_1->INTPOLSET = ch_bit; - } - if ((CMSDK_GPIO_1->INTTYPESET & ch_bit) && ~(CMSDK_GPIO_1->INTPOLSET & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_FALL); - } - CMSDK_GPIO_1->INTCLEAR = ch_bit; + if (word == 0) { + return ERROR_BIT_NUMBER; } + + while (((word >> bit_number++) & 1UL) == 0); + + return (bit_number - 1); } -void gpio0_irq0(void) +static void handler(struct arm_gpio_dev_t* dev, uint32_t gpio_number, + uint32_t exp_pin_base) { - handle_interrupt_in(0); + uint32_t irq_status = 0; + /* Pin that triggered the IRQ in this GPIO */ + uint8_t pin_number; + /* Pin number in the expension port */ + uint8_t exp_pin_number; + + (void)arm_gpio_get_irq_status(dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, + &irq_status); + + pin_number = find_first_set_bit(irq_status); + if (pin_number == ERROR_BIT_NUMBER) { + /* There was no IRQ */ + return; + } + + (void)arm_gpio_clear_interrupt(dev, pin_number); + + exp_pin_number = exp_pin_base + pin_number; + + gpio_irq[exp_pin_number].handler(gpio_irq[exp_pin_number].id, + gpio_irq[exp_pin_number].event); } -void gpio0_irq1(void) +#ifdef ARM_GPIO0 +void PORT0_IRQHandler(void) { - handle_interrupt_in(1); + handler(&ARM_GPIO0_DEV, GPIO0_NUMBER, EXP_PIN_BASE0); } +#endif /* ARM_GPIO0 */ -void gpio0_irq2(void) +#ifdef ARM_GPIO1 +void PORT1_ALL_IRQHandler(void) { - handle_interrupt_in(2); + handler(&ARM_GPIO1_DEV, GPIO1_NUMBER, EXP_PIN_BASE1); } +#endif /* ARM_GPIO1 */ -void gpio0_irq3(void) +#ifdef ARM_GPIO2 +void PORT2_ALL_IRQHandler(void) { - handle_interrupt_in(3); + handler(&ARM_GPIO2_DEV, GPIO2_NUMBER, EXP_PIN_BASE2); } +#endif /* ARM_GPIO2 */ -void gpio0_irq4(void) +#ifdef ARM_GPIO3 +void PORT3_ALL_IRQHandler(void) { - handle_interrupt_in(4); + handler(&ARM_GPIO3_DEV, GPIO3_NUMBER, EXP_PIN_BASE3); } +#endif /* ARM_GPIO3 */ -void gpio0_irq5(void) +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, + uint32_t id) { - handle_interrupt_in(5); -} + struct arm_gpio_dev_t *gpio_dev; -void gpio0_irq6(void) -{ - handle_interrupt_in(6); -} + if (pin >= EXP0 && pin <= EXP51) { + /* GPIO pins */ + switch (GPIO_DEV_NUMBER(pin)) { +#ifdef ARM_GPIO0 + case 0: + gpio_dev = &ARM_GPIO0_DEV; + obj->irq_number = PORT0_ALL_IRQn; + break; +#endif /* ARM_GPIO0 */ +#ifdef ARM_GPIO1 + case 1: + gpio_dev = &ARM_GPIO1_DEV; + obj->irq_number = PORT1_ALL_IRQn; + break; +#endif /* ARM_GPIO1 */ +#ifdef ARM_GPIO2 + case 2: + gpio_dev = &ARM_GPIO2_DEV; + obj->irq_number = PORT2_ALL_IRQn; + break; +#endif /* ARM_GPIO2 */ +#ifdef ARM_GPIO3 + case 3: + gpio_dev = &ARM_GPIO3_DEV; + obj->irq_number = PORT3_ALL_IRQn; + break; +#endif /* ARM_GPIO3 */ + default: + error("GPIO %d is not enabled", GPIO_DEV_NUMBER(pin)); + return -1; + } -void gpio0_irq7(void) -{ - handle_interrupt_in(7); -} + obj->gpio_dev = gpio_dev; + obj->pin_number = GPIO_PIN_NUMBER(pin); + obj->exp_pin_number = pin; -void gpio0_irq8(void) -{ - handle_interrupt_in(8); -} + arm_gpio_init(gpio_dev); -void gpio0_irq9(void) -{ - handle_interrupt_in(9); -} + /* Save the handler and id into the global structure */ + gpio_irq[pin].handler = handler; + gpio_irq[pin].id = id; -void gpio0_irq10(void) -{ - handle_interrupt_in(10); -} - -void gpio0_irq11(void) -{ - handle_interrupt_in(11); -} - -void gpio0_irq12(void) -{ - handle_interrupt_in(12); -} - -void gpio0_irq13(void) -{ - handle_interrupt_in(13); -} - -void gpio0_irq14(void) -{ - handle_interrupt_in(14); -} - -void gpio0_irq15(void) -{ - handle_interrupt_in(15); -} - -void gpio1_irq0(void) -{ - handle_interrupt_in(16); -} - -void gpio1_irq1(void) -{ - handle_interrupt_in(17); -} -void gpio1_irq2(void) -{ - handle_interrupt_in(18); -} - -void gpio1_irq3(void) -{ - handle_interrupt_in(19); -} - -void gpio1_irq4(void) -{ - handle_interrupt_in(20); -} - -void gpio1_irq5(void) -{ - handle_interrupt_in(21); -} - -void gpio1_irq6(void) -{ - handle_interrupt_in(22); -} - -void gpio1_irq7(void) -{ - handle_interrupt_in(23); -} - -void gpio1_irq8(void) -{ - handle_interrupt_in(24); -} - -void gpio1_irq9(void) -{ - handle_interrupt_in(25); -} - -void gpio1_irq10(void) -{ - handle_interrupt_in(26); -} - -void gpio1_irq11(void) -{ - handle_interrupt_in(27); -} - -void gpio1_irq12(void) -{ - handle_interrupt_in(28); -} - -void gpio1_irq13(void) -{ - handle_interrupt_in(29); -} - -void gpio1_irq14(void) -{ - handle_interrupt_in(30); -} - -void gpio1_irq15(void) -{ - handle_interrupt_in(31); -} - -int gpio_irq_init(gpio_irq_t *obj, PinName pin, - gpio_irq_handler handler, uint32_t id) -{ - int found_free_channel = 0; - int i = 0; - - if (pin == NC) { + return 0; + } else { + /* The pin is not concerned with GPIO IRQ */ + error("Pin %d is not a GPIO", pin); return -1; } - - irq_handler = handler; - - for (i=0; ich = i; - found_free_channel = 1; - break; - } - } - - if (!found_free_channel) { - return -1; - } - - /* To select a pin for any of the eight pin interrupts, write the pin number - * as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55. - * @see: mbed_capi/PinNames.h - */ - if (pin <16) { - CMSDK_GPIO_0->INTENSET |= (0x1 << pin); - } - - if (pin >= 16) { - CMSDK_GPIO_1->INTENSET |= (0x1 << pin); - } - - void (*channels_irq)(void) = NULL; - switch (obj->ch) { - case 0: - channels_irq = &gpio0_irq0; - break; - case 1: - channels_irq = &gpio0_irq1; - break; - case 2: - channels_irq = &gpio0_irq2; - break; - case 3: - channels_irq = &gpio0_irq3; - break; - case 4: - channels_irq = &gpio0_irq4; - break; - case 5: - channels_irq = &gpio0_irq5; - break; - case 6: - channels_irq = &gpio0_irq6; - break; - case 7: - channels_irq = &gpio0_irq7; - break; - case 8: - channels_irq = &gpio0_irq8; - break; - case 9: - channels_irq = &gpio0_irq9; - break; - case 10: - channels_irq = &gpio0_irq10; - break; - case 11: - channels_irq = &gpio0_irq11; - break; - case 12: - channels_irq = &gpio0_irq12; - break; - case 13: - channels_irq = &gpio0_irq13; - break; - case 14: - channels_irq = &gpio0_irq14; - break; - case 15: - channels_irq = &gpio0_irq15; - break; - case 16: - channels_irq = &gpio1_irq0; - break; - case 17: - channels_irq = &gpio1_irq1; - break; - case 18: - channels_irq = &gpio1_irq2; - break; - case 19: - channels_irq = &gpio1_irq3; - break; - case 20: - channels_irq = &gpio1_irq4; - break; - case 21: - channels_irq = &gpio1_irq5; - break; - case 22: - channels_irq = &gpio1_irq6; - break; - case 23: - channels_irq = &gpio1_irq7; - break; - case 24: - channels_irq = &gpio1_irq8; - break; - case 25: - channels_irq = &gpio1_irq9; - break; - case 26: - channels_irq = &gpio1_irq10; - break; - case 27: - channels_irq = &gpio1_irq11; - break; - case 28: - channels_irq = &gpio1_irq12; - break; - case 29: - channels_irq = &gpio1_irq13; - break; - case 30: - channels_irq = &gpio1_irq14; - break; - case 31: - channels_irq = &gpio1_irq15; - break; - } - - NVIC_SetVector((IRQn_Type)(PININT_IRQ + obj->ch), (uint32_t)channels_irq); - NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); - - return 0; } void gpio_irq_free(gpio_irq_t *obj) { - channel_ids[obj->ch] = 0; + /* Not implemented because the device can not be uninitialized. */ } void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { - unsigned int ch_bit = (1 << obj->ch); + /* Interrupt is set on an input pin on rising or falling edge */ + uint32_t flags = ARM_GPIO_PIN_ENABLE | ARM_GPIO_INPUT | ARM_GPIO_IRQ | + ARM_GPIO_IRQ_EDGE; - if (obj->ch <16) { - /* Clear interrupt */ - if (!(CMSDK_GPIO_0->INTTYPESET & ch_bit)) { - CMSDK_GPIO_0->INTCLEAR = ch_bit; - } - CMSDK_GPIO_0->INTTYPESET &= ch_bit; + switch (event) { + case IRQ_RISE: + flags |= ARM_GPIO_IRQ_ACTIVE_HIGH; + break; + case IRQ_FALL: + flags |= ARM_GPIO_IRQ_ACTIVE_LOW; + break; + case IRQ_NONE: + return; + } - /* Set interrupt */ - if (event == IRQ_RISE) { - CMSDK_GPIO_0->INTPOLSET |= ch_bit; - if (enable) { - CMSDK_GPIO_0->INTENSET |= ch_bit; - } else { - CMSDK_GPIO_0->INTENCLR |= ch_bit; - } - } else { - CMSDK_GPIO_0->INTPOLCLR |= ch_bit; - if (enable) { - CMSDK_GPIO_0->INTENSET |= ch_bit; - } else { - CMSDK_GPIO_0->INTENCLR |= ch_bit; - } - } + (void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, obj->pin_number, + flags); + + /* Record the event type of this pin */ + gpio_irq[obj->exp_pin_number].event = event; + + NVIC_EnableIRQ(obj->irq_number); + + if (enable) { + gpio_irq_enable(obj); } else { - /* Clear interrupt */ - if (!(CMSDK_GPIO_1->INTTYPESET & ch_bit)) { - CMSDK_GPIO_1->INTCLEAR = ch_bit; - } - CMSDK_GPIO_1->INTTYPESET &= ch_bit; - - /* Set interrupt */ - if (event == IRQ_RISE) { - CMSDK_GPIO_1->INTPOLSET |= ch_bit; - if (enable) { - CMSDK_GPIO_1->INTENSET |= ch_bit; - } else { - CMSDK_GPIO_1->INTENCLR |= ch_bit; - } - } else { - CMSDK_GPIO_1->INTPOLCLR |= ch_bit; - if (enable) { - CMSDK_GPIO_1->INTENSET |= ch_bit; - } else { - CMSDK_GPIO_1->INTENCLR |= ch_bit; - } - } + gpio_irq_disable(obj); } } void gpio_irq_enable(gpio_irq_t *obj) { - NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); + (void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, + obj->pin_number, ARM_GPIO_IRQ_ENABLE); } void gpio_irq_disable(gpio_irq_t *obj) { - NVIC_DisableIRQ((IRQn_Type)(PININT_IRQ + obj->ch)); + (void)arm_gpio_set_interrupt(obj->gpio_dev, ARM_GPIO_ACCESS_PIN, + obj->pin_number, ARM_GPIO_IRQ_DISABLE); } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_object.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_object.h deleted file mode 100644 index bf5a7a59c8..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_object.h +++ /dev/null @@ -1,56 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef MBED_GPIO_OBJECT_H -#define MBED_GPIO_OBJECT_H - -#include "cmsis.h" -#include "PortNames.h" -#include "PeripheralNames.h" -#include "PinNames.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - PinName pin; - uint32_t mask; - uint32_t pin_number; - __IO uint32_t *reg_dir; - __IO uint32_t *reg_dirclr; - __IO uint32_t *reg_data; - __I uint32_t *reg_in; -} gpio_t; - -static inline void gpio_write(gpio_t *obj, int value) -{ - if (value) { - *obj->reg_data |= (obj->mask); - } else { - *obj->reg_data &= ~(obj->mask); - } -} - -static inline int gpio_read(gpio_t *obj) -{ - return ((*obj->reg_in & obj->mask) ? 1 : 0); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_objects.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_objects.h new file mode 100755 index 0000000000..3d92d68c80 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/gpio_objects.h @@ -0,0 +1,56 @@ +/* mbed Microcontroller Library + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MBED_GPIO_OBJECTS_H__ +#define __MBED_GPIO_OBJECTS_H__ + +/* + * GPIO device number, there are 16 pins per GPIO + * equivalent: pin / 16 + */ +#define GPIO_DEV_NUMBER(pin) ((pin) >> 4) +/* + * Pin number of this pin inside its GPIO + * equivalent: pin % 16 + */ +#define GPIO_PIN_NUMBER(pin) ((pin) & 0xF) + +/* Number of the GPIO device */ +#define GPIO0_NUMBER 0 +#define GPIO1_NUMBER 1 +#define GPIO2_NUMBER 2 +#define GPIO3_NUMBER 3 + +/* Base EXP pin number for the corresponding GPIO */ +#define EXP_PIN_BASE0 EXP0 +#define EXP_PIN_BASE1 EXP16 +#define EXP_PIN_BASE2 EXP32 +#define EXP_PIN_BASE3 EXP48 + +#define GPIO_DEVICES 4 +#define PINS_PER_GPIO 16 +/* Pins 4 to 15 of GPIO3 are not used */ +#define PINS_NOT_USED 12 +#define PINS_NUMBER (GPIO_DEVICES * PINS_PER_GPIO - PINS_NOT_USED) + +/* GPIO3 port only uses first 4 pins */ +#define GPIO3_PIN_NUMBER 4 + +/* When doing a port access, the pin number argument is useless */ +#define ARG_NOT_USED 0 + +#endif /* __MBED_GPIO_OBJECTS_H__ */ + diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h index f60746f463..a95620c436 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,29 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef MBED_OBJECTS_H -#define MBED_OBJECTS_H +#ifndef __MBED_OBJECTS_H__ +#define __MBED_OBJECTS_H__ #include "cmsis.h" #include "PortNames.h" #include "PeripheralNames.h" #include "PinNames.h" +#include "platform_devices.h" +#include "gpio_objects.h" #ifdef __cplusplus extern "C" { #endif +typedef struct gpio_s { + struct arm_gpio_dev_t *gpio_dev; + struct arm_mps2_io_dev_t *mps2_io_dev; + uint32_t pin_number; + PinDirection direction; +} gpio_t; + struct gpio_irq_s { - uint32_t ch; + struct arm_gpio_dev_t *gpio_dev; + uint32_t pin_number; /* Pin number inside the GPIO */ + uint32_t exp_pin_number; /* Pin number on the expension port */ + IRQn_Type irq_number; /* IRQ number of the GPIO interrupt of + this pin */ }; struct port_s { - __IO uint32_t *reg_dir; - __IO uint32_t *reg_dirclr; - __IO uint32_t *reg_out; - __IO uint32_t *reg_in; - PortName port; - uint32_t mask; + struct arm_gpio_dev_t *gpio_dev; }; struct serial_s { @@ -69,10 +77,8 @@ struct analogin_s { uint16_t ctrl_register; /* Control bits with the channel identifier */ }; -#include "gpio_object.h" - #ifdef __cplusplus } #endif -#endif +#endif /* __MBED_OBJECTS_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c old mode 100644 new mode 100755 index bb752f16be..719cb4beaf --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/pinmap.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,40 +16,64 @@ #include "mbed_assert.h" #include "pinmap.h" #include "mbed_error.h" - -#define GET_GPIO_PIN_POS(pin) (pin & 0x0F) /* pin % 16 */ -#define GET_GPIO_MAP_NUM(pin) (pin >> 4) /* pin / 16 */ -#define GPIO_NUM 4 - -static CMSDK_GPIO_TypeDef* GPIO_MAP[GPIO_NUM] = { - CMSDK_GPIO0, - CMSDK_GPIO1, - CMSDK_GPIO2, - CMSDK_GPIO3 -}; +#include "objects.h" void pin_function(PinName pin, int function) { - CMSDK_GPIO_TypeDef* p_gpio_map = 0; + struct arm_gpio_dev_t *gpio_dev; + uint32_t flags; - MBED_ASSERT(pin != (PinName)NC); + MBED_ASSERT(pin != NC); + /* The pin has to be a GPIO pin */ if (pin >= EXP0 && pin <= EXP51) { - if (function == ALTERNATE_FUNC) { - p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)]; - p_gpio_map->ALTFUNCSET = (1 << GET_GPIO_PIN_POS(pin)); - } else if(function == GPIO_FUNC) { - p_gpio_map = GPIO_MAP[GET_GPIO_MAP_NUM(pin)]; - p_gpio_map->ALTFUNCCLR = (1 << GET_GPIO_PIN_POS(pin)); - } else { - error("Invalid pin_function value %d", function); + switch (function) { + case ALTERNATE_FUNC: + flags = ARM_GPIO_PIN_DISABLE; + break; + case GPIO_FUNC: + flags = ARM_GPIO_PIN_ENABLE; + break; + default: + return; } + + switch (GPIO_DEV_NUMBER(pin)) { +#ifdef ARM_GPIO0 + case GPIO0_NUMBER: + gpio_dev = &ARM_GPIO0_DEV; + break; +#endif /* ARM_GPIO0 */ +#ifdef ARM_GPIO1 + case GPIO1_NUMBER: + gpio_dev = &ARM_GPIO1_DEV; + break; +#endif /* ARM_GPIO1 */ +#ifdef ARM_GPIO2 + case GPIO2_NUMBER: + gpio_dev = &ARM_GPIO2_DEV; + break; +#endif /* ARM_GPIO2 */ +#ifdef ARM_GPIO3 + case GPIO3_NUMBER: + gpio_dev = &ARM_GPIO3_DEV; + break; +#endif /* ARM_GPIO3 */ + default: + error("GPIO %d, associated with expansion pin %d, is disabled", + pin, GPIO_DEV_NUMBER(pin)); + return; + } + + arm_gpio_init(gpio_dev); + (void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PIN, + GPIO_PIN_NUMBER(pin), flags); } } void pin_mode(PinName pin, PinMode mode) { - MBED_ASSERT(pin != (PinName)NC); + MBED_ASSERT(pin != NC); - /* Pin modes configuration is not supported */ + /* PinMode is not supported */ } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/port_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/port_api.c index 61c4ca8d52..3f96b55c80 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/port_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/port_api.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,86 +13,90 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "port_api.h" -#include "pinmap.h" -#include "gpio_api.h" - -#define MAX_GPIO_PINS 16 +#include "objects.h" +#include "mbed_error.h" PinName port_pin(PortName port, int pin_n) { - if (pin_n < 0 || pin_n > MAX_GPIO_PINS) { - error("Invalid GPIO pin number %d", pin_n); + if (pin_n < 0 || pin_n >= PINS_PER_GPIO || + ((port == Port3) && (pin_n >= GPIO3_PIN_NUMBER))) { + return NC; } - return (PinName)((port << PORT_SHIFT) | pin_n); + return (PINS_PER_GPIO * port + pin_n); } void port_init(port_t *obj, PortName port, int mask, PinDirection dir) { - uint32_t i; - CMSDK_GPIO_TypeDef *port_reg; + struct arm_gpio_dev_t *gpio_dev; + uint32_t flags = ARM_GPIO_PIN_ENABLE; switch (port) { - case Port0: - port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO0_BASE); - break; - case Port1: - port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO1_BASE); - break; - case Port2: - port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO2_BASE); - break; - case Port3: - port_reg = (CMSDK_GPIO_TypeDef *)(CMSDK_GPIO3_BASE); - break; +#ifdef ARM_GPIO0 + case Port0: + gpio_dev = &ARM_GPIO0_DEV; + break; +#endif /* ARM_GPIO0 */ +#ifdef ARM_GPIO1 + case Port1: + gpio_dev = &ARM_GPIO1_DEV; + break; +#endif /* ARM_GPIO1 */ +#ifdef ARM_GPIO2 + case Port2: + gpio_dev = &ARM_GPIO2_DEV; + break; +#endif /* ARM_GPIO2 */ +#ifdef ARM_GPIO3 + case Port3: + gpio_dev = &ARM_GPIO3_DEV; + break; +#endif /* ARM_GPIO3 */ + default: + error("Port%d is not enabled", port); + return; } - obj->port = port; - obj->mask = mask; - obj->reg_in = &port_reg->DATAOUT; - obj->reg_dir = &port_reg->OUTENABLESET; - obj->reg_dirclr = &port_reg->OUTENABLECLR; + arm_gpio_init(gpio_dev); + obj->gpio_dev = gpio_dev; - /* The function is set per pin: reuse gpio logic */ - for (i=0; i < MAX_GPIO_PINS; i++) { - if (obj->mask & (1<port, i)); - } + arm_gpio_set_port_mask(gpio_dev, mask); + + switch (dir) { + case PIN_INPUT: + flags |= ARM_GPIO_INPUT; + break; + case PIN_OUTPUT: + flags |= ARM_GPIO_OUTPUT; + break; + /* default: not added to force to cover all enumeration cases */ } - port_dir(obj, dir); + (void)arm_gpio_config(gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, flags); } void port_mode(port_t *obj, PinMode mode) { - uint32_t i; - /* The mode is set per pin: reuse pinmap logic */ - for (i=0; i < MAX_GPIO_PINS; i++) { - if (obj->mask & (1 << i)) { - pin_mode(port_pin(obj->port, i), mode); - } - } + /* PinMode is not supported */ } void port_dir(port_t *obj, PinDirection dir) { - switch (dir) { - case PIN_INPUT: - *obj->reg_dir &= ~obj->mask; - break; - case PIN_OUTPUT: - *obj->reg_dir |= obj->mask; - break; - } + uint32_t flags = (dir == PIN_OUTPUT) ? ARM_GPIO_OUTPUT : ARM_GPIO_INPUT; + (void)arm_gpio_config(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, + flags); } void port_write(port_t *obj, int value) { - *obj->reg_in = value; + (void)arm_gpio_write(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, ARG_NOT_USED, + (uint32_t)value); } int port_read(port_t *obj) { - return (*obj->reg_in); + return (int)arm_gpio_read(obj->gpio_dev, ARM_GPIO_ACCESS_PORT, + ARG_NOT_USED); } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c index 828d162a11..fe1b28835a 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c @@ -1,5 +1,5 @@ /* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -124,8 +124,8 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) * The CMSDK APB UART doesn't have support for flow control. * Ref. DDI0479C_cortex_m_system_design_kit_r1p0_trm.pdf */ - uart_data[obj->index].sw_rts.pin = NC; - uart_data[obj->index].sw_cts.pin = NC; + uart_data[obj->index].sw_rts.pin_number = NC; + uart_data[obj->index].sw_cts.pin_number = NC; if (uart == STDIO_UART) { stdio_uart_inited = 1; @@ -220,7 +220,7 @@ static inline void uart_irq(uint32_t intstatus, uint32_t index, return; } - if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin)) { + if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin_number)) { gpio_write(&uart_data[index].sw_rts, 1); /* Disable interrupt if it wasn't enabled by the application */ if (!uart_data[index].rx_irq_set_api) { From 37cf802a7adbb123218c5d74db19f77a334a3705 Mon Sep 17 00:00:00 2001 From: Tamas Kaman Date: Thu, 7 Dec 2017 12:34:13 +0100 Subject: [PATCH 3/4] CM3DS: update SPI implementation This commit adds the SPI driver which is now called by the SPI HAL implementation. It also removes legacy definitions. Change-Id: Iadb20dda9dfa571db3de66c3a1ce45d80d8b81b6 Signed-off-by: Tamas Kaman --- .../TARGET_CM3DS_MPS2/PeripheralNames.h | 11 +- .../TARGET_CM3DS_MPS2/device/SMM_MPS2.h | 155 +--- .../TARGET_CM3DS_MPS2/device/device_cfg.h | 8 + .../device/drivers/spi_pl022_drv.c | 870 ++++++++++++++++++ .../device/drivers/spi_pl022_drv.h | 501 ++++++++++ .../device/platform_devices.c | 111 +++ .../device/platform_devices.h | 18 + .../TARGET_CM3DS_MPS2/objects.h | 6 +- .../TARGET_CM3DS_MPS2/spi_api.c | 367 ++++---- .../TARGET_CM3DS_MPS2/spi_def.h | 174 ---- 10 files changed, 1685 insertions(+), 536 deletions(-) create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.c create mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h delete mode 100644 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h index c442b5868f..fd6d842625 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h @@ -53,11 +53,12 @@ typedef enum { } ADCName; typedef enum { - SPI_0 = (int)MPS2_SSP0_BASE, - SPI_1 = (int)MPS2_SSP1_BASE, - SPI_2 = (int)MPS2_SSP2_BASE, - SPI_3 = (int)MPS2_SSP3_BASE, - SPI_4 = (int)MPS2_SSP4_BASE + SPI_0 = 0, + SPI_1, + SPI_2, + SPI_3, + SPI_4, + SPI_NC = (SPI_4 + 1) } SPIName; typedef enum { diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h index 0920930a2d..462e740ea9 100644 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/SMM_MPS2.h @@ -1,6 +1,6 @@ /* MPS2 CMSIS Library * - * Copyright (c) 2006-2017 ARM Limited + * Copyright (c) 2006-2018 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -153,154 +153,6 @@ typedef struct // } MPS2_SCC_TypeDef; -/******************************************************************************/ -/* SSP Peripheral declaration */ -/******************************************************************************/ - -typedef struct // Document DDI0194G_ssp_pl022_r1p3_trm.pdf -{ - __IO uint32_t CR0; // Offset: 0x000 (R/W) Control register 0 - // [31:16] : Reserved - // [15:8] : Serial clock rate - // [7] : SSPCLKOUT phase, applicable to Motorola SPI frame format only - // [6] : SSPCLKOUT polarity, applicable to Motorola SPI frame format only - // [5:4] : Frame format - // [3:0] : Data Size Select - __IO uint32_t CR1; // Offset: 0x004 (R/W) Control register 1 - // [31:4] : Reserved - // [3] : Slave-mode output disable - // [2] : Master or slave mode select - // [1] : Synchronous serial port enable - // [0] : Loop back mode - __IO uint32_t DR; // Offset: 0x008 (R/W) Data register - // [31:16] : Reserved - // [15:0] : Transmit/Receive FIFO - __I uint32_t SR; // Offset: 0x00C (R/ ) Status register - // [31:5] : Reserved - // [4] : PrimeCell SSP busy flag - // [3] : Receive FIFO full - // [2] : Receive FIFO not empty - // [1] : Transmit FIFO not full - // [0] : Transmit FIFO empty - __IO uint32_t CPSR; // Offset: 0x010 (R/W) Clock prescale register - // [31:8] : Reserved - // [8:0] : Clock prescale divisor - __IO uint32_t IMSC; // Offset: 0x014 (R/W) Interrupt mask set or clear register - // [31:4] : Reserved - // [3] : Transmit FIFO interrupt mask - // [2] : Receive FIFO interrupt mask - // [1] : Receive timeout interrupt mask - // [0] : Receive overrun interrupt mask - __I uint32_t RIS; // Offset: 0x018 (R/ ) Raw interrupt status register - // [31:4] : Reserved - // [3] : raw interrupt state, prior to masking, of the SSPTXINTR interrupt - // [2] : raw interrupt state, prior to masking, of the SSPRXINTR interrupt - // [1] : raw interrupt state, prior to masking, of the SSPRTINTR interrupt - // [0] : raw interrupt state, prior to masking, of the SSPRORINTR interrupt - __I uint32_t MIS; // Offset: 0x01C (R/ ) Masked interrupt status register - // [31:4] : Reserved - // [3] : transmit FIFO masked interrupt state, after masking, of the SSPTXINTR interrupt - // [2] : receive FIFO masked interrupt state, after masking, of the SSPRXINTR interrupt - // [1] : receive timeout masked interrupt state, after masking, of the SSPRTINTR interrupt - // [0] : receive over run masked interrupt status, after masking, of the SSPRORINTR interrupt - __O uint32_t ICR; // Offset: 0x020 ( /W) Interrupt clear register - // [31:2] : Reserved - // [1] : Clears the SSPRTINTR interrupt - // [0] : Clears the SSPRORINTR interrupt - __IO uint32_t DMACR; // Offset: 0x024 (R/W) DMA control register - // [31:2] : Reserved - // [1] : Transmit DMA Enable - // [0] : Receive DMA Enable -} MPS2_SSP_TypeDef; - - -// SSP_CR0 Control register 0 -#define SSP_CR0_DSS_Pos 0 // Data Size Select -#define SSP_CR0_DSS_Msk (0xF<bit_rate is 0 + */ +static uint32_t spi_calc_clock_rate( + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg, + uint32_t sys_clk, volatile uint32_t *cr0) +{ + uint32_t clkps_dvsr; /* clock prescale divisor */ + uint32_t scr; /* serial clock rate */ + + for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE; + clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) { + + /* Calculate clock rate based on the new clock prescale divisor */ + scr = (sys_clk / (clkps_dvsr * ctrl_cfg->bit_rate)) - 1; + + /* Checks if it can be supported by the divider */ + if (scr <= SPI_PL022_MAX_SCR_VALUE) { + *cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK; + *cr0 |= (scr << SPI_PL022_SSPCR0_SCR_POS); + return clkps_dvsr; + } + } + + /* no good value was found */ + *cr0 &= ~SPI_PL022_SSPCR0_SCR_MSK; + return SPI_PL022_INVALID_SSPCPSR_VALUE; +} + +void spi_pl022_dev_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK; +} + +void spi_pl022_dev_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK; +} + +uint32_t spi_pl022_get_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return p_spi->sspsr; +} + +/* + * \brief Configures the SPI PL022 device. + * + * \param[in] spi_dev Pointer to SPI memory map \ref spi_pl022_dev_reg_map_t + * \param[in] ctrl_cfg SPI control configuration \ref spi_pl022_ctrl_cfg_t + * \param[in] sys_clk System clock. + * + * \return Error code from \ref spi_pl022_error_t + */ +static enum spi_pl022_error_t spi_set_configuration( + struct spi_pl022_dev_reg_map_t* spi_dev, + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg, + uint32_t sys_clk) +{ + uint32_t tmp_cr0, tmp_cr1; + uint32_t clk_dvsr; + + if(!sys_clk || !ctrl_cfg->bit_rate) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + /* Word size */ + tmp_cr0 = ((ctrl_cfg->word_size -1) << SPI_PL022_SSPCR0_DSS_POS) + & SPI_PL022_SSPCR0_DSS_MSK; + + /* Frame format is stored in the least 2 bits*/ + switch(ctrl_cfg->frame_format & 0x3ul) + { + case SPI_PL022_CFG_FRF_MOT: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MOT_SPI << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + /* Add motorola phase & polarity */ + tmp_cr0 |= (SPI_PL022_SSPCR0_SPO_MSK & SPI_PL022_SSPCR0_SPH_MSK); + break; + case SPI_PL022_CFG_FRF_TI: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_TI_SS << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + break; + case SPI_PL022_CFG_FRF_MICROWIRE: + tmp_cr0 |= (SPI_PL022_SSPCR0_FRF_MICROWIRE << SPI_PL022_SSPCR0_FRF_POS) + & SPI_PL022_SSPCR0_FRF_MSK; + break; + default: + return SPI_PL022_ERR_BAD_CONFIG; + /* break; */ + } + + /* Clock logic */ + clk_dvsr = spi_calc_clock_rate(ctrl_cfg, sys_clk, &tmp_cr0); + + if (SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) { + return SPI_PL022_ERR_BAD_CONFIG; + } + + /* Enable device and set configured mode */ + tmp_cr1 = (0x1 << SPI_PL022_SSPCR1_SSE_POS) & SPI_PL022_SSPCR1_SSE_MSK; + tmp_cr1 |= ((ctrl_cfg->spi_mode << SPI_PL022_SSPCR1_MS_POS) + & SPI_PL022_SSPCR1_MS_MSK); + + + /* Start initialization by disabling the device */ + spi_dev->sspcr1 = 0; + + /* Set the value received for the configuration */ + spi_dev->sspcpsr = clk_dvsr; + spi_dev->sspcr0 = tmp_cr0; + + /* Default setup hard coded */ + spi_dev->sspimsc = 0; + spi_dev->sspdmacr = 0; + spi_dev->sspicr = (SPI_PL022_SSPICR_RORIC_MSK | SPI_PL022_SSPICR_RTIC_MSK); + + spi_dev->sspcr1 = tmp_cr1; + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_init(struct spi_pl022_dev_t* dev, + uint32_t sys_clk) +{ + enum spi_pl022_error_t ret; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + ret = spi_set_configuration(p_spi, &dev->cfg->default_ctrl_cfg, sys_clk); + + if(ret != SPI_PL022_ERR_NONE) { + return ret; + } + + dev->data->sys_clk = sys_clk; + + /* Initilizes current SPI control configuration */ + memcpy(&dev->data->ctrl_cfg, &dev->cfg->default_ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + dev->data->state = SPI_PL022_INITIALIZED; + + return ret; +} + +enum spi_pl022_error_t spi_pl022_set_ctrl_cfg(struct spi_pl022_dev_t* dev, + const struct spi_pl022_ctrl_cfg_t* ctrl_cfg) +{ + enum spi_pl022_error_t ret; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(ctrl_cfg == NULL) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + ret = spi_set_configuration(p_spi, ctrl_cfg, dev->data->sys_clk); + + if(ret != SPI_PL022_ERR_NONE) { + return ret; + } + + /* Updates current SPI control configuration */ + memcpy(&dev->data->ctrl_cfg, ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_get_ctrl_cfg(struct spi_pl022_dev_t* dev, + struct spi_pl022_ctrl_cfg_t* ctrl_cfg) +{ + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(ctrl_cfg == NULL) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + /* Copy current SPI control configuration */ + memcpy(ctrl_cfg, &dev->data->ctrl_cfg, + sizeof(struct spi_pl022_ctrl_cfg_t)); + + return SPI_PL022_ERR_NONE; +} + +void spi_pl022_select_mode(struct spi_pl022_dev_t* dev, + enum spi_pl022_mode_select_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + + /* Disable device */ + p_spi->sspcr1 &= ~SPI_PL022_SSPCR1_SSE_MSK; + /* Set mode */ + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_MS_MSK) + | (mode << SPI_PL022_SSPCR1_MS_POS); + dev->data->ctrl_cfg.spi_mode = mode; + /* Re-enable device */ + p_spi->sspcr1 |= SPI_PL022_SSPCR1_SSE_MSK; +} + +void spi_pl022_set_slave_output(struct spi_pl022_dev_t* dev, + enum spi_pl022_slave_output_mode_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_SOD_MSK) + | (mode << SPI_PL022_SSPCR1_SOD_POS); +} + +void spi_pl022_set_loopback_mode(struct spi_pl022_dev_t* dev, + enum spi_pl022_loopback_select_t mode) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspcr1 = (p_spi->sspcr1 & ~SPI_PL022_SSPCR1_LBM_MSK) + | (mode << SPI_PL022_SSPCR1_LBM_POS); +} + +void spi_pl022_enable_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspimsc |= (irq_mask & SPI_PL022_SSPIMSC_VALID_MSK); +} + +void spi_pl022_disable_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspimsc &= ~(irq_mask & SPI_PL022_SSPIMSC_VALID_MSK); +} + +uint32_t spi_pl022_get_raw_irq_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return (p_spi->sspris & SPI_PL022_SSPRIS_VALID_MSK); +} + +uint32_t spi_pl022_get_masked_irq_status(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + return (p_spi->sspmis & SPI_PL022_SSPMIS_VALID_MSK); +} + +void spi_pl022_clear_interrupt(struct spi_pl022_dev_t* dev, + uint32_t irq_mask) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspicr = (irq_mask & SPI_PL022_SSPICR_VALID_MSK); +} + +void spi_pl022_dma_mode_enable(struct spi_pl022_dev_t* dev, + uint32_t dma) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspdmacr |= (dma & SPI_PL022_SSPDMACR_VALID_MSK); +} + +void spi_pl022_dma_mode_disable(struct spi_pl022_dev_t* dev, + uint32_t dma) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + p_spi->sspdmacr &= ~(dma & SPI_PL022_SSPDMACR_VALID_MSK); +} + +void spi_pl022_get_periphID(struct spi_pl022_dev_t* dev, + struct spi_pl022_periphid_t* periphid) +{ + uint32_t tempid, tempid2; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + tempid = p_spi->sspperiphid0 & SPI_PL022_SSPPERIPH_ID0_PARTNO_0_MSK; + tempid2 = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_PARTNO_1_MSK) + << SPI_PL022_SSPPERIPH_ID0_PARTNO_0_SIZE; + periphid->partNumber = tempid | tempid2; + + tempid = (p_spi->sspperiphid1 & SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_MSK) + >> SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_POS; + tempid2 = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_DESIGNER_1_MSK) + << SPI_PL022_SSPPERIPH_ID1_DESIGNER_0_SIZE; + periphid->designerID = tempid | tempid2; + + tempid = (p_spi->sspperiphid2 & SPI_PL022_SSPPERIPH_ID2_REVIISON_MSK) + >> SPI_PL022_SSPPERIPH_ID2_REVISION_SIZE; + periphid->revision = tempid; + + tempid = p_spi->sspperiphid3 & SPI_PL022_SSPPERIPH_ID3_CONFIG_MSK; + periphid->configuration = tempid; +} + +void spi_pl022_get_PrimeCell_ID(struct spi_pl022_dev_t* dev, + struct spi_pl022_primecell_id_t* cellid) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + cellid->cellid0 = (uint8_t) p_spi->ssppcellid0; + cellid->cellid1 = (uint8_t) p_spi->ssppcellid1; + cellid->cellid2 = (uint8_t) p_spi->ssppcellid2; + cellid->cellid3 = (uint8_t) p_spi->ssppcellid3; +} + +enum spi_pl022_error_t spi_pl022_set_sys_clk(struct spi_pl022_dev_t* dev, + uint32_t sys_clk) +{ + uint32_t clk_dvsr; + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(!(dev->data->state & SPI_PL022_INITIALIZED)) { + return SPI_PL022_ERR_NOT_INIT; + } + + if(!sys_clk) { + return SPI_PL022_ERR_INVALID_ARGS; + } + + clk_dvsr = spi_calc_clock_rate(&dev->data->ctrl_cfg, sys_clk, &p_spi->sspcr0); + + if(SPI_PL022_INVALID_SSPCPSR_VALUE == clk_dvsr) { + return SPI_PL022_ERR_BAD_CONFIG; + } + + p_spi->sspcpsr = clk_dvsr; + dev->data->sys_clk = sys_clk; + + return SPI_PL022_ERR_NONE; +} + +enum spi_pl022_error_t spi_pl022_read(struct spi_pl022_dev_t* dev, + void *rx_ptr) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(p_spi->sspsr & SPI_PL022_SSPSR_RNE_MSK) { + if(dev->data->ctrl_cfg.word_size <= 8) { + *(uint8_t*)rx_ptr = p_spi->sspdr & WORD_1BYTE_MASK; + } else { + *(uint16_t*)rx_ptr = p_spi->sspdr & WORD_2BYTES_MASK; + } + return SPI_PL022_ERR_NONE; + } + return SPI_PL022_ERR_NO_RX; +} + +uint32_t spi_pl022_slave_read(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + uint32_t data; + + if(dev->data->ctrl_cfg.word_size <= 8) { + data = p_spi->sspdr & WORD_1BYTE_MASK; + } else { + data = p_spi->sspdr & WORD_2BYTES_MASK; + } + return data; +} + +enum spi_pl022_error_t spi_pl022_write(struct spi_pl022_dev_t* dev, + const enum spi_pl022_mode_select_t mode, + const void *tx_ptr) +{ + struct spi_pl022_dev_reg_map_t* p_spi = + (struct spi_pl022_dev_reg_map_t*) dev->cfg->base; + + if(p_spi->sspsr & SPI_PL022_SSPSR_TNF_MSK){ + if(dev->data->ctrl_cfg.word_size <= 8) { + p_spi->sspdr = *(const uint8_t*)tx_ptr; + } else { + p_spi->sspdr = *(const uint16_t*)tx_ptr; + } + /* Wait for write to go through */ + if (mode == SPI_PL022_MASTER_SELECT) { + while(p_spi->sspsr & SPI_PL022_SSPSR_BSY_MSK) {}; + } + return SPI_PL022_ERR_NONE; + } + return SPI_PL022_ERR_NO_TX; +} + +enum spi_pl022_error_t spi_pl022_txrx_blocking(struct spi_pl022_dev_t* dev, + const void *tx_ptr, + uint32_t *tx_len_ptr, + void *rx_ptr, + uint32_t *rx_len_ptr) +{ + uint32_t i; + enum spi_pl022_error_t retval = SPI_PL022_ERR_NONE; + uint8_t word_size = 1; + uint32_t rx_data, tx_data, total_len; + + if(dev->data->ctrl_cfg.word_size > 8) { + word_size = 2; + /* return error if sizes are not word_size aligned */ + if ((*tx_len_ptr & 0x1) || (*rx_len_ptr & 0x1)) { + return SPI_PL022_ERR_INVALID_ARGS; + } + } + + total_len = (*tx_len_ptr > *rx_len_ptr) ? *tx_len_ptr : *rx_len_ptr; + + for(i=0;idata->ctrl_cfg.spi_mode, &tx_data); + if(retval != SPI_PL022_ERR_NONE) { + *tx_len_ptr = i; + *rx_len_ptr = i; + break; + } + if(i < *tx_len_ptr) { + tx_ptr = (const uint8_t*)tx_ptr + word_size; + } + retval = spi_pl022_read(dev, &rx_data); + if(retval != SPI_PL022_ERR_NONE) { + /* send went through, align tx_len to the updated tx_ptr */ + *tx_len_ptr = i + word_size; + /* don't update rx_len if there is an overflow */ + if (i < *rx_len_ptr) { + *rx_len_ptr = i; + } + break; + } + /* do not overflow rx buffer */ + if(i<*rx_len_ptr) { + if (word_size == 1) { + *(uint8_t*)rx_ptr = (uint8_t) rx_data; + } else { + *(uint16_t*)rx_ptr = (uint16_t) rx_data; + } + rx_ptr = (uint8_t*)rx_ptr + word_size; + } + } + + return retval; +} + +/* + * TEST APIs + */ +void spi_pl022_test_fifo_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr |= SPI_PL022_SSPTCR_TESTFIFO_MSK; +} + +void spi_pl022_test_fifo_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr &= ~SPI_PL022_SSPTCR_TESTFIFO_MSK; +} + +void spi_pl022_integration_test_enable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr |= SPI_PL022_SSPTCR_ITEN_MSK; +} + +void spi_pl022_integration_test_disable(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + p_spi->ssptcr &= ~SPI_PL022_SSPTCR_ITEN_MSK; +} + + +void spi_pl022_write_test_data(struct spi_pl022_dev_t* dev, + void *tx_ptr) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + if(dev->data->ctrl_cfg.word_size <= 8) { + p_spi->ssptdr = *(const uint8_t*)tx_ptr; + } else { + p_spi->ssptdr = *(const uint16_t*)tx_ptr; + } +} + +uint32_t spi_pl022_read_test_output_reg(struct spi_pl022_dev_t* dev) +{ + struct spi_pl022_dev_test_reg_map_t* p_spi = + (struct spi_pl022_dev_test_reg_map_t*) + (dev->cfg->base + SPI_PL022_TEST_REG_BASE); + + return p_spi->sspitop; +} + diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h new file mode 100644 index 0000000000..49864bb445 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/spi_pl022_drv.h @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file spi_pl022_drv.h + * \brief Generic driver for ARM SPI PL022. + */ + +#ifndef __SPI_PL022_DRV_H__ +#define __SPI_PL022_DRV_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Frame format */ +#define SPI_PL022_CFG_FRF_MOT 0 +#define SPI_PL022_CFG_FRF_TI 1 +#define SPI_PL022_CFG_FRF_MICROWIRE 2 + +enum spi_pl022_mode_select_t { + SPI_PL022_MASTER_SELECT = 0, + SPI_PL022_SLAVE_SELECT, +}; + +enum spi_pl022_slave_output_mode_t { + SPI_PL022_SLAVE_OUTPUT_EN = 0, + SPI_PL022_SLAVE_OUTPUT_DIS, +}; + +enum spi_pl022_loopback_select_t { + SPI_PL022_LOOPBACK_MODE_DIS = 0, + SPI_PL022_LOOPBACK_MODE_EN, +}; + +struct spi_pl022_periphid_t { + uint32_t partNumber; + uint32_t designerID; + uint32_t revision; + uint32_t configuration; +}; + +struct spi_pl022_primecell_id_t { + uint8_t cellid0; + uint8_t cellid1; + uint8_t cellid2; + uint8_t cellid3; +}; + +/* ARM SPI PL022 device control configuration structure */ +struct spi_pl022_ctrl_cfg_t { + enum spi_pl022_mode_select_t spi_mode; /*!< master-slave */ + uint8_t frame_format; /*!< frame format bitmap + clock phase [7] polarity [6] + reserved [5:3] + frame_format [1:0] */ + uint8_t word_size; /*!< value 4 to 16 */ + uint8_t reserved[2]; /*!< to keep 32 bits aligned */ + uint32_t bit_rate; /*!< required bit rate */ +}; + +/* ARM SPI PL022 device configuration structure */ +struct spi_pl022_dev_cfg_t { + const uint32_t base; /*!< SPI PL022 base address */ + const struct spi_pl022_ctrl_cfg_t default_ctrl_cfg; /*!< Default SPI + configuration */ +}; + +/* ARM SPI PL022 device data structure */ +struct spi_pl022_dev_data_t { + uint32_t state; /*!< SPI driver state */ + uint32_t sys_clk; /*!< System clock frequency */ + struct spi_pl022_ctrl_cfg_t ctrl_cfg; /*!< SPI control + configuration data */ +}; + +/* ARM SPI PL022 device structure */ +struct spi_pl022_dev_t { + const struct spi_pl022_dev_cfg_t* const cfg; /*!< SPI driver + configuration */ + struct spi_pl022_dev_data_t* const data; /*!< SPI driver data */ +}; + +enum spi_pl022_error_t { + SPI_PL022_ERR_NONE = 0, /*!< No error */ + SPI_PL022_ERR_INVALID_ARGS, /*!< Invalid input arguments */ + SPI_PL022_ERR_NOT_INIT, /*!< SPI driver is not initialized */ + SPI_PL022_ERR_NO_TX, /*!< SPI transm FIFO full */ + SPI_PL022_ERR_NO_RX, /*!< SPI receive FIFO empty */ + SPI_PL022_ERR_BAD_CONFIG, /*!< Bad SPI configuration */ +}; + + +/* Interrupt mask defines for the interrupt APIs */ + +/* Receive Overrun Interrupt */ +#define SPI_PL022_RX_OR_INTR_POS 0 +#define SPI_PL022_RX_OR_INTR_MSK (0x1ul< #include "spi_api.h" -#include "spi_def.h" -#include "cmsis.h" #include "pinmap.h" #include "mbed_error.h" #include "mbed_wait_api.h" +#include "platform_devices.h" -#define SPI_PL022_MIN_SSPCPSR_VALUE 2 -#define SPI_PL022_MAX_SSPCPSR_VALUE 254 -#define SPI_PL022_MAX_SRC_VALUE 255 -#define SPI_PL022_SSPCR0_SCR_POS 8 -#define SPI_PL022_SSPCR0_SCR_MSK (0xFFul<spi = &SPI0_PL022_DEV; + return 0; +#endif /* ARM_SPI0 */ +#ifdef ARM_SPI1 + case SPI_1: + obj->spi = &SPI1_PL022_DEV; + return 0; +#endif /* ARM_SPI1 */ +#ifdef ARM_SPI2 + case SPI_2: + obj->spi = &SPI2_PL022_DEV; + return 0; +#endif /* ARM_SPI2 */ +#ifdef ARM_SPI3 + case SPI_3: + obj->spi = &SPI3_PL022_DEV; + return 0; +#endif /* ARM_SPI3 */ +#ifdef ARM_SPI4 + case SPI_4: + obj->spi = &SPI4_PL022_DEV; + return 0; +#endif /* ARM_SPI4 */ + default: + error("Can not assign valid SPI peripheral to the pins given"); + return 1; + } +} void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) { - /* Determine the SPI to use */ - SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI); - SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO); - SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK); - SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL); - SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso); - SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel); - - obj->spi = (MPS2_SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl); - if ((int)obj->spi == NC) { - error("SPI pinout mapping failed"); + if (spi_fill_object(obj, mosi, miso, sclk, ssel) != 0) { + return; } - /* Enable power and clocking */ - switch ((int)obj->spi) { - case SPI_0: - obj->spi->CR1 = 0; - obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8; - obj->spi->CPSR = SSP_CPSR_DFLT; - obj->spi->IMSC = 0x8; - obj->spi->DMACR = 0; - obj->spi->CR1 = SSP_CR1_SSE_Msk; - obj->spi->ICR = 0x3; - break; - case SPI_1: /* Configure SSP used for LCD */ - obj->spi->CR1 = 0; /* Synchronous serial port disable */ - obj->spi->DMACR = 0; /* Disable FIFO DMA */ - obj->spi->IMSC = 0; /* Mask all FIFO/IRQ interrupts */ - obj->spi->ICR = ((1ul << 0) | /* Clear SSPRORINTR interrupt */ - (1ul << 1) ); /* Clear SSPRTINTR interrupt */ - obj->spi->CR0 = ((7ul << 0) | /* 8 bit data size */ - (0ul << 4) | /* Motorola frame format */ - (0ul << 6) | /* CPOL = 0 */ - (0ul << 7) | /* CPHA = 0 */ - (1ul << 8) ); /* Set serial clock rate */ - obj->spi->CPSR = (2ul << 0); /* set SSP clk to 6MHz (6.6MHz max) */ - obj->spi->CR1 = ((1ul << 1) | /* Synchronous serial port enable */ - (0ul << 2) ); /* Device configured as master */ - break; - case SPI_2: /* Shield ADC SPI */ - case SPI_3: /* Shield 0 SPI */ - case SPI_4: /* Shield 1 SPI */ - obj->spi->CR1 = 0; - obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8; - obj->spi->CPSR = SSP_CPSR_DFLT; - obj->spi->IMSC = 0x8; - obj->spi->DMACR = 0; - obj->spi->CR1 = SSP_CR1_SSE_Msk; - obj->spi->ICR = 0x3; - /* Set pin function as an alt-function */ - if (mosi != NC) { - pin_function(mosi, ALTERNATE_FUNC); - } - if (miso != NC) { - pin_function(miso, ALTERNATE_FUNC); - } - if (sclk != NC) { - pin_function(sclk, ALTERNATE_FUNC); - } - if (ssel != NC) { - pin_function(ssel, ALTERNATE_FUNC); - } - break; + (void)spi_pl022_init(obj->spi, SystemCoreClock); + + /* + * If the pins are not linked to a GPIO, + * pin_function will have no effect. + * Mosi, miso and ssel pins are allowed to be NC, + * call pin_function only if they are connected + */ + if (mosi != NC) { + pin_function(mosi, pinmap_function(mosi, PinMap_SPI_MOSI)); } - - /* Set default format and frequency */ - if (ssel == NC) { - spi_format(obj, 8, 0, 0); /* 8 bits, mode 0, master */ - } else { - spi_format(obj, 8, 0, 1); /* 8 bits, mode 0, slave */ + if (miso != NC) { + pin_function(miso, pinmap_function(miso, PinMap_SPI_MISO)); } - - /* Default SPI frequency */ - spi_frequency(obj, 1000000); - - /* Enable the ssp channel */ - ssp_enable(obj); + if (ssel != NC) { + pin_function(ssel, pinmap_function(ssel, PinMap_SPI_SSEL)); + } + pin_function(sclk, pinmap_function(sclk, PinMap_SPI_SCLK)); } void spi_free(spi_t *obj) { - error("SPI free error"); + /* No need to implement free function, this API is intentionally blank */ } void spi_format(spi_t *obj, int bits, int mode, int slave) { - ssp_disable(obj); - if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) { + uint32_t polarity, phase, frame_format; + struct spi_pl022_ctrl_cfg_t ctrl_cfg; + + if (!(bits >= SPI_BITS_MIN_VALUE && bits <= SPI_BITS_MAX_VALUE) || + (mode & ~SPI_MODE_MAX_VALUE_MSK)) { error("SPI format error"); + return; } - int polarity = (mode & 0x2) ? 1 : 0; - int phase = (mode & 0x1) ? 1 : 0; + spi_pl022_dev_disable(obj->spi); + if (spi_pl022_get_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) { + error("SPI not initialized"); + return; + }; - // set it up - int DSS = bits - 1; /* DSS (data select size) */ - int SPO = (polarity) ? 1 : 0; /* SPO - clock out polarity */ - int SPH = (phase) ? 1 : 0; /* SPH - clock out phase */ + polarity = (mode & SPI_MODE_POLARITY_BIT_MSK) ? 1u : 0; + phase = (mode & SPI_MODE_PHASE_BIT_MSK) ? 1u : 0; + frame_format = (SPI_PL022_CFG_FRF_MOT << 0 | + polarity << 6 | + phase << 7); - int FRF = 0; /* FRF (frame format) = SPI */ - uint32_t tmp = obj->spi->CR0; - tmp &= ~(0xFFFF); - tmp |= DSS << 0 - | FRF << 4 - | SPO << 6 - | SPH << 7; - obj->spi->CR0 = tmp; + ctrl_cfg.frame_format = (uint8_t) frame_format; + ctrl_cfg.word_size = (uint8_t) bits; + ctrl_cfg.spi_mode = + slave ? SPI_PL022_SLAVE_SELECT : SPI_PL022_MASTER_SELECT; - tmp = obj->spi->CR1; - tmp &= ~(0xD); - tmp |= 0 << 0 /* LBM - loop back mode - off */ - | ((slave) ? 1 : 0) << 2 /* MS - master slave mode, 1 = slave */ - | 0 << 3; /* SOD - slave output disable - na */ - obj->spi->CR1 = tmp; + if (spi_pl022_set_ctrl_cfg(obj->spi, &ctrl_cfg) != 0) { + error("SPI configuration failed"); + } - ssp_enable(obj); + spi_pl022_dev_enable(obj->spi); } void spi_frequency(spi_t *obj, int hz) { - uint32_t clkps_dvsr, scr; - uint32_t sys_clk = SystemCoreClock; + spi_pl022_dev_disable(obj->spi); - for(clkps_dvsr = SPI_PL022_MIN_SSPCPSR_VALUE; - clkps_dvsr <= SPI_PL022_MAX_SSPCPSR_VALUE; clkps_dvsr += 2) { - - /* Calculate clock rate based on the new clock prescale divisor */ - scr = (sys_clk / (clkps_dvsr * hz)) - 1; - - /* Checks if it can be supported by the divider */ - if (scr <= SPI_PL022_MAX_SRC_VALUE) { - ssp_disable(obj); - obj->spi->CPSR = clkps_dvsr; - obj->spi->CR0 &= ~SPI_PL022_SSPCR0_SCR_MSK; - obj->spi->CR0 |= (scr << SPI_PL022_SSPCR0_SCR_POS); - ssp_enable(obj); - return; - } + obj->spi->data->ctrl_cfg.bit_rate = hz; + if (spi_pl022_set_sys_clk(obj->spi, SystemCoreClock) != 0) { + error("SPI frequency config failed"); } - error("Couldn't setup requested SPI frequency %dHz", hz); -} - -static inline int ssp_disable(spi_t *obj) -{ - return obj->spi->CR1 &= ~(1 << 1); -} - -static inline int ssp_enable(spi_t *obj) -{ - return obj->spi->CR1 |= SSP_CR1_SSE_Msk; -} - -static inline int ssp_readable(spi_t *obj) -{ - return obj->spi->SR & (1 << 2); -} - -static inline int ssp_writeable(spi_t *obj) -{ - return obj->spi->SR & SSP_SR_BSY_Msk; -} - -static inline void ssp_write(spi_t *obj, int value) -{ - obj->spi->DR = value; - while (ssp_writeable(obj)); -} -static inline int ssp_read(spi_t *obj) -{ - int read_DR = obj->spi->DR; - return read_DR; -} - -static inline int ssp_busy(spi_t *obj) -{ - return (obj->spi->SR & (1 << 4)) ? (1) : (0); + spi_pl022_dev_enable(obj->spi); } int spi_master_write(spi_t *obj, int value) { - ssp_write(obj, value); - while (obj->spi->SR & SSP_SR_BSY_Msk); /* Wait for send to finish */ - return (ssp_read(obj)); + int32_t rx_data = 0; + uint32_t size = 1; + + if(obj->spi->data->ctrl_cfg.word_size > 8) { + size = 2; + } + + if (spi_pl022_txrx_blocking(obj->spi, &value, &size, &rx_data, &size) ) { + return 0; + } + + return rx_data; } int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, char write_fill) { - int total = (tx_length > rx_length) ? tx_length : rx_length; - char out, in; - - for (int i = 0; i < total; i++) { - out = (i < tx_length) ? tx_buffer[i] : write_fill; - in = spi_master_write(obj, out); - if (i < rx_length) { - rx_buffer[i] = in; - } + if (spi_pl022_txrx_blocking(obj->spi, tx_buffer, (uint32_t*)&tx_length, + rx_buffer, (uint32_t*)&rx_length)) { + return 0; } - return total; + return ((tx_length > rx_length) ? tx_length : rx_length); } int spi_slave_receive(spi_t *obj) { - return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0); + int32_t status = spi_pl022_get_status(obj->spi); + /* Rx FIFO not empty and device not busy */ + int32_t ret = ((status & SPI_PL022_SSPSR_RNE_MSK) && + !(status & SPI_PL022_SSPSR_BSY_MSK)); + return ret; +} + +uint8_t spi_get_module(spi_t *obj) +{ + if (obj->spi == &SPI0_PL022_DEV) { + return SPI_0; + } else if (obj->spi == &SPI1_PL022_DEV) { + return SPI_1; + } else if (obj->spi == &SPI2_PL022_DEV) { + return SPI_2; + } else if (obj->spi == &SPI3_PL022_DEV) { + return SPI_3; + } else if (obj->spi == &SPI4_PL022_DEV) { + return SPI_4; + } else { + error("SPI object is not initialized"); + return (SPI_NC); + } } int spi_slave_read(spi_t *obj) { - return obj->spi->DR; + while(spi_slave_receive(obj) == 0) {}; + return spi_pl022_slave_read(obj->spi); } void spi_slave_write(spi_t *obj, int value) { - while (ssp_writeable(obj) == 0); - obj->spi->DR = value; + (void)spi_pl022_write(obj->spi, SPI_PL022_SLAVE_SELECT, &value); } int spi_busy(spi_t *obj) { - return ssp_busy(obj); + int32_t status = spi_pl022_get_status(obj->spi); + return (status & SPI_PL022_SSPSR_BSY_MSK); } diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h deleted file mode 100644 index ca8e450be8..0000000000 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/spi_def.h +++ /dev/null @@ -1,174 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2006-2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ---------------------------------------------------------------- - * File: spi_def.h - * Release: Version 2.0 - * ---------------------------------------------------------------- - * - * SSP interface Support - * ===================== - */ - -#define SSPCS_BASE (0x4002804C) // SSP chip select register -#define SSP_BASE (0x40020000) // SSP Prime Cell - -#define SSPCR0 ((volatile unsigned int *)(SSP_BASE + 0x00)) -#define SSPCR1 ((volatile unsigned int *)(SSP_BASE + 0x04)) -#define SSPDR ((volatile unsigned int *)(SSP_BASE + 0x08)) -#define SSPSR ((volatile unsigned int *)(SSP_BASE + 0x0C)) -#define SSPCPSR ((volatile unsigned int *)(SSP_BASE + 0x10)) -#define SSPIMSC ((volatile unsigned int *)(SSP_BASE + 0x14)) -#define SSPRIS ((volatile unsigned int *)(SSP_BASE + 0x18)) -#define SSPMIS ((volatile unsigned int *)(SSP_BASE + 0x1C)) -#define SSPICR ((volatile unsigned int *)(SSP_BASE + 0x20)) -#define SSPDMACR ((volatile unsigned int *)(SSP_BASE + 0x24)) -#define SSPCS ((volatile unsigned int *)(SSPCS_BASE)) - -// SSPCR0 Control register 0 -#define SSPCR0_SCR_DFLT 0x0300 // Serial Clock Rate (divide), default set at 3 -#define SSPCR0_SPH 0x0080 // SSPCLKOUT phase -#define SSPCR0_SPO 0x0040 // SSPCLKOUT polarity -#define SSPCR0_FRF_MOT 0x0000 // Frame format, Motorola -#define SSPCR0_DSS_8 0x0007 // Data packet size, 8bits -#define SSPCR0_DSS_16 0x000F // Data packet size, 16bits - -// SSPCR1 Control register 1 -#define SSPCR1_SOD 0x0008 // Slave Output mode Disable -#define SSPCR1_MS 0x0004 // Master or Slave mode -#define SSPCR1_SSE 0x0002 // Serial port enable -#define SSPCR1_LBM 0x0001 // Loop Back Mode - -// SSPSR Status register -#define SSPSR_BSY 0x0010 // Busy -#define SSPSR_RFF 0x0008 // Receive FIFO full -#define SSPSR_RNE 0x0004 // Receive FIFO not empty -#define SSPSR_TNF 0x0002 // Transmit FIFO not full -#define SSPSR_TFE 0x0001 // Transmit FIFO empty - -// SSPCPSR Clock prescale register -#define SSPCPSR_DFLT 0x0008 // Clock prescale (use with SCR), default set at 8 - -// SSPIMSC Interrupt mask set and clear register -#define SSPIMSC_TXIM 0x0008 // Transmit FIFO not Masked -#define SSPIMSC_RXIM 0x0004 // Receive FIFO not Masked -#define SSPIMSC_RTIM 0x0002 // Receive timeout not Masked -#define SSPIMSC_RORIM 0x0001 // Receive overrun not Masked - -// SSPRIS Raw interrupt status register -#define SSPRIS_TXRIS 0x0008 // Raw Transmit interrupt flag -#define SSPRIS_RXRIS 0x0004 // Raw Receive interrupt flag -#define SSPRIS_RTRIS 0x0002 // Raw Timemout interrupt flag -#define SSPRIS_RORRIS 0x0001 // Raw Overrun interrupt flag - -// SSPMIS Masked interrupt status register -#define SSPMIS_TXMIS 0x0008 // Masked Transmit interrupt flag -#define SSPMIS_RXMIS 0x0004 // Masked Receive interrupt flag -#define SSPMIS_RTMIS 0x0002 // Masked Timemout interrupt flag -#define SSPMIS_RORMIS 0x0001 // Masked Overrun interrupt flag - -// SSPICR Interrupt clear register -#define SSPICR_RTIC 0x0002 // Clears Timeout interrupt flag -#define SSPICR_RORIC 0x0001 // Clears Overrun interrupt flag - -// SSPDMACR DMA control register -#define SSPDMACR_TXDMAE 0x0002 // Enable Transmit FIFO DMA -#define SSPDMACR_RXDMAE 0x0001 // Enable Receive FIFO DMA - -// SPICS register (0=Chip Select low) -#define SSPCS_nCS1 0x0002 // nCS1 (SPI_nSS) - -// SPI defaults -#define SSPMAXTIME 1000 // Maximum time to wait for SSP (10*10uS) - -// EEPROM instruction set -#define EEWRSR 0x0001 // Write status -#define EEWRITE 0x0002 // Write data -#define EEREAD 0x0003 // Read data -#define EEWDI 0x0004 // Write disable -#define EEWREN 0x0006 // Write enable -#define EERDSR 0x0005 // Read status - -// EEPROM status register flags -#define EERDSR_WIP 0x0001 // Write in process -#define EERDSR_WEL 0x0002 // Write enable latch -#define EERDSR_BP0 0x0004 // Block protect 0 -#define EERDSR_BP1 0x0008 // Block protect 1 -#define EERDSR_WPEN 0x0080 // Write protect enable - - /* ---------------------------------------------------------------- - * - * Color LCD Support - * ================= - */ - -// Color LCD Controller Internal Register addresses -#define LSSPCS_BASE (0x4002804C) // LSSP chip select register -#define LSSP_BASE (0x40021000) // LSSP Prime Cell - -#define LSSPCR0 ((volatile unsigned int *)(LSSP_BASE + 0x00)) -#define LSSPCR1 ((volatile unsigned int *)(LSSP_BASE + 0x04)) -#define LSSPDR ((volatile unsigned int *)(LSSP_BASE + 0x08)) -#define LSSPSR ((volatile unsigned int *)(LSSP_BASE + 0x0C)) -#define LSSPCPSR ((volatile unsigned int *)(LSSP_BASE + 0x10)) -#define LSSPIMSC ((volatile unsigned int *)(LSSP_BASE + 0x14)) -#define LSSPRIS ((volatile unsigned int *)(LSSP_BASE + 0x18)) -#define LSSPMIS ((volatile unsigned int *)(LSSP_BASE + 0x1C)) -#define LSSPICR ((volatile unsigned int *)(LSSP_BASE + 0x20)) -#define LSSPDMACR ((volatile unsigned int *)(LSSP_BASE + 0x24)) -#define LSSPCS ((volatile unsigned int *)(LSSPCS_BASE)) - -// LSSPCR0 Control register 0 -#define LSSPCR0_SCR_DFLT 0x0100 // Serial Clock Rate (divide), CLK/(CPSR*(1+SCR)) -#define LSSPCR0_SPH 0x0080 // LSSPCLKOUT phase -#define LSSPCR0_SPO 0x0040 // LSSPCLKOUT polarity -#define LSSPCR0_FRF_MOT 0x0000 // Frame format, Motorola -#define LSSPCR0_DSS_8 0x0007 // Data packet size, 8bits -#define LSSPCR0_DSS_16 0x000F // Data packet size, 16bits - -// LSSPCR1 Control register 1 -#define LSSPCR1_SOD 0x0008 // Slave Output mode Disable -#define LSSPCR1_MS 0x0004 // Master or Slave mode -#define LSSPCR1_SSE 0x0002 // Serial port enable -#define LSSPCR1_LBM 0x0001 // Loop Back Mode - -// LSSPSR Status register -#define LSSPSR_BSY 0x0010 // Busy -#define LSSPSR_RFF 0x0008 // Receive FIFO full -#define LSSPSR_RNE 0x0004 // Receive FIFO not empty -#define LSSPSR_TNF 0x0002 // Transmit FIFO not full -#define LSSPSR_TFE 0x0001 // Transmit FIFO empty - -// LSSPCPSR Clock prescale register -#define LSSPCPSR_DFLT 0x0002 // Clock prescale (use with SCR) - -// SPICS register -#define LSSPCS_nCS0 0x0001 // nCS0 (CLCD_CS) -#define LSSPCS_nCS2 0x0004 // nCS2 (CLCD_T_CS) -#define LCD_RESET 0x0008 // RESET (CLCD_RESET) -#define LCD_RS 0x0010 // RS (CLCD_RS) -#define LCD_RD 0x0020 // RD (CLCD_RD) -#define LCD_BL 0x0040 // Backlight (CLCD_BL_CTRL) - -// SPI defaults -#define LSSPMAXTIME 10000 // Maximum time to wait for LSSP (10*10uS) -#define LSPI_START (0x70) // Start byte for SPI transfer -#define LSPI_RD (0x01) // WR bit 1 within start -#define LSPI_WR (0x00) // WR bit 0 within start -#define LSPI_DATA (0x02) // RS bit 1 within start byte -#define LSPI_INDEX (0x00) // RS bit 0 within start byte - -// Screen size -#define LCD_WIDTH 320 // Screen Width (in pixels) -#define LCD_HEIGHT 240 // Screen Height (in pixels) From a79a67057587447ca8e2d752215f9d656b89b793 Mon Sep 17 00:00:00 2001 From: Avinash Mehta Date: Fri, 8 Dec 2017 17:48:23 +0000 Subject: [PATCH 4/4] CM3DS: update UART implementation This commit adds the UART driver and updates the UART HAL implementation to use this driver. It also removes legacy definitions. Change-Id: Ie8e7a7bb64c763a2d97bc66d949fab3596736bbc Signed-off-by: Avinash Mehta --- .../TARGET_CM3DS_MPS2/PeripheralNames.h | 10 +- .../TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h | 74 +-- .../TARGET_CM3DS_MPS2/device/device_cfg.h | 8 + .../device/drivers/arm_uart_drv.c | 283 ++++++++++ .../device/drivers/arm_uart_drv.h | 230 +++++++++ .../device/platform_devices.c | 61 +++ .../device/platform_devices.h | 18 + .../TARGET_CM3DS_MPS2/objects.h | 6 +- .../TARGET_CM3DS_MPS2/serial_api.c | 486 +++++++++--------- 9 files changed, 846 insertions(+), 330 deletions(-) mode change 100644 => 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h mode change 100644 => 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.c create mode 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.h mode change 100644 => 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h mode change 100644 => 100755 targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h old mode 100644 new mode 100755 index fd6d842625..5db4fc14d1 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/PeripheralNames.h @@ -23,11 +23,11 @@ extern "C" { #endif typedef enum { - UART_0 = (int)CMSDK_UART0_BASE, /* MCC UART */ - UART_1 = (int)CMSDK_UART1_BASE, /* MPS2+ UART */ - UART_2 = (int)CMSDK_UART2_BASE, /* Shield 0 UART */ - UART_3 = (int)CMSDK_UART3_BASE, /* Shield 1 UART */ - UART_4 = (int)CMSDK_UART4_BASE /* Shield BT UART */ + UART_0 = 0, /* MCC UART */ + UART_1, /* MPS2+ UART */ + UART_2, /* Shield 0 UART */ + UART_3, /* Shield 1 UART */ + UART_4 /* Shield BT UART */ } UARTName; typedef enum { diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h old mode 100644 new mode 100755 index ebbd7b02a8..a9bb5d828c --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/CMSDK_CM3DS.h @@ -135,73 +135,6 @@ typedef enum IRQn #warning Not supported compiler type #endif -/*------------- Universal Asynchronous Receiver Transmitter (UART) -----------*/ -typedef struct -{ - __IO uint32_t DATA; /* Offset: 0x000 (R/W) Data Register */ - __IO uint32_t STATE; /* Offset: 0x004 (R/W) Status Register */ - __IO uint32_t CTRL; /* Offset: 0x008 (R/W) Control Register */ - union { - __I uint32_t INTSTATUS; /* Offset: 0x00C (R/ ) Interrupt Status Register */ - __O uint32_t INTCLEAR; /* Offset: 0x00C ( /W) Interrupt Clear Register */ - }; - __IO uint32_t BAUDDIV; /* Offset: 0x010 (R/W) Baudrate Divider Register */ - -} CMSDK_UART_TypeDef; - -/* CMSDK_UART DATA Register Definitions */ - -#define CMSDK_UART_DATA_Pos 0 /* CMSDK_UART_DATA_Pos: DATA Position */ -#define CMSDK_UART_DATA_Msk (0xFFul << CMSDK_UART_DATA_Pos) /* CMSDK_UART DATA: DATA Mask */ - -#define CMSDK_UART_STATE_RXOR_Pos 3 /* CMSDK_UART STATE: RXOR Position */ -#define CMSDK_UART_STATE_RXOR_Msk (0x1ul << CMSDK_UART_STATE_RXOR_Pos) /* CMSDK_UART STATE: RXOR Mask */ - -#define CMSDK_UART_STATE_TXOR_Pos 2 /* CMSDK_UART STATE: TXOR Position */ -#define CMSDK_UART_STATE_TXOR_Msk (0x1ul << CMSDK_UART_STATE_TXOR_Pos) /* CMSDK_UART STATE: TXOR Mask */ - -#define CMSDK_UART_STATE_RXBF_Pos 1 /* CMSDK_UART STATE: RXBF Position */ -#define CMSDK_UART_STATE_RXBF_Msk (0x1ul << CMSDK_UART_STATE_RXBF_Pos) /* CMSDK_UART STATE: RXBF Mask */ - -#define CMSDK_UART_STATE_TXBF_Pos 0 /* CMSDK_UART STATE: TXBF Position */ -#define CMSDK_UART_STATE_TXBF_Msk (0x1ul << CMSDK_UART_STATE_TXBF_Pos ) /* CMSDK_UART STATE: TXBF Mask */ - -#define CMSDK_UART_CTRL_HSTM_Pos 6 /* CMSDK_UART CTRL: HSTM Position */ -#define CMSDK_UART_CTRL_HSTM_Msk (0x01ul << CMSDK_UART_CTRL_HSTM_Pos) /* CMSDK_UART CTRL: HSTM Mask */ - -#define CMSDK_UART_CTRL_RXORIRQEN_Pos 5 /* CMSDK_UART CTRL: RXORIRQEN Position */ -#define CMSDK_UART_CTRL_RXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXORIRQEN_Pos) /* CMSDK_UART CTRL: RXORIRQEN Mask */ - -#define CMSDK_UART_CTRL_TXORIRQEN_Pos 4 /* CMSDK_UART CTRL: TXORIRQEN Position */ -#define CMSDK_UART_CTRL_TXORIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXORIRQEN_Pos) /* CMSDK_UART CTRL: TXORIRQEN Mask */ - -#define CMSDK_UART_CTRL_RXIRQEN_Pos 3 /* CMSDK_UART CTRL: RXIRQEN Position */ -#define CMSDK_UART_CTRL_RXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_RXIRQEN_Pos) /* CMSDK_UART CTRL: RXIRQEN Mask */ - -#define CMSDK_UART_CTRL_TXIRQEN_Pos 2 /* CMSDK_UART CTRL: TXIRQEN Position */ -#define CMSDK_UART_CTRL_TXIRQEN_Msk (0x01ul << CMSDK_UART_CTRL_TXIRQEN_Pos) /* CMSDK_UART CTRL: TXIRQEN Mask */ - -#define CMSDK_UART_CTRL_RXEN_Pos 1 /* CMSDK_UART CTRL: RXEN Position */ -#define CMSDK_UART_CTRL_RXEN_Msk (0x01ul << CMSDK_UART_CTRL_RXEN_Pos) /* CMSDK_UART CTRL: RXEN Mask */ - -#define CMSDK_UART_CTRL_TXEN_Pos 0 /* CMSDK_UART CTRL: TXEN Position */ -#define CMSDK_UART_CTRL_TXEN_Msk (0x01ul << CMSDK_UART_CTRL_TXEN_Pos) /* CMSDK_UART CTRL: TXEN Mask */ - -#define CMSDK_UART_INTSTATUS_RXORIRQ_Pos 3 /* CMSDK_UART CTRL: RXORIRQ Position */ -#define CMSDK_UART_INTSTATUS_RXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXORIRQ_Pos) /* CMSDK_UART CTRL: RXORIRQ Mask */ - -#define CMSDK_UART_INTSTATUS_TXORIRQ_Pos 2 /* CMSDK_UART CTRL: TXORIRQ Position */ -#define CMSDK_UART_INTSTATUS_TXORIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXORIRQ_Pos) /* CMSDK_UART CTRL: TXORIRQ Mask */ - -#define CMSDK_UART_INTSTATUS_RXIRQ_Pos 1 /* CMSDK_UART CTRL: RXIRQ Position */ -#define CMSDK_UART_INTSTATUS_RXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_RXIRQ_Pos) /* CMSDK_UART CTRL: RXIRQ Mask */ - -#define CMSDK_UART_INTSTATUS_TXIRQ_Pos 0 /* CMSDK_UART CTRL: TXIRQ Position */ -#define CMSDK_UART_INTSTATUS_TXIRQ_Msk (0x01ul << CMSDK_UART_INTSTATUS_TXIRQ_Pos) /* CMSDK_UART CTRL: TXIRQ Mask */ - -#define CMSDK_UART_BAUDDIV_Pos 0 /* CMSDK_UART BAUDDIV: BAUDDIV Position */ -#define CMSDK_UART_BAUDDIV_Msk (0xFFFFFul << CMSDK_UART_BAUDDIV_Pos) /* CMSDK_UART BAUDDIV: BAUDDIV Mask */ - /*------------- System Control (SYSCON) --------------------------------------*/ typedef struct { @@ -408,11 +341,6 @@ typedef struct /* ================ Peripheral declaration ================ */ /* ================================================================================ */ -#define CMSDK_UART0 ((CMSDK_UART_TypeDef *) CMSDK_UART0_BASE ) -#define CMSDK_UART1 ((CMSDK_UART_TypeDef *) CMSDK_UART1_BASE ) -#define CMSDK_UART2 ((CMSDK_UART_TypeDef *) CMSDK_UART2_BASE ) -#define CMSDK_UART3 ((CMSDK_UART_TypeDef *) CMSDK_UART3_BASE ) -#define CMSDK_UART4 ((CMSDK_UART_TypeDef *) CMSDK_UART4_BASE ) #define CMSDK_RTC ((CMSDK_RTC_TypeDef *) CMSDK_RTC_BASE ) #define CMSDK_WATCHDOG ((CMSDK_WATCHDOG_TypeDef *) CMSDK_WATCHDOG_BASE ) #define CMSDK_SYSCON ((CMSDK_SYSCON_TypeDef *) CMSDK_SYSCTRL_BASE ) @@ -421,4 +349,4 @@ typedef struct } #endif -#endif /* CMSDK_BEETLE_H */ +#endif /* CMSDK_CM3DS_H */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h index 816c08eab5..dd39c21a0a 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/device_cfg.h @@ -50,4 +50,12 @@ #define ARM_SPI3 #define ARM_SPI4 +/* ARM UART */ +#define DEFAULT_UART_BAUDRATE 9600 +#define ARM_UART0 +#define ARM_UART1 +#define ARM_UART2 +#define ARM_UART3 +#define ARM_UART4 + #endif /* __ARM_LTD_DEVICE_CFG_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.c new file mode 100755 index 0000000000..dea31c586d --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "arm_uart_drv.h" + +#include + +/* UART register map structure */ +struct _arm_uart_reg_map_t { + volatile uint32_t data; /* Offset: 0x000 (R/W) data register */ + volatile uint32_t state; /* Offset: 0x004 (R/W) status register */ + volatile uint32_t ctrl; /* Offset: 0x008 (R/W) control register */ + union { + volatile uint32_t intrstatus; /* Offset: 0x00c (R/ ) interrupt status + * register */ + volatile uint32_t intrclear; /* Offset: 0x00c ( /W) interrupt clear + * register */ + }intr_reg; + volatile uint32_t bauddiv; /* Offset: 0x010 (R/W) Baudrate divider + * register */ +}; + +/* CTRL Register */ +#define ARM_UART_TX_EN (1ul << 0) +#define ARM_UART_RX_EN (1ul << 1) +#define ARM_UART_TX_INTR_EN (1ul << 2) +#define ARM_UART_RX_INTR_EN (1ul << 3) + +/* STATE Register */ +#define ARM_UART_TX_BF (1ul << 0) +#define ARM_UART_RX_BF (1ul << 1) + +/* INTSTATUS Register */ +#define ARM_UART_TX_INTR (1ul << 0) +#define ARM_UART_RX_INTR (1ul << 1) + +/* UART state definitions */ +#define ARM_UART_INITIALIZED (1ul << 0) + +enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev, + uint32_t system_clk) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + if(system_clk == 0) { + return ARM_UART_ERR_INVALID_ARG; + } + + /* Sets baudrate and system clock */ + dev->data->system_clk = system_clk; + dev->data->baudrate = dev->cfg->default_baudrate; + + /* Sets baudrate */ + p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate); + + /* Enables receiver and transmitter */ + p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN; + + dev->data->state = ARM_UART_INITIALIZED; + + return ARM_UART_ERR_NONE; +} + +enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev, + uint32_t baudrate) +{ + uint32_t bauddiv; + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(baudrate == 0) { + return ARM_UART_ERR_INVALID_BAUD; + } + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return ARM_UART_ERR_NOT_INIT; + } + + /* Sets baudrate */ + bauddiv = (dev->data->system_clk / baudrate); + dev->data->baudrate = baudrate; + + /* Minimum bauddiv value */ + if(bauddiv < 16) { + return ARM_UART_ERR_INVALID_BAUD; + } + + p_uart->bauddiv = bauddiv; + + return ARM_UART_ERR_NONE; +} + +uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev) +{ + return dev->data->baudrate; +} + +enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev, + uint32_t system_clk) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(system_clk == 0) { + return ARM_UART_ERR_INVALID_ARG; + } + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return ARM_UART_ERR_NOT_INIT; + } + + /* Sets system clock */ + dev->data->system_clk = system_clk; + + /* Updates baudrate divider */ + p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate); + + /* Enables receiver and transmitter */ + return ARM_UART_ERR_NONE; +} + +enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(!(p_uart->state & ARM_UART_RX_BF)) { + return ARM_UART_ERR_NOT_READY; + } + + /* Reads data */ + *byte = (uint8_t)p_uart->data; + + return ARM_UART_ERR_NONE; +} + +enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(p_uart->state & ARM_UART_TX_BF) { + return ARM_UART_ERR_NOT_READY; + } + + /* Sends data */ + p_uart->data = byte; + + return ARM_UART_ERR_NONE; +} + +enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return ARM_UART_ERR_NOT_INIT; + } + + p_uart->ctrl |= ARM_UART_TX_INTR_EN; + + return ARM_UART_ERR_NONE; +} + +void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(dev->data->state & ARM_UART_INITIALIZED ) { + p_uart->ctrl &= ~ARM_UART_TX_INTR_EN; + } +} + +uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return 0; + } + + return !(p_uart->state & ARM_UART_TX_BF); +} + +enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return ARM_UART_ERR_NOT_INIT; + } + + p_uart->ctrl |= ARM_UART_RX_INTR_EN; + + return ARM_UART_ERR_NONE; +} + +void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(dev->data->state & ARM_UART_INITIALIZED) { + p_uart->ctrl &= ~ARM_UART_RX_INTR_EN; + } +} + +uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(!(dev->data->state & ARM_UART_INITIALIZED)) { + return 0; + } + + return (p_uart->state & ARM_UART_RX_BF); +} + +void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev, + enum arm_uart_irq_t irq) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + if(dev->data->state & ARM_UART_INITIALIZED) { + /* Clears pending interrupts */ + switch(irq) { + case ARM_UART_IRQ_RX: + p_uart->intr_reg.intrclear = ARM_UART_RX_INTR; + break; + case ARM_UART_IRQ_TX: + p_uart->intr_reg.intrclear = ARM_UART_TX_INTR; + break; + case ARM_UART_IRQ_COMBINED: + p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR); + break; + case ARM_UART_IRQ_NONE: + break; + /* default: not defined to force all cases to be handled */ + } + } +} + +enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev) +{ + struct _arm_uart_reg_map_t* p_uart = + (struct _arm_uart_reg_map_t*)dev->cfg->base; + + + if(dev->data->state & ARM_UART_INITIALIZED) { + switch(p_uart->intr_reg.intrstatus) { + case ARM_UART_TX_INTR: + return ARM_UART_IRQ_TX; + break; + case ARM_UART_RX_INTR: + return ARM_UART_IRQ_RX; + break; + case ARM_UART_TX_INTR | ARM_UART_RX_INTR: + return ARM_UART_IRQ_COMBINED; + break; + /* default: not defined to force all cases to be handled */ + } + } + return ARM_UART_IRQ_NONE; +} diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.h new file mode 100755 index 0000000000..59ad29eb52 --- /dev/null +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/drivers/arm_uart_drv.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2016-2018 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file arm_uart_drv.h + * \brief Generic driver for ARM UART. + */ + +#ifndef __ARM_UART_DRV_H__ +#define __ARM_UART_DRV_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ARM UART device configuration structure */ +struct arm_uart_dev_cfg_t { + const uint32_t base; /*!< UART base address */ + const uint32_t default_baudrate; /*!< Default baudrate */ +}; + +/* ARM UART device data structure */ +struct arm_uart_dev_data_t { + uint32_t state; /*!< Indicates if the uart driver + is initialized and enabled */ + uint32_t system_clk; /*!< System clock */ + uint32_t baudrate; /*!< Baudrate */ +}; + +/* ARM UART device structure */ +struct arm_uart_dev_t { + const struct arm_uart_dev_cfg_t* const cfg; /*!< UART configuration */ + struct arm_uart_dev_data_t* const data; /*!< UART data */ +}; + +/* ARM UART enumeration types */ +enum arm_uart_error_t { + ARM_UART_ERR_NONE = 0, /*!< No error */ + ARM_UART_ERR_INVALID_ARG, /*!< Error invalid input argument */ + ARM_UART_ERR_INVALID_BAUD, /*!< Invalid baudrate */ + ARM_UART_ERR_NOT_INIT, /*!< Error UART not initialized */ + ARM_UART_ERR_NOT_READY, /*!< Error UART not ready */ +}; + +enum arm_uart_irq_t { + ARM_UART_IRQ_RX, /*!< RX interrupt source */ + ARM_UART_IRQ_TX, /*!< TX interrupt source */ + ARM_UART_IRQ_COMBINED, /*!< RX-TX combined interrupt source */ + ARM_UART_IRQ_NONE = 0xFF /*!< RX-TX combined interrupt source */ +}; + +/** + * \brief Initializes UART. It uses the default baudrate to configure + * the peripheral at this point. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] system_clk System clock used by the device. + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev, + uint32_t system_clk); + +/** + * \brief Sets the UART baudrate. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] baudrate New baudrate. + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev, + uint32_t baudrate); + +/** + * \brief Gets the UART baudrate. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return Returns the UART baudrate. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev); + +/** + * \brief Sets system clock. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] system_clk System clock used by the device. + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev, + uint32_t system_clk); +/** + * \brief Reads one byte from UART dev. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] byte Pointer to byte. + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note For better performance, this function doesn't check if dev and byte + * pointer are NULL, and if the driver is initialized. + */ +enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte); + +/** + * \brief Writes a byte to UART dev. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] byte Byte to write. + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note For better performance, this function doesn't check if dev is NULL and + * if the driver is initialized to have better performance. + */ +enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte); + +/** + * \brief Enables TX interrupt. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev); + +/** + * \brief Disables TX interrupt. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev); + +/** + * \brief Verifies if Tx is ready to send more data. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return 1 if TX is ready, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev); + +/** + * \brief Enables RX interrupt. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return Returns error code as specified in \ref arm_uart_error_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev); + +/** + * \brief Disables RX interrupt + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \note This function doesn't check if dev is NULL. + */ +void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev); + +/** + * \brief Verifies if Rx has data. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return 1 if RX has data, 0 otherwise. + * + * \note This function doesn't check if dev is NULL. + */ +uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev); + +/** + * \brief Clears UART interrupt. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * \param[in] irq IRQ source to clean \ref arm_uart_irq_t + * + * \note This function doesn't check if dev is NULL. + */ +void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev, + enum arm_uart_irq_t irq); + +/** + * \brief Returns UART interrupt status. + * + * \param[in] dev UART device struct \ref arm_uart_dev_t + * + * \return IRQ status \ref arm_uart_irq_t + * + * \note This function doesn't check if dev is NULL. + */ +enum arm_uart_irq_t arm_uart_get_interrupt_status(struct arm_uart_dev_t* dev); + +#ifdef __cplusplus +} +#endif +#endif /* __ARM_UART_DRV_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c index b3d1e0dc72..51170c9e84 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.c @@ -208,3 +208,64 @@ static struct spi_pl022_dev_data_t SPI4_PL022_DEV_DATA = { struct spi_pl022_dev_t SPI4_PL022_DEV = {&(SPI4_PL022_DEV_CFG), &(SPI4_PL022_DEV_DATA)}; #endif /* ARM_SPI4 */ + +/* ARM UART driver structures */ +#ifdef ARM_UART0 +static const struct arm_uart_dev_cfg_t ARM_UART0_DEV_CFG = { + .base = CMSDK_UART0_BASE, + .default_baudrate = DEFAULT_UART_BAUDRATE}; +static struct arm_uart_dev_data_t ARM_UART0_DEV_DATA = { + .state = 0, + .system_clk = 0, + .baudrate = 0}; +struct arm_uart_dev_t ARM_UART0_DEV = {&(ARM_UART0_DEV_CFG), + &(ARM_UART0_DEV_DATA)}; +#endif /* ARM_UART0 */ + +#ifdef ARM_UART1 +static const struct arm_uart_dev_cfg_t ARM_UART1_DEV_CFG = { + .base = CMSDK_UART1_BASE, + .default_baudrate = DEFAULT_UART_BAUDRATE}; +static struct arm_uart_dev_data_t ARM_UART1_DEV_DATA = { + .state = 0, + .system_clk = 0, + .baudrate = 0}; +struct arm_uart_dev_t ARM_UART1_DEV = {&(ARM_UART1_DEV_CFG), + &(ARM_UART1_DEV_DATA)}; +#endif /* ARM_UART1 */ + +#ifdef ARM_UART2 +static const struct arm_uart_dev_cfg_t ARM_UART2_DEV_CFG = { + .base = CMSDK_UART2_BASE, + .default_baudrate = DEFAULT_UART_BAUDRATE}; +static struct arm_uart_dev_data_t ARM_UART2_DEV_DATA = { + .state = 0, + .system_clk = 0, + .baudrate = 0}; +struct arm_uart_dev_t ARM_UART2_DEV = {&(ARM_UART2_DEV_CFG), + &(ARM_UART2_DEV_DATA)}; +#endif /* ARM_UART2 */ + +#ifdef ARM_UART3 +static const struct arm_uart_dev_cfg_t ARM_UART3_DEV_CFG = { + .base = CMSDK_UART3_BASE, + .default_baudrate = DEFAULT_UART_BAUDRATE}; +static struct arm_uart_dev_data_t ARM_UART3_DEV_DATA = { + .state = 0, + .system_clk = 0, + .baudrate = 0}; +struct arm_uart_dev_t ARM_UART3_DEV = {&(ARM_UART3_DEV_CFG), + &(ARM_UART3_DEV_DATA)}; +#endif /* ARM_UART3 */ + +#ifdef ARM_UART4 +static const struct arm_uart_dev_cfg_t ARM_UART4_DEV_CFG = { + .base = CMSDK_UART4_BASE, + .default_baudrate = DEFAULT_UART_BAUDRATE}; +static struct arm_uart_dev_data_t ARM_UART4_DEV_DATA = { + .state = 0, + .system_clk = 0, + .baudrate = 0}; +struct arm_uart_dev_t ARM_UART4_DEV = {&(ARM_UART4_DEV_CFG), + &(ARM_UART4_DEV_DATA)}; +#endif /* ARM_UART4 */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h index 361eded7bf..d6a7fb2a8a 100755 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/device/platform_devices.h @@ -24,6 +24,7 @@ #include "arm_gpio_drv.h" #include "arm_mps2_io_drv.h" #include "spi_pl022_drv.h" +#include "arm_uart_drv.h" /* ======= Defines peripheral configuration structures ======= */ @@ -77,4 +78,21 @@ extern struct spi_pl022_dev_t SPI3_PL022_DEV; extern struct spi_pl022_dev_t SPI4_PL022_DEV; #endif +/* ARM UART driver structures */ +#ifdef ARM_UART0 +extern struct arm_uart_dev_t ARM_UART0_DEV; +#endif +#ifdef ARM_UART1 +extern struct arm_uart_dev_t ARM_UART1_DEV; +#endif +#ifdef ARM_UART2 +extern struct arm_uart_dev_t ARM_UART2_DEV; +#endif +#ifdef ARM_UART3 +extern struct arm_uart_dev_t ARM_UART3_DEV; +#endif +#ifdef ARM_UART4 +extern struct arm_uart_dev_t ARM_UART4_DEV; +#endif + #endif /* __ARM_LTD_PLATFORM_DEVICES_H__ */ diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h old mode 100644 new mode 100755 index b2267a5248..57866628e0 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/objects.h @@ -47,8 +47,10 @@ struct port_s { }; struct serial_s { - CMSDK_UART_TypeDef *uart; - int index; + struct arm_uart_dev_t *uart; + UARTName index; + IRQn_Type irq_number; /* IRQ number of the RX interrupt for + this UART device */ }; struct i2c_s { diff --git a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c old mode 100644 new mode 100755 index fe1b28835a..06895656a5 --- a/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c +++ b/targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c @@ -20,174 +20,138 @@ #include #include "serial_api.h" -#include "cmsis.h" #include "pinmap.h" #include "mbed_error.h" #include "gpio_api.h" +#include "platform_devices.h" /****************************************************************************** * INITIALIZATION ******************************************************************************/ +#define STDIO_UART_NOT_INITED 0 +#define STDIO_UART_INITED 1 +#define UART_NUMBER 5 + +struct uart_irq_t { + uart_irq_handler handler; + uint32_t id; +}; + static const PinMap PinMap_UART_TX[] = { - {MCC_TX , UART_0, 0}, - {USBTX , UART_1, 0}, - {SH0_TX , UART_2, ALTERNATE_FUNC}, - {SH1_TX , UART_3, ALTERNATE_FUNC}, - {XB_TX , UART_4, ALTERNATE_FUNC}, - {NC , NC , 0} + {MCC_TX, UART_0, 0}, + {USBTX, UART_1, 0}, + {SH0_TX, UART_2, ALTERNATE_FUNC}, + {SH1_TX, UART_3, ALTERNATE_FUNC}, + {XB_TX, UART_4, ALTERNATE_FUNC}, + {NC, NC, 0} }; static const PinMap PinMap_UART_RX[] = { - {MCC_RX , UART_0, 0}, - {USBRX , UART_1, 0}, - {SH0_RX , UART_2, ALTERNATE_FUNC}, - {SH1_RX , UART_3, ALTERNATE_FUNC}, - {XB_RX , UART_4, ALTERNATE_FUNC}, - {NC , NC , 0} + {MCC_RX, UART_0, 0}, + {USBRX, UART_1, 0}, + {SH0_RX, UART_2, ALTERNATE_FUNC}, + {SH1_RX, UART_3, ALTERNATE_FUNC}, + {XB_RX, UART_4, ALTERNATE_FUNC}, + {NC, NC, 0} }; -#define UART_NUM 5 +/* Handlers registered */ +static struct uart_irq_t uart_irq[UART_NUMBER]; -static uart_irq_handler irq_handler; - -int stdio_uart_inited = 0; +/* Global variables needed for mbed */ +int stdio_uart_inited = STDIO_UART_NOT_INITED; serial_t stdio_uart; -struct serial_global_data_s { - uint32_t serial_irq_id; - gpio_t sw_rts, sw_cts; - uint8_t count, rx_irq_set_flow, rx_irq_set_api; -}; +/* + * Fill the serial_obj structure with good elements. + */ +static uint32_t fill_serial_object(struct serial_s *serial_obj, PinName tx, + PinName rx) +{ + UARTName uart_peripheral; -static struct serial_global_data_s uart_data[UART_NUM]; + if (serial_obj == NULL) { + error("serial_s structure is NULL"); + return 1; + } + + uart_peripheral = pinmap_merge(pinmap_peripheral(tx, PinMap_UART_TX), + pinmap_peripheral(rx, PinMap_UART_RX)); + + switch (uart_peripheral) { +#ifdef ARM_UART0 + case UART_0: + serial_obj->uart = &ARM_UART0_DEV; + serial_obj->index = UART_0; + serial_obj->irq_number = UART0_IRQn; + /* Fill stdio_uart global variable with these settings */ + memcpy(&stdio_uart, serial_obj, sizeof(struct serial_s)); + stdio_uart_inited = STDIO_UART_INITED; + return 0; +#endif /* ARM_UART0 */ +#ifdef ARM_UART1 + case UART_1: + serial_obj->uart = &ARM_UART1_DEV; + serial_obj->index = UART_1; + serial_obj->irq_number = UART1_IRQn; + return 0; +#endif /* ARM_UART1 */ +#ifdef ARM_UART2 + case UART_2: + serial_obj->uart = &ARM_UART2_DEV; + serial_obj->index = UART_2; + serial_obj->irq_number = UART2_IRQn; + return 0; +#endif /* ARM_UART2 */ +#ifdef ARM_UART3 + case UART_3: + serial_obj->uart = &ARM_UART3_DEV; + serial_obj->index = UART_3; + serial_obj->irq_number = UART3_IRQn; + return 0; +#endif /* ARM_UART3 */ +#ifdef ARM_UART4 + case UART_4: + serial_obj->uart = &ARM_UART4_DEV; + serial_obj->index = UART_4; + serial_obj->irq_number = UART4_IRQn; + return 0; +#endif /* ARM_UART4 */ + default: + error("can not assign a valid UART peripheral to TX and RX pins given"); + return 1; + } +} void serial_init(serial_t *obj, PinName tx, PinName rx) { - uint32_t uart_ctrl = 0; - - /* Determine the UART to use */ - UARTName uart_tx = (UARTName)pinmap_peripheral(tx, PinMap_UART_TX); - UARTName uart_rx = (UARTName)pinmap_peripheral(rx, PinMap_UART_RX); - UARTName uart = (UARTName)pinmap_merge(uart_tx, uart_rx); - - if ((int)uart == NC) { - error("Serial pinout mapping failed"); + if (fill_serial_object(obj, tx, rx) != 0) { return; } - obj->uart = (CMSDK_UART_TypeDef *)uart; - - if (tx != NC) { - uart_ctrl = 0x01; /* TX enable */ - } - if (rx != NC) { - uart_ctrl |= 0x02; /* RX enable */ - } - - switch (uart) { - case UART_0: - CMSDK_UART0->CTRL = uart_ctrl; - obj->index = 0; - break; - case UART_1: - CMSDK_UART1->CTRL = uart_ctrl; - obj->index = 1; - break; - case UART_2: - CMSDK_UART2->CTRL = 0; - obj->index = 2; - pin_function(tx, ALTERNATE_FUNC); - pin_function(rx, ALTERNATE_FUNC); - CMSDK_UART2->CTRL = uart_ctrl; - break; - case UART_3: - CMSDK_UART3->CTRL = 0; - obj->index = 3; - pin_function(tx, ALTERNATE_FUNC); - pin_function(rx, ALTERNATE_FUNC); - CMSDK_UART3->CTRL = uart_ctrl; - break; - case UART_4: - CMSDK_UART4->CTRL = 0; - obj->index = 4; - pin_function(tx, ALTERNATE_FUNC); - pin_function(rx, ALTERNATE_FUNC); - CMSDK_UART4->CTRL = uart_ctrl; - break; - } - - /* Set default baud rate and format */ - serial_baud(obj, 9600); + (void)arm_uart_init(obj->uart, SystemCoreClock); /* - * The CMSDK APB UART doesn't have support for flow control. - * Ref. DDI0479C_cortex_m_system_design_kit_r1p0_trm.pdf + * If tx and rx pins are not linked to a GPIO (like for UART0), + * pin_function will have no effect. */ - uart_data[obj->index].sw_rts.pin_number = NC; - uart_data[obj->index].sw_cts.pin_number = NC; - - if (uart == STDIO_UART) { - stdio_uart_inited = 1; - memcpy(&stdio_uart, obj, sizeof(serial_t)); - } - - /* Clear UART */ - serial_clear(obj); + pin_function(tx, pinmap_function(tx, PinMap_UART_TX)); + pin_function(rx, pinmap_function(rx, PinMap_UART_RX)); } void serial_free(serial_t *obj) { - uart_data[obj->index].serial_irq_id = 0; + uart_irq[obj->index].id = 0; + uart_irq[obj->index].handler = 0; } void serial_baud(serial_t *obj, int baudrate) { - /* - * The MPS2 has a simple divider to control the baud rate. - * The formula is: - * Baudrate = PCLK / BAUDDIV where PCLK = SystemCoreClock and - * BAUDDIV is the desire baudrate - * - * So, if the desired baud rate is 9600 the calculation will be: - * Baudrate = SystemCoreClock / 9600; - */ - - /* Check to see if minimum baud value entered */ - int baudrate_div = 0; - - if (baudrate == 0) { - error("Invalid baudrate value"); - return; + if (arm_uart_set_baudrate(obj->uart, (uint32_t)baudrate) != + ARM_UART_ERR_NONE) { + error("Invalid baudrate value or uart not initialized"); } - - baudrate_div = SystemCoreClock / baudrate; - - if (baudrate >= 16) { - switch ((int)obj->uart) { - case UART_0: - CMSDK_UART0->BAUDDIV = baudrate_div; - break; - case UART_1: - CMSDK_UART1->BAUDDIV = baudrate_div; - break; - case UART_2: - CMSDK_UART2->BAUDDIV = baudrate_div; - break; - case UART_3: - CMSDK_UART3->BAUDDIV = baudrate_div; - break; - case UART_4: - CMSDK_UART4->BAUDDIV = baudrate_div; - break; - default: - error("Invalid uart object"); - break; - } - } else { - error("Invalid baudrate value"); - } - } void serial_format(serial_t *obj, int data_bits, @@ -204,138 +168,160 @@ void serial_format(serial_t *obj, int data_bits, /****************************************************************************** * INTERRUPTS HANDLING ******************************************************************************/ -static inline void uart_irq(uint32_t intstatus, uint32_t index, - CMSDK_UART_TypeDef *puart) +#ifdef ARM_UART0 +void UART0_IRQHandler() { - SerialIrq irq_type; - - switch (intstatus) { - case 1: - irq_type = TxIrq; + enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART0_DEV); + arm_uart_clear_interrupt(&ARM_UART0_DEV, irq); + if(uart_irq[UART_0].handler) { + switch(irq) { + case ARM_UART_IRQ_RX: + uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq); break; - case 2: - irq_type = RxIrq; + case ARM_UART_IRQ_TX: + uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq); break; + case ARM_UART_IRQ_COMBINED: + uart_irq[UART_0].handler(uart_irq[UART_0].id, RxIrq); + uart_irq[UART_0].handler(uart_irq[UART_0].id, TxIrq); + break; + case ARM_UART_IRQ_NONE: default: - return; - } - - if ((RxIrq == irq_type) && (NC != uart_data[index].sw_rts.pin_number)) { - gpio_write(&uart_data[index].sw_rts, 1); - /* Disable interrupt if it wasn't enabled by the application */ - if (!uart_data[index].rx_irq_set_api) { - /* Disable Rx interrupt */ - puart->CTRL &= ~(CMSDK_UART_CTRL_RXIRQEN_Msk); + break; } } +} +#endif /* ARM_UART0 */ - if (uart_data[index].serial_irq_id != 0) { - if ((irq_type != RxIrq) || (uart_data[index].rx_irq_set_api)) { - irq_handler(uart_data[index].serial_irq_id, irq_type); +#ifdef ARM_UART1 +void UART1_IRQHandler() +{ + enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART1_DEV); + arm_uart_clear_interrupt(&ARM_UART1_DEV, irq); + if(uart_irq[UART_1].handler) { + switch(irq) { + case ARM_UART_IRQ_RX: + uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq); + break; + case ARM_UART_IRQ_TX: + uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq); + break; + case ARM_UART_IRQ_COMBINED: + uart_irq[UART_1].handler(uart_irq[UART_1].id, RxIrq); + uart_irq[UART_1].handler(uart_irq[UART_1].id, TxIrq); + break; + case ARM_UART_IRQ_NONE: + default: + break; } } +} +#endif /* ARM_UART1 */ - if (irq_type == TxIrq) { - /* Clear the TX interrupt Flag */ - puart->INTCLEAR |= 0x01; - } else { - /* Clear the Rx interupt Flag */ - puart->INTCLEAR |= 0x02; +#ifdef ARM_UART2 +void UART2_IRQHandler() +{ + enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART2_DEV); + arm_uart_clear_interrupt(&ARM_UART2_DEV, irq); + if(uart_irq[UART_2].handler) { + switch(irq) { + case ARM_UART_IRQ_RX: + uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq); + break; + case ARM_UART_IRQ_TX: + uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq); + break; + case ARM_UART_IRQ_COMBINED: + uart_irq[UART_2].handler(uart_irq[UART_2].id, RxIrq); + uart_irq[UART_2].handler(uart_irq[UART_2].id, TxIrq); + break; + case ARM_UART_IRQ_NONE: + default: + break; + } } } +#endif /* ARM_UART2 */ -void uart0_irq() +#ifdef ARM_UART3 +void UART3_IRQHandler() { - uart_irq(CMSDK_UART0->INTSTATUS & 0x3, 0, (CMSDK_UART_TypeDef*)CMSDK_UART0); + enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART3_DEV); + arm_uart_clear_interrupt(&ARM_UART3_DEV, irq); + if(uart_irq[UART_3].handler) { + switch(irq) { + case ARM_UART_IRQ_RX: + uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq); + break; + case ARM_UART_IRQ_TX: + uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq); + break; + case ARM_UART_IRQ_COMBINED: + uart_irq[UART_3].handler(uart_irq[UART_3].id, RxIrq); + uart_irq[UART_3].handler(uart_irq[UART_3].id, TxIrq); + break; + case ARM_UART_IRQ_NONE: + default: + break; + } + } } +#endif /* ARM_UART3 */ -void uart1_irq() +#ifdef ARM_UART4 +void UART4_IRQHandler() { - uart_irq(CMSDK_UART1->INTSTATUS & 0x3, 1, (CMSDK_UART_TypeDef*)CMSDK_UART1); -} - -void uart2_irq() -{ - uart_irq(CMSDK_UART2->INTSTATUS & 0x3, 2, (CMSDK_UART_TypeDef*)CMSDK_UART2); -} - -void uart3_irq() { - uart_irq(CMSDK_UART3->INTSTATUS & 0x3, 3, (CMSDK_UART_TypeDef*)CMSDK_UART3); -} - -void uart4_irq() { - uart_irq(CMSDK_UART4->INTSTATUS & 0x3, 4, (CMSDK_UART_TypeDef*)CMSDK_UART4); + enum arm_uart_irq_t irq = arm_uart_get_interrupt_status(&ARM_UART4_DEV); + arm_uart_clear_interrupt(&ARM_UART4_DEV, irq); + if(uart_irq[UART_4].handler) { + switch(irq) { + case ARM_UART_IRQ_RX: + uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq); + break; + case ARM_UART_IRQ_TX: + uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq); + break; + case ARM_UART_IRQ_COMBINED: + uart_irq[UART_4].handler(uart_irq[UART_4].id, RxIrq); + uart_irq[UART_4].handler(uart_irq[UART_4].id, TxIrq); + break; + case ARM_UART_IRQ_NONE: + default: + break; + } + } } +#endif /* ARM_UART4 */ void serial_irq_handler(serial_t *obj, uart_irq_handler handler, uint32_t id) { - irq_handler = handler; - uart_data[obj->index].serial_irq_id = id; -} - -static void serial_irq_set_internal(serial_t *obj, SerialIrq irq, uint32_t enable) -{ - - IRQn_Type irq_n = (IRQn_Type)0; - uint32_t vector = 0; - - switch ((int)obj->uart) { - case UART_0: - irq_n = UART0_IRQn; - vector = (uint32_t)&uart0_irq; - break; - case UART_1: - irq_n = UART1_IRQn; - vector = (uint32_t)&uart1_irq; - break; - case UART_2: - irq_n = UART2_IRQn; - vector = (uint32_t)&uart2_irq; - break; - case UART_3: - irq_n = UART3_IRQn; - vector = (uint32_t)&uart3_irq; - break; - case UART_4: - irq_n = UART4_IRQn; - vector = (uint32_t)&uart4_irq; - break; - } - - if (enable) { - if (irq == TxIrq) { - /* Set TX interrupt enable in CTRL REG */ - obj->uart->CTRL |= CMSDK_UART_CTRL_TXIRQEN_Msk; - } else { - /* Set Rx interrupt on in CTRL REG */ - obj->uart->CTRL |= CMSDK_UART_CTRL_RXIRQEN_Msk; - } - NVIC_SetVector(irq_n, vector); - NVIC_EnableIRQ(irq_n); - } else if ((irq == TxIrq) || - (uart_data[obj->index].rx_irq_set_api - + uart_data[obj->index].rx_irq_set_flow == 0)) { - /* Disable IRQ */ - int all_disabled = 0; - SerialIrq other_irq = (irq == RxIrq) ? (TxIrq) : (RxIrq); - - obj->uart->CTRL &= ~(1 << (irq + 2)); - - all_disabled = (obj->uart->CTRL & (1 << (other_irq + 2))) == 0; - - if (all_disabled) { - NVIC_DisableIRQ(irq_n); - } - } + uart_irq[obj->index].handler = handler; + uart_irq[obj->index].id = id; } void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) { - if (RxIrq == irq) { - uart_data[obj->index].rx_irq_set_api = enable; + switch (irq) { + case RxIrq: + if (enable) { + NVIC_EnableIRQ(obj->irq_number); + (void)arm_uart_irq_rx_enable(obj->uart); + } else { + arm_uart_irq_rx_disable(obj->uart); + NVIC_DisableIRQ(obj->irq_number); + } + break; + case TxIrq: + if (enable) { + NVIC_EnableIRQ(obj->irq_number); + (void)arm_uart_irq_tx_enable(obj->uart); + } else { + arm_uart_irq_tx_disable(obj->uart); + NVIC_DisableIRQ(obj->irq_number); + } + break; } - - serial_irq_set_internal(obj, irq, enable); + /* default: not added to force to cover all enumeration cases */ } /****************************************************************************** @@ -343,34 +329,33 @@ void serial_irq_set(serial_t *obj, SerialIrq irq, uint32_t enable) ******************************************************************************/ int serial_getc(serial_t *obj) { - while (serial_readable(obj) == 0) { - /* NOP */ - } + uint8_t byte = 0; - return obj->uart->DATA; + while (!serial_readable(obj)){}; + (void)arm_uart_read(obj->uart, &byte); + + return (int)byte; } void serial_putc(serial_t *obj, int c) { - while (serial_writable(obj)) { - /* NOP */ - } - obj->uart->DATA = c; + while (!serial_writable(obj)){}; + (void)arm_uart_write(obj->uart, (int)c); } int serial_readable(serial_t *obj) { - return obj->uart->STATE & 0x2; + return arm_uart_rx_ready(obj->uart); } int serial_writable(serial_t *obj) { - return obj->uart->STATE & 0x1; + return arm_uart_tx_ready(obj->uart); } void serial_clear(serial_t *obj) { - obj->uart->DATA = 0x00; + (void)arm_uart_write(obj->uart, 0x00); } void serial_pinout_tx(PinName tx) @@ -395,7 +380,8 @@ void serial_break_clear(serial_t *obj) */ error("serial_break_clear function not supported"); } -void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, PinName txflow) +void serial_set_flow_control(serial_t *obj, FlowControl type, PinName rxflow, + PinName txflow) { /* * The CMSDK APB UART doesn't have support for flow control.