Merge pull request #151 from bcostm/master

[NUCLEO_F030R8] Fix vectors remap in RAM issue and more...
pull/152/head
Bogdan Marinescu 2014-01-27 07:25:03 -08:00
commit 887fc11980
10 changed files with 321 additions and 115 deletions

View File

@ -38,7 +38,7 @@ static unsigned char vtor_remap = 0; // To keep track that the vectors remap is
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
int i;
// Space for dynamic vectors, initialised to allocate in R/W
static volatile uint32_t* vectors = (uint32_t *)NVIC_RAM_VECTOR_ADDRESS;
static volatile uint32_t *vectors = (uint32_t *)NVIC_RAM_VECTOR_ADDRESS;
// Copy and switch to dynamic vectors if first time called
if (vtor_remap == 0) {
@ -46,6 +46,7 @@ void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector) {
for (i = 0; i < NVIC_NUM_VECTORS; i++) {
vectors[i] = old_vectors[i];
}
SYSCFG->CFGR1 |= 0x03; // Embedded SRAM mapped at 0x00000000
vtor_remap = 1; // The vectors remap is done
}

View File

@ -122,7 +122,7 @@ static inline uint16_t adc_read(analogin_t *obj) {
}
while(!ADC_GetFlagStatus(adc, ADC_FLAG_ADRDY)); // Wait ADC ready
ADC_StartOfConversion(adc); // Start conversion
while(ADC_GetFlagStatus(adc, ADC_FLAG_EOC) == RESET); // Wait end of conversion

View File

@ -49,9 +49,9 @@
#define DEVICE_RTC 1
#define DEVICE_PWMOUT 0
#define DEVICE_PWMOUT 1
#define DEVICE_SLEEP 0
#define DEVICE_SLEEP 1
//=======================================

View File

@ -31,6 +31,8 @@
#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;
@ -39,35 +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
switch (port_index) {
case PortA:
gpio = (GPIO_TypeDef *)GPIOA_BASE;
break;
case PortB:
gpio = (GPIO_TypeDef *)GPIOB_BASE;
break;
case PortC:
gpio = (GPIO_TypeDef *)GPIOC_BASE;
break;
case PortD:
gpio = (GPIO_TypeDef *)GPIOD_BASE;
break;
case PortF:
gpio = (GPIO_TypeDef *)GPIOF_BASE;
break;
default:
error("GPIO port number is not correct.");
break;
}
// 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);

View File

@ -0,0 +1,210 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#include <stddef.h>
#include "cmsis.h"
#include "gpio_irq_api.h"
#include "pinmap.h"
#include "error.h"
#define EDGE_NONE (0)
#define EDGE_RISE (1)
#define EDGE_FALL (2)
#define EDGE_BOTH (3)
#define CHANNEL_NUM (3)
static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0};
static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0};
static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0};
static gpio_irq_handler irq_handler;
static void handle_interrupt_in(uint32_t irq_index) {
// 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(pin);
}
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[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);}
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;
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 interrupt routine
switch (pin) {
case PC_13: // User button
irq_n = EXTI4_15_IRQn;
vector = (uint32_t)&gpio_irq0;
irq_index = 0;
break;
case PA_0:
irq_n = EXTI0_1_IRQn;
vector = (uint32_t)&gpio_irq1;
irq_index = 1;
break;
case PB_3:
irq_n = EXTI2_3_IRQn;
vector = (uint32_t)&gpio_irq2;
irq_index = 2;
break;
default:
error("This pin is not supported\n");
return -1;
}
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
// Enable SYSCFG clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
// Connect EXTI line to pin
SYSCFG_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_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);
// 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;
irq_handler = handler;
return 0;
}
void gpio_irq_free(gpio_irq_t *obj) {
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);
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;
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) {
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

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

View File

@ -30,6 +30,38 @@
#include "pinmap.h"
#include "error.h"
// 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_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
break;
case PortB:
gpio_add = GPIOB_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
break;
case PortC:
gpio_add = GPIOC_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
break;
case PortD:
gpio_add = GPIOD_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
break;
case PortF:
gpio_add = GPIOF_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
break;
default:
error("Port number is not correct.");
break;
}
return gpio_add;
}
/**
* Configure pin (mode, speed, output type and pull-up/pull-down)
*/
@ -47,34 +79,11 @@ void pin_function(PinName pin, int data) {
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
// Get GPIO structure base address and enable clock
switch (port_index) {
case PortA:
gpio = (GPIO_TypeDef *)GPIOA_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
break;
case PortB:
gpio = (GPIO_TypeDef *)GPIOB_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
break;
case PortC:
gpio = (GPIO_TypeDef *)GPIOC_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
break;
case PortD:
gpio = (GPIO_TypeDef *)GPIOD_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
break;
case PortF:
gpio = (GPIO_TypeDef *)GPIOF_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
break;
default:
error("GPIO port number is not correct.");
break;
}
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
gpio = (GPIO_TypeDef *)gpio_add;
// Configure GPIO
GPIO_InitStructure.GPIO_Pin = (uint16_t)(1 << pin_index);
GPIO_InitStructure.GPIO_Mode = (GPIOMode_TypeDef)mode;
@ -104,38 +113,15 @@ void pin_function(PinName pin, int data) {
*/
void pin_mode(PinName pin, PinMode mode) {
GPIO_TypeDef *gpio;
if (pin == NC) return;
uint32_t port_index = STM_PORT(pin);
uint32_t pin_index = STM_PIN(pin);
// Get GPIO structure base address and enable clock
switch (port_index) {
case PortA:
gpio = (GPIO_TypeDef *)GPIOA_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
break;
case PortB:
gpio = (GPIO_TypeDef *)GPIOB_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
break;
case PortC:
gpio = (GPIO_TypeDef *)GPIOC_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
break;
case PortD:
gpio = (GPIO_TypeDef *)GPIOD_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
break;
case PortF:
gpio = (GPIO_TypeDef *)GPIOF_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
break;
default:
error("GPIO port number is not correct.");
break;
}
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
gpio = (GPIO_TypeDef *)gpio_add;
// Configure pull-up/pull-down resistors
uint32_t pupd = (uint32_t)mode;

View File

@ -34,6 +34,8 @@
#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) {
@ -42,35 +44,12 @@ 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;
uint32_t port_index = (uint32_t)port; // (0=A, 1=B, 2=C, 3=D, 4=E, 5=F, ...)
// Get GPIO structure base address and enable clock
switch (port_index) {
case PortA:
gpio = (GPIO_TypeDef *)GPIOA_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
break;
case PortB:
gpio = (GPIO_TypeDef *)GPIOB_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
break;
case PortC:
gpio = (GPIO_TypeDef *)GPIOC_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
break;
case PortD:
gpio = (GPIO_TypeDef *)GPIOD_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
break;
case PortF:
gpio = (GPIO_TypeDef *)GPIOF_BASE;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
break;
default:
error("GPIO port number is not correct.");
break;
}
// Enable GPIO clock
uint32_t gpio_add = Set_GPIO_Clock(port_index);
gpio = (GPIO_TypeDef *)gpio_add;
// Fill PORT object structure for future use
obj->port = port;

View File

@ -96,7 +96,7 @@ void serial_init(serial_t *obj, PinName tx, PinName rx) {
pinmap_pinout(rx, PinMap_UART_RX);
pin_mode(tx, PullUp);
pin_mode(rx, PullUp);
// Configure UART
obj->baudrate = 9600;
obj->databits = USART_WordLength_8b;

View File

@ -0,0 +1,46 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2014, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#include "sleep_api.h"
#include "cmsis.h"
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);
}