From f16b97148286628025e4bd6bc991be5f99505dd0 Mon Sep 17 00:00:00 2001 From: ccli8 Date: Mon, 26 Feb 2018 10:26:09 +0800 Subject: [PATCH] [M2351] Fix GPIO to be TrustZone-aware 1. Revise NU_PORT_BASE to be TrustZone-aware 2. Add TrustZone-aware NU_GET_GPIO_PIN_DATA/NU_SET_GPIO_PIN_DATA to replace GPIO_PIN_DATA 3. Revise pin_function to be TrustZone-aware --- .../TARGET_NUMAKER_PFM_M2351/PinNames.h | 41 +++++- .../TARGET_NUVOTON/TARGET_M2351/gpio_api.c | 3 - .../TARGET_M2351/gpio_irq_api.c | 127 +++++++++--------- .../TARGET_NUVOTON/TARGET_M2351/gpio_object.h | 24 +--- targets/TARGET_NUVOTON/TARGET_M2351/pinmap.c | 19 ++- .../TARGET_NUVOTON/TARGET_M2351/port_api.c | 22 +-- 6 files changed, 120 insertions(+), 116 deletions(-) diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/TARGET_NUMAKER_PFM_M2351/PinNames.h b/targets/TARGET_NUVOTON/TARGET_M2351/TARGET_NUMAKER_PFM_M2351/PinNames.h index df90cc6bee..3713a04d49 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/TARGET_NUMAKER_PFM_M2351/PinNames.h +++ b/targets/TARGET_NUVOTON/TARGET_M2351/TARGET_NUMAKER_PFM_M2351/PinNames.h @@ -17,6 +17,7 @@ #define MBED_PINNAMES_H #include "cmsis.h" +#include "partition_M2351.h" #ifdef __cplusplus extern "C" { @@ -39,10 +40,48 @@ extern "C" { #define NU_PINNAME_BIND(PINNAME, modname) ((PinName) NU_PINNAME_BIND_(NU_PINPORT(PINNAME), NU_PININDEX(PINNAME), modname)) #define NU_PINNAME_BIND_(PORT, PIN, modname) ((((unsigned int)(PORT)) << NU_PINPORT_Pos) | (((unsigned int)(PIN)) << NU_PININDEX_Pos) | (NU_MODINDEX(modname) << NU_PIN_MODINDEX_Pos) | NU_PIN_BIND_Msk) -#define NU_PORT_BASE(port) ((GPIO_T *)(((uint32_t) (GPIOA_BASE + NS_OFFSET)) + 0x40 * port)) // Set All GPIO as non-secure +/* Revise NU_PORT_BASE to be TrustZone-aware */ +__STATIC_INLINE GPIO_T *NU_PORT_BASE(uint32_t PORT) +{ + uint32_t port_base = ((uint32_t) GPIOA_BASE) + 0x40 * PORT; + +#if defined(SCU_INIT_IONSSET_VAL) + if (SCU_INIT_IONSSET_VAL & (1 << (PORT + 0))) { + port_base += NS_OFFSET; + } +#endif + + return ((GPIO_T *) port_base); +} + #define NU_MFP_POS(pin) ((pin % 8) * 4) #define NU_MFP_MSK(pin) (0xful << NU_MFP_POS(pin)) +/* TrustZone-aware version of GPIO_PIN_DATA to get GPIO pin data */ +__STATIC_INLINE uint32_t NU_GET_GPIO_PIN_DATA(uint32_t PORT, uint32_t PIN) +{ +#if defined(SCU_INIT_IONSSET_VAL) + if (SCU_INIT_IONSSET_VAL & (1 << (PORT + 0))) { + return GPIO_PIN_DATA_NS(PORT, PIN); + } +#endif + + return GPIO_PIN_DATA(PORT, PIN); +} + +/* TrustZone-aware version of GPIO_PIN_DATA to set GPIO pin data */ +__STATIC_INLINE void NU_SET_GPIO_PIN_DATA(uint32_t PORT, uint32_t PIN, uint32_t VALUE) +{ +#if defined(SCU_INIT_IONSSET_VAL) + if (SCU_INIT_IONSSET_VAL & (1 << (PORT + 0))) { + GPIO_PIN_DATA_NS(PORT, PIN) = VALUE; + return; + } +#endif + + GPIO_PIN_DATA(PORT, PIN) = VALUE; +} + // LEGACY #define NU_PINNAME_TO_PIN(PINNAME) NU_PININDEX(PINNAME) #define NU_PINNAME_TO_PORT(PINNAME) NU_PINPORT(PINNAME) diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_api.c b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_api.c index 84e77e5fca..9c83e28a5e 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_api.c @@ -62,8 +62,6 @@ void gpio_mode(gpio_t *obj, PinMode mode) pin_mode(obj->pin, mode); } -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) -__attribute__((cmse_nonsecure_entry)) void gpio_dir(gpio_t *obj, PinDirection direction) { if (obj->pin == (PinName) NC) { @@ -91,4 +89,3 @@ void gpio_dir(gpio_t *obj, PinDirection direction) GPIO_SetMode(gpio_base, 1 << pin_index, mode_intern); } -#endif diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c index c4daf20dec..6b40f62899 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_irq_api.c @@ -22,7 +22,6 @@ #include "cmsis.h" #include "pinmap.h" #include "PeripheralPins.h" -#include "mbed_error.h" #include "nu_bitutil.h" #define NU_MAX_PIN_PER_PORT 16 @@ -31,6 +30,7 @@ struct nu_gpio_irq_var { gpio_irq_t * obj_arr[NU_MAX_PIN_PER_PORT]; IRQn_Type irq_n; void (*vec)(void); + uint32_t port_index; }; static void gpio_irq_0_vec(void); @@ -44,34 +44,34 @@ static void gpio_irq(struct nu_gpio_irq_var *var); //EINT0_IRQn static struct nu_gpio_irq_var gpio_irq_var_arr[] = { - {{NULL}, GPA_IRQn, gpio_irq_0_vec}, - {{NULL}, GPB_IRQn, gpio_irq_1_vec}, - {{NULL}, GPC_IRQn, gpio_irq_2_vec}, - {{NULL}, GPD_IRQn, gpio_irq_3_vec}, - {{NULL}, GPE_IRQn, gpio_irq_4_vec}, - {{NULL}, GPF_IRQn, gpio_irq_5_vec}, - {{NULL}, GPG_IRQn, gpio_irq_6_vec} + {{NULL}, GPA_IRQn, gpio_irq_0_vec, 0}, + {{NULL}, GPB_IRQn, gpio_irq_1_vec, 1}, + {{NULL}, GPC_IRQn, gpio_irq_2_vec, 2}, + {{NULL}, GPD_IRQn, gpio_irq_3_vec, 3}, + {{NULL}, GPE_IRQn, gpio_irq_4_vec, 4}, + {{NULL}, GPF_IRQn, gpio_irq_5_vec, 5}, + {{NULL}, GPG_IRQn, gpio_irq_6_vec, 6}, }; #define NU_MAX_PORT (sizeof (gpio_irq_var_arr) / sizeof (gpio_irq_var_arr[0])) -#ifndef MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE -#define MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE 0 +#ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE +#define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE 0 #endif -#ifndef MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE_LIST -#define MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE_LIST NC +#ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST +#define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST NC #endif static PinName gpio_irq_debounce_arr[] = { - MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE_LIST + MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST }; -#ifndef MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE -#define MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE GPIO_DBCTL_DBCLKSRC_LIRC +#ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE +#define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE GPIO_DBCTL_DBCLKSRC_LIRC #endif -#ifndef MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE -#define MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE GPIO_DBCTL_DBCLKSEL_16 +#ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE +#define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE GPIO_DBCTL_DBCLKSEL_16 #endif int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) @@ -79,58 +79,59 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 if (pin == NC) { return -1; } - + uint32_t pin_index = NU_PINNAME_TO_PIN(pin); uint32_t port_index = NU_PINNAME_TO_PORT(pin); if (pin_index >= NU_MAX_PIN_PER_PORT || port_index >= NU_MAX_PORT) { return -1; } - + obj->pin = pin; obj->irq_handler = (uint32_t) handler; obj->irq_id = id; GPIO_T *gpio_base = NU_PORT_BASE(port_index); - //gpio_set(pin); - + // NOTE: In InterruptIn constructor, gpio_irq_init() is called with gpio_init_in() which is responsible for multi-function pin setting. + // There is no need to call gpio_set() redundantly. + { -#if MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_ENABLE +#if MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE // Suppress compiler warning (void) gpio_irq_debounce_arr; // Configure de-bounce clock source and sampling cycle time - GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE); + GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE); GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index); #else // Enable de-bounce if the pin is in the de-bounce enable list - + // De-bounce defaults to disabled. GPIO_DISABLE_DEBOUNCE(gpio_base, 1 << pin_index); - + PinName *debounce_pos = gpio_irq_debounce_arr; PinName *debounce_end = gpio_irq_debounce_arr + sizeof (gpio_irq_debounce_arr) / sizeof (gpio_irq_debounce_arr[0]); for (; debounce_pos != debounce_end && *debounce_pos != NC; debounce_pos ++) { uint32_t pin_index_debunce = NU_PINNAME_TO_PIN(*debounce_pos); uint32_t port_index_debounce = NU_PINNAME_TO_PORT(*debounce_pos); - + if (pin_index == pin_index_debunce && port_index == port_index_debounce) { // Configure de-bounce clock source and sampling cycle time - GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_M2351_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE); + GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE); GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index); break; } } #endif } - + struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + var->obj_arr[pin_index] = obj; - + // NOTE: InterruptIn requires IRQ enabled by default. gpio_irq_enable(obj); - + return 0; } @@ -139,10 +140,10 @@ void gpio_irq_free(gpio_irq_t *obj) uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_DisableIRQ(var->irq_n); NU_PORT_BASE(port_index)->INTEN = 0; - + MBED_ASSERT(pin_index < NU_MAX_PIN_PER_PORT); var->obj_arr[pin_index] = NULL; } @@ -152,27 +153,27 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + switch (event) { - case IRQ_RISE: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING); - } - else { - gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index); - } - break; - - case IRQ_FALL: - if (enable) { - GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING); - } - else { - gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index); - } - break; - default: - break; + case IRQ_RISE: + if (enable) { + GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING); + } else { + gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index); + } + break; + + case IRQ_FALL: + if (enable) { + GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING); + } else { + gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index); + } + break; + + case IRQ_NONE: + default: + break; } } @@ -180,7 +181,7 @@ void gpio_irq_enable(gpio_irq_t *obj) { uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_SetVector(var->irq_n, (uint32_t) var->vec); NVIC_EnableIRQ(var->irq_n); } @@ -189,7 +190,7 @@ void gpio_irq_disable(gpio_irq_t *obj) { uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index; - + NVIC_DisableIRQ(var->irq_n); } @@ -224,30 +225,32 @@ static void gpio_irq_6_vec(void) static void gpio_irq(struct nu_gpio_irq_var *var) { - uint32_t port_index = var->irq_n - GPA_IRQn; + // NOTE: GPA_IRQn, GPB_IRQn, ... are not arranged sequentially, so we cannot calculate out port_index through offset from GPA_IRQn. + // Instead, we add port_index into gpio_irq_var_arr table. + uint32_t port_index = var->port_index; GPIO_T *gpio_base = NU_PORT_BASE(port_index); - + uint32_t intsrc = gpio_base->INTSRC; uint32_t inten = gpio_base->INTEN; while (intsrc) { int pin_index = nu_ctz(intsrc); gpio_irq_t *obj = var->obj_arr[pin_index]; if (inten & (GPIO_INT_RISING << pin_index)) { - if (GPIO_PIN_DATA(port_index, pin_index)) { + if (NU_GET_GPIO_PIN_DATA(port_index, pin_index)) { if (obj->irq_handler) { ((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_RISE); } } } - - if (inten & (GPIO_INT_FALLING << pin_index)) { - if (! GPIO_PIN_DATA(port_index, pin_index)) { + + if (inten & (GPIO_INT_FALLING << pin_index)) { + if (! NU_GET_GPIO_PIN_DATA(port_index, pin_index)) { if (obj->irq_handler) { ((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_FALL); } } } - + intsrc &= ~(1 << pin_index); } // Clear all interrupt flags diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_object.h b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_object.h index 7987b3ebad..6437ac617b 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/gpio_object.h +++ b/targets/TARGET_NUVOTON/TARGET_M2351/gpio_object.h @@ -38,16 +38,8 @@ static inline void gpio_write(gpio_t *obj, int value) MBED_ASSERT(obj->pin != (PinName)NC); uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); -#if defined (NVIC_INIT_ITNS0_VAL) - if( NVIC_INIT_ITNS0_VAL & (0x01 << (16 + port_index)) ) - { - GPIO_PIN_DATA_NS(port_index, pin_index) = value ? 1 : 0; - } else { - GPIO_PIN_DATA(port_index, pin_index) = value ? 1 : 0; - } -#else - GPIO_PIN_DATA(port_index, pin_index) = value ? 1 : 0; -#endif + + NU_SET_GPIO_PIN_DATA(port_index, pin_index, value ? 1 : 0); } static inline int gpio_read(gpio_t *obj) @@ -55,16 +47,8 @@ static inline int gpio_read(gpio_t *obj) MBED_ASSERT(obj->pin != (PinName)NC); uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin); uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin); -#if defined (NVIC_INIT_ITNS0_VAL) - if( NVIC_INIT_ITNS0_VAL & (0x01 << (16 + port_index)) ) - { - return (GPIO_PIN_DATA_NS(port_index, pin_index) ? 1 : 0); - } else { - return (GPIO_PIN_DATA(port_index, pin_index) ? 1 : 0); - } -#else - return (GPIO_PIN_DATA(port_index, pin_index) ? 1 : 0); -#endif + + return (NU_GET_GPIO_PIN_DATA(port_index, pin_index) ? 1 : 0); } #ifdef __cplusplus diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/pinmap.c b/targets/TARGET_NUVOTON/TARGET_M2351/pinmap.c index cf6fb58c6f..e7d2dd9830 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/pinmap.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/pinmap.c @@ -14,10 +14,12 @@ * limitations under the License. */ +#include #include "mbed_assert.h" #include "pinmap.h" #include "PortNames.h" #include "mbed_error.h" +#include "partition_m2351.h" /** * Configure pin multi-function @@ -30,21 +32,18 @@ void pin_function(PinName pin, int data) MBED_ASSERT(pin != (PinName)NC); uint32_t pin_index = NU_PINNAME_TO_PIN(pin); uint32_t port_index = NU_PINNAME_TO_PORT(pin); + + /* Guard access to secure GPIO from non-secure domain */ + if (cmse_nonsecure_caller() && + (! (SCU_INIT_IONSSET_VAL & (1 << (port_index + 0))))) { + error("Non-secure domain tries to control secure or undefined GPIO."); + } + __IO uint32_t *GPx_MFPx = ((__IO uint32_t *) &SYS->GPA_MFPL) + port_index * 2 + (pin_index / 8); - //uint32_t MFP_Pos = NU_MFP_POS(pin_index); uint32_t MFP_Msk = NU_MFP_MSK(pin_index); // E.g.: SYS->GPA_MFPL = (SYS->GPA_MFPL & (~SYS_GPA_MFPL_PA0MFP_Msk) ) | SYS_GPA_MFPL_PA0MFP_SC0_CD ; *GPx_MFPx = (*GPx_MFPx & (~MFP_Msk)) | data; - - // [TODO] Disconnect JTAG-DP + SW-DP signals. - // Warning: Need to reconnect under reset - //if ((pin == PA_13) || (pin == PA_14)) { - // - //} - //if ((pin == PA_15) || (pin == PB_3) || (pin == PB_4)) { - // - //} } #endif diff --git a/targets/TARGET_NUVOTON/TARGET_M2351/port_api.c b/targets/TARGET_NUVOTON/TARGET_M2351/port_api.c index b36b0309a7..197e780aac 100644 --- a/targets/TARGET_NUVOTON/TARGET_M2351/port_api.c +++ b/targets/TARGET_NUVOTON/TARGET_M2351/port_api.c @@ -77,16 +77,7 @@ void port_write(port_t *obj, int value) for (i = 0; i < GPIO_PIN_MAX; i++) { if (obj->mask & (1 << i)) { -#if defined (NVIC_INIT_ITNS0_VAL) - if( NVIC_INIT_ITNS0_VAL & (0x01 << (16 + port_index)) ) - { - GPIO_PIN_DATA_NS(port_index, i) = (value & obj->mask) ? 1 : 0; - } else { - GPIO_PIN_DATA(port_index, i) = (value & obj->mask) ? 1 : 0; - } -#else - GPIO_PIN_DATA(port_index, i) = (value & obj->mask) ? 1 : 0; -#endif + NU_SET_GPIO_PIN_DATA(port_index, i, (value & obj->mask) ? 1 : 0); } } } @@ -99,16 +90,7 @@ int port_read(port_t *obj) for (i = 0; i < GPIO_PIN_MAX; i++) { if (obj->mask & (1 << i)) { -#if defined (NVIC_INIT_ITNS0_VAL) - if( NVIC_INIT_ITNS0_VAL & (0x01 << (16 + port_index)) ) - { - value = value | (GPIO_PIN_DATA_NS(port_index, i) << i); - } else { - value = value | (GPIO_PIN_DATA(port_index, i) << i); - } -#else - value = value | (GPIO_PIN_DATA(port_index, i) << i); -#endif + value = value | (NU_GET_GPIO_PIN_DATA(port_index, i) << i); } }