Merge pull request #129 from bcostm/master

[NUCLEO_F103RB] InterruptIn, Sleep, RTC added
pull/131/head^2
Bogdan Marinescu 2013-12-17 00:41:36 -08:00
commit 572b22395f
5 changed files with 366 additions and 6 deletions

View File

@ -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
@ -33,18 +33,18 @@
#define DEVICE_SPI 1
#define DEVICE_SPISLAVE 0
#define DEVICE_RTC 0
#define DEVICE_RTC 1
#define DEVICE_PWMOUT 1
#define DEVICE_SLEEP 1
//=======================================
#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

View File

@ -0,0 +1,242 @@
/* 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 <stddef.h>
#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);
}
// 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_RISE);
}
}
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;
}

View File

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

View File

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

View File

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