[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
pull/7302/head
ccli8 2018-02-26 10:26:09 +08:00
parent 2aa2b7eb00
commit f16b971482
6 changed files with 120 additions and 116 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -14,10 +14,12 @@
* limitations under the License.
*/
#include <arm_cmse.h>
#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

View File

@ -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);
}
}