From 956064b4bc57062ef8feb6431159db06e8807a2f Mon Sep 17 00:00:00 2001 From: bcostm Date: Sat, 14 Dec 2013 18:53:57 +0100 Subject: [PATCH 1/4] [NUCLEO_F103RB] Add InterruptIn --- .../TARGET_STM/TARGET_NUCLEO_F103RB/device.h | 6 +- .../TARGET_NUCLEO_F103RB/gpio_irq_api.c | 239 ++++++++++++++++++ .../TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c | 2 + .../TARGET_STM/TARGET_NUCLEO_F103RB/objects.h | 4 +- 4 files changed, 246 insertions(+), 5 deletions(-) create mode 100644 libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h index 82ec60c3e8..cbdcba2b30 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h @@ -20,7 +20,7 @@ #define DEVICE_PORTOUT 1 #define DEVICE_PORTINOUT 1 -#define DEVICE_INTERRUPTIN 0 +#define DEVICE_INTERRUPTIN 1 #define DEVICE_ANALOGIN 1 #define DEVICE_ANALOGOUT 0 @@ -37,14 +37,14 @@ #define DEVICE_PWMOUT 1 +#define DEVICE_SLEEP 0 + //======================================= #define DEVICE_SEMIHOST 0 #define DEVICE_LOCALFILESYSTEM 0 #define DEVICE_ID_LENGTH 24 -#define DEVICE_SLEEP 0 - #define DEVICE_DEBUG_AWARENESS 0 #define DEVICE_STDIO_MESSAGES 1 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 new file mode 100644 index 0000000000..4c1d48ce1e --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c @@ -0,0 +1,239 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 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 +#include "cmsis.h" + +#include "gpio_irq_api.h" +#include "error.h" + +#define EDGE_NONE (0) +#define EDGE_RISE (1) +#define EDGE_FALL (2) +#define EDGE_BOTH (3) + +#define CHANNEL_NUM (16) + +static uint32_t channel_ids[CHANNEL_NUM] = {0}; + +static gpio_irq_handler irq_handler; + +static void handle_interrupt_in(uint32_t channel) { + if (channel_ids[channel] == 0) return; + + uint32_t exti_line = (uint32_t)(1 << channel); + if (EXTI_GetITStatus(exti_line) != RESET) + { + EXTI_ClearITPendingBit(exti_line); + } + // Check if it's a rising or a falling event + if (EXTI->RTSR & (uint32_t)(1 << channel)) { + irq_handler(channel_ids[channel], IRQ_RISE); + } + else { + irq_handler(channel_ids[channel], IRQ_FALL); + } +} + +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);} + +int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { + IRQn_Type irq_n = (IRQn_Type)0; + uint32_t vector = 0; + + if (pin == NC) return -1; + + uint32_t pin_number = (uint32_t)pin; + uint32_t pin_index = (pin_number & 0xF); + uint32_t port_index = (pin_number >> 4); + + // Select irq number and vector + switch (pin_index) { + case 0: + irq_n = EXTI0_IRQn; + vector = (uint32_t)&gpio_irq0; + 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: + irq_n = EXTI3_IRQn; + vector = (uint32_t)&gpio_irq3; + break; + case 4: + irq_n = EXTI4_IRQn; + vector = (uint32_t)&gpio_irq4; + break; + case 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; + 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: + return -1; + } + + // Enable GPIO and AFIO clocks + RCC_APB2PeriphClockCmd((uint32_t)(RCC_APB2Periph_GPIOA << port_index), ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); + + // Connect EXTI line to pin + GPIO_EXTILineConfig(port_index, pin_index); + + // Configure EXTI line + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index); + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure); + + // Enable and set EXTI interrupt to the lowest priority + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = irq_n; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + NVIC_SetVector(irq_n, vector); + NVIC_EnableIRQ(irq_n); + + // Save for future use + obj->ch = pin_index; + obj->irq_n = irq_n; + obj->event = EDGE_NONE; + + channel_ids[obj->ch] = id; + + irq_handler = handler; + + return 0; +} + +void gpio_irq_free(gpio_irq_t *obj) { + channel_ids[obj->ch] = 0; + // Disable EXTI line + EXTI_InitTypeDef EXTI_InitStructure; + EXTI_StructInit(&EXTI_InitStructure); + EXTI_Init(&EXTI_InitStructure); + obj->event = EDGE_NONE; +} + +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); + EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; + + if (event == IRQ_RISE) { + if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) { + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; + obj->event = EDGE_BOTH; + } + else { // NONE or RISE + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; + obj->event = EDGE_RISE; + } + } + + if (event == IRQ_FALL) { + if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) { + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; + obj->event = EDGE_BOTH; + } + else { // NONE or FALL + EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; + obj->event = EDGE_FALL; + } + } + + if (enable) { + EXTI_InitStructure.EXTI_LineCmd = ENABLE; + } + else { + EXTI_InitStructure.EXTI_LineCmd = DISABLE; + } + + EXTI_Init(&EXTI_InitStructure); +} + +void gpio_irq_enable(gpio_irq_t *obj) { + NVIC_EnableIRQ(obj->irq_n); +} + +void gpio_irq_disable(gpio_irq_t *obj) { + NVIC_DisableIRQ(obj->irq_n); + obj->event = EDGE_NONE; +} diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c index c69a46b6b3..1f9edba2b7 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c @@ -170,6 +170,8 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int timeout; int count; + if (length == 0) return 0; + /* // Wait until the bus is not busy anymore timeout = LONG_TIMEOUT; 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 191cf77fe0..cc363fddad 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 @@ -26,9 +26,9 @@ extern "C" { #endif struct gpio_irq_s { - uint32_t port; - uint32_t pin; uint32_t ch; + IRQn_Type irq_n; + uint32_t event; // 0=none, 1=rise, 2=fall, 3=rise+fall }; struct port_s { From 967509de53716a48ab65e15f265e8d7e094a9438 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 16 Dec 2013 09:56:00 +0100 Subject: [PATCH 2/4] [NUCLEO_F103RB] Add sleep --- .../TARGET_STM/TARGET_NUCLEO_F103RB/device.h | 2 +- .../TARGET_NUCLEO_F103RB/gpio_irq_api.c | 11 ++-- .../TARGET_STM/TARGET_NUCLEO_F103RB/sleep.c | 53 +++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/sleep.c diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h index cbdcba2b30..13e7368ab2 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h @@ -37,7 +37,7 @@ #define DEVICE_PWMOUT 1 -#define DEVICE_SLEEP 0 +#define DEVICE_SLEEP 1 //======================================= 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 4c1d48ce1e..040df710ce 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 @@ -38,12 +38,15 @@ static void handle_interrupt_in(uint32_t channel) { { EXTI_ClearITPendingBit(exti_line); } - // Check if it's a rising or a falling event - if (EXTI->RTSR & (uint32_t)(1 << channel)) { - irq_handler(channel_ids[channel], IRQ_RISE); + + // 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); } else { - irq_handler(channel_ids[channel], IRQ_FALL); + irq_handler(channel_ids[channel], IRQ_RISE); } } diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/sleep.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/sleep.c new file mode 100644 index 0000000000..958c1528ed --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/sleep.c @@ -0,0 +1,53 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 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 "sleep_api.h" +#include "cmsis.h" + +static void SYSCLKConfig_STOP(void) +{ + ErrorStatus HSEStartUpStatus; + + RCC_HSEConfig(RCC_HSE_ON); // Enable HSE + + HSEStartUpStatus = RCC_WaitForHSEStartUp(); // Wait till HSE is ready + + if (HSEStartUpStatus == SUCCESS) { + RCC_PLLCmd(ENABLE); // Enable PLL + while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {} // Wait till PLL is ready + RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); // Select PLL as system clock source + while(RCC_GetSYSCLKSource() != 0x08) {} // Wait till PLL is used as system clock source + } +} + +void sleep(void) +{ + SCB->SCR = 0; // Normal sleep mode for ARM core + __WFI(); +} + +void deepsleep(void) +{ + // Enable PWR clock + RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); + + // Request to enter STOP mode with regulator in low power mode + PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); + + // At this stage the system has resumed from STOP mode. + // Re-configure the system clock: enable HSE, PLL and select + // PLL as system clock source (because HSE and PLL are disabled in STOP mode). + SYSCLKConfig_STOP(); +} From f8ecc9be46fa2faf14fce62b6eca3e0344017b2c Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 16 Dec 2013 10:13:31 +0100 Subject: [PATCH 3/4] [NUCLEO_F103RB] Allow ACK polling with I2C (again) Go back to the last modification made by Bogdan. --- .../mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c index 1f9edba2b7..c69a46b6b3 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/i2c_api.c @@ -170,8 +170,6 @@ int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int timeout; int count; - if (length == 0) return 0; - /* // Wait until the bus is not busy anymore timeout = LONG_TIMEOUT; From adce27f2692b3e114678e15604f74d0c8cc95874 Mon Sep 17 00:00:00 2001 From: bcostm Date: Mon, 16 Dec 2013 14:33:58 +0100 Subject: [PATCH 4/4] [NUCLEO_F103RB] Add RTC --- .../TARGET_STM/TARGET_NUCLEO_F103RB/device.h | 2 +- .../TARGET_STM/TARGET_NUCLEO_F103RB/rtc_api.c | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/rtc_api.c diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h index 13e7368ab2..aa0959d66f 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/device.h @@ -33,7 +33,7 @@ #define DEVICE_SPI 1 #define DEVICE_SPISLAVE 0 -#define DEVICE_RTC 0 +#define DEVICE_RTC 1 #define DEVICE_PWMOUT 1 diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/rtc_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/rtc_api.c new file mode 100644 index 0000000000..821e8a483b --- /dev/null +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/rtc_api.c @@ -0,0 +1,65 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 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 "rtc_api.h" + +static int rtc_inited = 0; + +void rtc_init(void) { + RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); // Enable PWR and Backup clock + + PWR_BackupAccessCmd(ENABLE); // Allow access to Backup Domain + + BKP_DeInit(); // Reset Backup Domain + + // Enable LSE and wait till it's ready + RCC_LSEConfig(RCC_LSE_ON); + while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} + + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Select LSE as RTC Clock Source + + RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock + + RTC_WaitForSynchro(); // Wait for RTC registers synchronization + + RTC_WaitForLastTask(); // Wait until last write operation on RTC registers has finished + + // Set RTC period to 1 sec + // RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) + RTC_SetPrescaler(32767); + + RTC_WaitForLastTask(); // Wait until last write operation on RTC registers has finished + + rtc_inited = 1; +} + +void rtc_free(void) { + RCC_DeInit(); // Resets the RCC clock configuration to the default reset state + rtc_inited = 0; +} + +int rtc_isenabled(void) { + return rtc_inited; +} + +time_t rtc_read(void) { + return (time_t)RTC_GetCounter(); +} + +void rtc_write(time_t t) { + RTC_WaitForLastTask(); // Wait until last write operation on RTC registers has finished + RTC_SetCounter(t); // Change the current time + RTC_WaitForLastTask(); // Wait until last write operation on RTC registers has finished +}