From d14992dcfd0793c8362344eaec5cf2e35700ae78 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 27 Jan 2014 09:59:07 +0100 Subject: [PATCH] [NUCLEO_F103RB] Improvement of gpio and gpio_irq api --- .../TARGET_NUCLEO_F103RB/gpio_api.c | 14 +- .../TARGET_NUCLEO_F103RB/gpio_irq_api.c | 154 +++++++----------- .../TARGET_STM/TARGET_NUCLEO_F103RB/objects.h | 4 +- .../TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c | 59 +++++-- .../TARGET_NUCLEO_F103RB/port_api.c | 12 +- .../TARGET_NUCLEO_F103RB/us_ticker.c | 14 +- 6 files changed, 129 insertions(+), 128 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_api.c index 1d971e3bd3..6506e24651 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_api.c @@ -29,6 +29,9 @@ */ #include "gpio_api.h" #include "pinmap.h" +#include "error.h" + +extern uint32_t Set_GPIO_Clock(uint32_t port_idx); uint32_t gpio_set(PinName pin) { if (pin == NC) return 0; @@ -38,14 +41,17 @@ uint32_t gpio_set(PinName pin) { return (uint32_t)(1 << ((uint32_t)pin & 0xF)); // Return the pin mask } -void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) { +void gpio_init(gpio_t *obj, PinName pin, PinDirection direction) { + GPIO_TypeDef *gpio; + if (pin == NC) return; uint32_t port_index = STM_PORT(pin); - // Get GPIO structure base address - GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10)); - + // Enable GPIO clock + uint32_t gpio_add = Set_GPIO_Clock(port_index); + gpio = (GPIO_TypeDef *)gpio_add; + // Fill GPIO object structure for future use obj->pin = pin; obj->mask = gpio_set(pin); diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c index 703f6cf3a5..9461ed5357 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c @@ -31,6 +31,7 @@ #include "cmsis.h" #include "gpio_irq_api.h" +#include "pinmap.h" #include "error.h" #define EDGE_NONE (0) @@ -38,132 +39,88 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) -#define CHANNEL_NUM (16) +#define CHANNEL_NUM (4) -static uint32_t channel_ids[CHANNEL_NUM] = {0}; +static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0, 0}; +static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0, 0}; +static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0, 0}; static gpio_irq_handler irq_handler; -static void handle_interrupt_in(uint32_t channel) { - if (channel_ids[channel] == 0) return; +static void handle_interrupt_in(uint32_t irq_index) { - uint32_t exti_line = (uint32_t)(1 << channel); - if (EXTI_GetITStatus(exti_line) != RESET) + // Retrieve the gpio and pin that generate the irq + GPIO_TypeDef *gpio = (GPIO_TypeDef *)(channel_gpio[irq_index]); + uint32_t pin = (uint32_t)(1 << channel_pin[irq_index]); + + // Clear interrupt flag + if (EXTI_GetITStatus(pin) != RESET) { - EXTI_ClearITPendingBit(exti_line); + EXTI_ClearITPendingBit(pin); } - // Warning: - // On this device we don't know if a rising or falling event occured. - // In case both rise and fall events are set, only the FALL event will be reported. - if (EXTI->FTSR & (uint32_t)(1 << channel)) { - irq_handler(channel_ids[channel], IRQ_FALL); + if (channel_ids[irq_index] == 0) return; + + // Check which edge has generated the irq + if ((gpio->IDR & pin) == 0) { + irq_handler(channel_ids[irq_index], IRQ_FALL); } - else { - irq_handler(channel_ids[channel], IRQ_RISE); + else { + irq_handler(channel_ids[irq_index], IRQ_RISE); } } +// The irq_index is passed to the function static void gpio_irq0(void) {handle_interrupt_in(0);} static void gpio_irq1(void) {handle_interrupt_in(1);} static void gpio_irq2(void) {handle_interrupt_in(2);} static void gpio_irq3(void) {handle_interrupt_in(3);} -static void gpio_irq4(void) {handle_interrupt_in(4);} -static void gpio_irq5(void) {handle_interrupt_in(5);} -static void gpio_irq6(void) {handle_interrupt_in(6);} -static void gpio_irq7(void) {handle_interrupt_in(7);} -static void gpio_irq8(void) {handle_interrupt_in(8);} -static void gpio_irq9(void) {handle_interrupt_in(9);} -static void gpio_irq10(void) {handle_interrupt_in(10);} -static void gpio_irq11(void) {handle_interrupt_in(11);} -static void gpio_irq12(void) {handle_interrupt_in(12);} -static void gpio_irq13(void) {handle_interrupt_in(13);} -static void gpio_irq14(void) {handle_interrupt_in(14);} -static void gpio_irq15(void) {handle_interrupt_in(15);} + +extern uint32_t Set_GPIO_Clock(uint32_t port_idx); int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { - IRQn_Type irq_n = (IRQn_Type)0; + IRQn_Type irq_n = (IRQn_Type)0; uint32_t vector = 0; - + uint32_t irq_index; + if (pin == NC) return -1; uint32_t port_index = STM_PORT(pin); uint32_t pin_index = STM_PIN(pin); - - // Select irq number and vector - switch (pin_index) { - case 0: - irq_n = EXTI0_IRQn; + + // Select irq number and interrupt routine + switch (pin) { + case PC_13: // User button + irq_n = EXTI15_10_IRQn; vector = (uint32_t)&gpio_irq0; + irq_index = 0; break; - case 1: - irq_n = EXTI1_IRQn; - vector = (uint32_t)&gpio_irq1; - break; - case 2: - irq_n = EXTI2_IRQn; - vector = (uint32_t)&gpio_irq2; - break; - case 3: + case PB_3: irq_n = EXTI3_IRQn; - vector = (uint32_t)&gpio_irq3; + vector = (uint32_t)&gpio_irq1; + irq_index = 1; break; - case 4: + case PB_4: irq_n = EXTI4_IRQn; - vector = (uint32_t)&gpio_irq4; + vector = (uint32_t)&gpio_irq2; + irq_index = 2; break; - case 5: + case PB_5: irq_n = EXTI9_5_IRQn; - vector = (uint32_t)&gpio_irq5; - break; - case 6: - irq_n = EXTI9_5_IRQn; - vector = (uint32_t)&gpio_irq6; - break; - case 7: - irq_n = EXTI9_5_IRQn; - vector = (uint32_t)&gpio_irq7; - break; - case 8: - irq_n = EXTI9_5_IRQn; - vector = (uint32_t)&gpio_irq8; - break; - case 9: - irq_n = EXTI9_5_IRQn; - vector = (uint32_t)&gpio_irq9; + vector = (uint32_t)&gpio_irq3; + irq_index = 3; break; - case 10: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq10; - break; - case 11: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq11; - break; - case 12: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq12; - break; - case 13: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq13; - break; - case 14: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq14; - break; - case 15: - irq_n = EXTI15_10_IRQn; - vector = (uint32_t)&gpio_irq15; - break; default: + error("This pin is not supported with InterruptIn.\n"); return -1; } + + // Enable GPIO clock + uint32_t gpio_add = Set_GPIO_Clock(port_index); - // Enable GPIO and AFIO clocks - RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE); + // Enable AFIO clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); - + // Connect EXTI line to pin GPIO_EXTILineConfig(port_index, pin_index); @@ -186,20 +143,23 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 NVIC_SetVector(irq_n, vector); NVIC_EnableIRQ(irq_n); - // Save for future use - obj->ch = pin_index; + // Save informations for future use obj->irq_n = irq_n; + obj->irq_index = irq_index; obj->event = EDGE_NONE; + channel_ids[irq_index] = id; + channel_gpio[irq_index] = gpio_add; + channel_pin[irq_index] = pin_index; - channel_ids[obj->ch] = id; - irq_handler = handler; return 0; } void gpio_irq_free(gpio_irq_t *obj) { - channel_ids[obj->ch] = 0; + channel_ids[obj->irq_index] = 0; + channel_gpio[obj->irq_index] = 0; + channel_pin[obj->irq_index] = 0; // Disable EXTI line EXTI_InitTypeDef EXTI_InitStructure; EXTI_StructInit(&EXTI_InitStructure); @@ -210,7 +170,9 @@ void gpio_irq_free(gpio_irq_t *obj) { void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { EXTI_InitTypeDef EXTI_InitStructure; - EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << obj->ch); + uint32_t pin_index = channel_pin[obj->irq_index]; + + EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index); EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; if (event == IRQ_RISE) { diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h index ed42f28c2a..2e1a43b421 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h @@ -40,9 +40,9 @@ extern "C" { #endif struct gpio_irq_s { - uint32_t ch; IRQn_Type irq_n; - uint32_t event; // 0=none, 1=rise, 2=fall, 3=rise+fall + uint32_t irq_index; + uint32_t event; }; struct port_s { diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c index 6c833eed09..6f48d8f67b 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/pinmap.c @@ -43,28 +43,58 @@ static const uint32_t AF_mapping[] = { GPIO_Remap_I2C1 // 8 }; +// Not an API function +// Enable GPIO clock and return GPIO base address +uint32_t Set_GPIO_Clock(uint32_t port_idx) { + uint32_t gpio_add = 0; + switch (port_idx) { + case PortA: + gpio_add = GPIOA_BASE; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); + break; + case PortB: + gpio_add = GPIOB_BASE; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); + break; + case PortC: + gpio_add = GPIOC_BASE; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); + break; + case PortD: + gpio_add = GPIOD_BASE; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); + break; + default: + error("Port number is not correct."); + break; + } + return gpio_add; +} + /** - * Set the pin function (input, output, alternate function or analog) + output speed + AF + * Configure pin (input, output, alternate function or analog) + output speed + AF */ void pin_function(PinName pin, int data) { + GPIO_TypeDef *gpio; + GPIO_InitTypeDef GPIO_InitStructure; + if (pin == NC) return; - // Get the pin mode and alternate-function number + // Get the pin informations uint32_t mode = STM_PIN_MODE(data); uint32_t afnum = STM_PIN_AFNUM(data); uint32_t port_index = STM_PORT(pin); uint32_t pin_index = STM_PIN(pin); - - // Get GPIO structure base address - GPIO_TypeDef *gpio = ((GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10))); - // Enable GPIO and AFIO clocks - RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE); + // Enable GPIO clock + uint32_t gpio_add = Set_GPIO_Clock(port_index); + gpio = (GPIO_TypeDef *)gpio_add; + + // Enable AFIO clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // Configure GPIO - GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = (uint16_t)(1 << pin_index); GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)mode; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; @@ -86,21 +116,20 @@ void pin_function(PinName pin, int data) { } /** - * Set the pin mode (open-drain/push-pull + pull-up/pull-down) + * Configure pin pull-up/pull-down */ void pin_mode(PinName pin, PinMode mode) { - if (pin == NC) return; - + GPIO_TypeDef *gpio; GPIO_InitTypeDef GPIO_InitStructure; + if (pin == NC) return; + uint32_t port_index = STM_PORT(pin); uint32_t pin_index = STM_PIN(pin); - - // Get GPIO structure base address - GPIO_TypeDef *gpio = ((GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10))); // Enable GPIO clock - RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE); + uint32_t gpio_add = Set_GPIO_Clock(port_index); + gpio = (GPIO_TypeDef *)gpio_add; // Configure open-drain and pull-up/down switch (mode) { diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/port_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/port_api.c index 3d072753f1..97340e2dfa 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/port_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/port_api.c @@ -30,9 +30,12 @@ #include "port_api.h" #include "pinmap.h" #include "gpio_api.h" +#include "error.h" #if DEVICE_PORTIN || DEVICE_PORTOUT +extern uint32_t Set_GPIO_Clock(uint32_t port_idx); + // high nibble = port number (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...) // low nibble = pin number PinName port_pin(PortName port, int pin_n) { @@ -40,14 +43,13 @@ PinName port_pin(PortName port, int pin_n) { } void port_init(port_t *obj, PortName port, int mask, PinDirection dir) { - + GPIO_TypeDef *gpio; + uint32_t port_index = (uint32_t)port; // (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...) // Enable GPIO clock - RCC_APB2PeriphClockCmd((RCC_APB2Periph_GPIOA << port_index), ENABLE); - - // Get GPIO structure base address - GPIO_TypeDef *gpio = (GPIO_TypeDef *)(GPIOA_BASE + (port_index << 10)); + uint32_t gpio_add = Set_GPIO_Clock(port_index); + gpio = (GPIO_TypeDef *)gpio_add; // Fill PORT object structure for future use obj->port = port; diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/us_ticker.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/us_ticker.c index 107bc4e983..fb36519dae 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/us_ticker.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/us_ticker.c @@ -34,11 +34,11 @@ #define TIM_MST TIM1 #define TIM_MST_IRQ TIM1_CC_IRQn -#define TIM_MST_RCC RCC_APB2Periph_TIM1 +#define TIM_MST_RCC RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE) #define TIM_SLV TIM4 #define TIM_SLV_IRQ TIM4_IRQn -#define TIM_SLV_RCC RCC_APB1Periph_TIM4 +#define TIM_SLV_RCC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE) #define MST_SLV_ITR TIM_TS_ITR0 @@ -53,8 +53,8 @@ void us_ticker_init(void) { us_ticker_inited = 1; // Enable Timers clock - RCC_APB2PeriphClockCmd(TIM_MST_RCC, ENABLE); - RCC_APB1PeriphClockCmd(TIM_SLV_RCC, ENABLE); + TIM_MST_RCC; + TIM_SLV_RCC; // Master and Slave timers time base configuration TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); @@ -94,9 +94,11 @@ uint32_t us_ticker_read() { // previous (incorrect) value of Slave and the new value of Master, which would return a // value in the past. Avoid this by computing consecutive values of the timer until they // are properly ordered. - counter = counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16) + (uint32_t)TIM_GetCounter(TIM_MST); + counter = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16); + counter += (uint32_t)TIM_GetCounter(TIM_MST); while (1) { - counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16) + (uint32_t)TIM_GetCounter(TIM_MST); + counter2 = (uint32_t)((uint32_t)TIM_GetCounter(TIM_SLV) << 16); + counter2 += (uint32_t)TIM_GetCounter(TIM_MST); if (counter2 > counter) { break; }