1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-01-18 03:52:11 +01:00

exti: rewrite exti layer to improve portability

The exti layer now allows drivers to register interrupt callbacks
during board initialization.  All details of the driver using a
particular EXTI pin have been removed from the EXTI layer so it
can now be used on any board without board-specific modification.

This includes some nice refinements provided by Mike Smith during
initial review.  His original commits have been squashed into this
one.
This commit is contained in:
Stacey Sheldon 2012-01-22 23:23:41 -05:00
parent 64202ce092
commit bfe6676eed
10 changed files with 299 additions and 114 deletions

View File

@ -72,7 +72,7 @@ void PIOS_DEBUG_PinValue4BitL(uint8_t value)
/**
* Report a serious error and halt
*/
void PIOS_DEBUG_Panic(const char *msg)
void PIOS_DEBUG_Panic(const char *msg) __attribute__ ((noreturn))
{
#ifdef PIOS_COM_DEBUG
register int *lr asm("lr"); // Link-register holds the PC of the caller

View File

@ -284,6 +284,4 @@ extern uint32_t pios_com_telem_usb_id;
#define PIOS_USB_DETECT_GPIO_PORT GPIOC
#define PIOS_USB_MAX_DEVS 1
#define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_15
#define PIOS_USB_DETECT_EXTI_LINE EXTI_Line15
#define PIOS_IRQ_USB_PRIORITY PIOS_IRQ_PRIO_MID
#endif /* STM32103CB_AHRS_H_ */

View File

@ -316,8 +316,6 @@ extern uint32_t pios_com_aux_id;
#define PIOS_USB_MAX_DEVS 1
#define PIOS_USB_HID_MAX_DEVS 1
#define PIOS_USB_DETECT_GPIO_PIN GPIO_Pin_4
#define PIOS_USB_DETECT_EXTI_LINE EXTI_Line4
#define PIOS_IRQ_USB_PRIORITY PIOS_IRQ_PRIO_MID
/**
* glue macros for file IO

View File

@ -36,19 +36,11 @@
#error PIOS_EXTI Must be included in the project!
#endif /* PIOS_INCLUDE_EXTI */
#include <pios_exti.h>
/* Glocal Variables */
ConversionTypeTypeDef CurrentRead;
#ifdef PIOS_BMP085_HAS_GPIOS
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreHandle PIOS_BMP085_EOC;
#else
int32_t PIOS_BMP085_EOC;
#endif
#endif /* PIOS_BMP085_HAS_GPIOS */
/* Local Variables */
static BMP085CalibDataTypeDef CalibData;
@ -60,18 +52,69 @@ static volatile uint32_t RawPressure;
static volatile uint32_t Pressure;
static volatile uint16_t Temperature;
#ifdef PIOS_BMP085_HAS_GPIOS
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreHandle PIOS_BMP085_EOC;
#else
int32_t PIOS_BMP085_EOC;
#endif
void PIOS_BMP085_EndOfConversion (void)
{
#if defined(PIOS_INCLUDE_FREERTOS)
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
#endif
/* Read the ADC Value */
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveFromISR(PIOS_BMP085_EOC, &xHigherPriorityTaskWoken);
#else
PIOS_BMP085_EOC=1;
#endif
#if defined(PIOS_INCLUDE_FREERTOS)
/* Yield From ISR if needed */
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
#endif
}
static const struct pios_exti_cfg pios_exti_bmp085_cfg __exti_config = {
.vector = PIOS_BMP085_EndOfConversion,
.line = PIOS_BMP085_EOC_EXTI_LINE,
.pin = {
.gpio = PIOS_BMP085_EOC_GPIO_PORT,
.init = {
.GPIO_Pin = PIOS_BMP085_EOC_GPIO_PIN,
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
},
},
.irq = {
.init = {
.NVIC_IRQChannel = PIOS_BMP085_EOC_IRQn,
.NVIC_IRQChannelPreemptionPriority = PIOS_BMP085_EOC_PRIO,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.exti = {
.init = {
.EXTI_Line = PIOS_BMP085_EOC_EXTI_LINE,
.EXTI_Mode = EXTI_Mode_Interrupt,
.EXTI_Trigger = EXTI_Trigger_Rising,
.EXTI_LineCmd = ENABLE,
},
},
};
#endif /* PIOS_BMP085_HAS_GPIOS */
/**
* Initialise the BMP085 sensor
*/
void PIOS_BMP085_Init(void)
{
#ifdef PIOS_BMP085_HAS_GPIOS
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
#if defined(PIOS_INCLUDE_FREERTOS)
/* Semaphore used by ISR to signal End-Of-Conversion */
vSemaphoreCreateBinary(PIOS_BMP085_EOC);
@ -84,27 +127,12 @@ void PIOS_BMP085_Init(void)
/* Enable EOC GPIO clock */
RCC_APB2PeriphClockCmd(PIOS_BMP085_EOC_CLK | RCC_APB2Periph_AFIO, ENABLE);
/* Configure EOC pin as input floating */
GPIO_InitStructure.GPIO_Pin = PIOS_BMP085_EOC_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(PIOS_BMP085_EOC_GPIO_PORT, &GPIO_InitStructure);
/* Configure the End Of Conversion (EOC) interrupt */
GPIO_EXTILineConfig(PIOS_BMP085_EOC_PORT_SOURCE, PIOS_BMP085_EOC_PIN_SOURCE);
EXTI_InitStructure.EXTI_Line = PIOS_BMP085_EOC_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EOC EXTI Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = PIOS_BMP085_EOC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_BMP085_EOC_PRIO;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
if (PIOS_EXTI_Init(&pios_exti_bmp085_cfg)) {
PIOS_Assert(0);
}
/* Configure XCLR pin as push/pull alternate funtion output */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PIOS_BMP085_XCLR_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(PIOS_BMP085_XCLR_GPIO_PORT, &GPIO_InitStructure);

View File

@ -34,6 +34,8 @@
#if defined(PIOS_INCLUDE_HMC5843)
#include <pios_exti.h>
/* HMC5843 Addresses */
#define PIOS_HMC5843_I2C_ADDR 0x1E
#define PIOS_HMC5843_CONFIG_REG_A (uint8_t)0x00
@ -107,37 +109,48 @@ static void PIOS_HMC5843_Config(PIOS_HMC5843_ConfigTypeDef * HMC5843_Config_Stru
static bool PIOS_HMC5843_Read(uint8_t address, uint8_t * buffer, uint8_t len);
static bool PIOS_HMC5843_Write(uint8_t address, uint8_t buffer);
void PIOS_HMC5843_EndOfConversion (void)
{
pios_hmc5843_data_ready = true;
}
static const struct pios_exti_cfg pios_exti_hmc5843_cfg __exti_config = {
.vector = PIOS_HMC5843_EndOfConversion,
.line = PIOS_HMC5843_DRDY_EXTI_LINE,
.pin = {
.gpio = PIOS_HMC5843_DRDY_GPIO_PORT,
.init = {
.GPIO_Pin = PIOS_HMC5843_DRDY_GPIO_PIN,
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
},
},
.irq = {
.init = {
.NVIC_IRQChannel = PIOS_HMC5843_DRDY_IRQn,
.NVIC_IRQChannelPreemptionPriority = PIOS_HMC5843_DRDY_PRIO,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.exti = {
.init = {
.EXTI_Line = PIOS_HMC5843_DRDY_EXTI_LINE,
.EXTI_Mode = EXTI_Mode_Interrupt,
.EXTI_Trigger = EXTI_Trigger_Rising,
.EXTI_LineCmd = ENABLE,
},
},
};
/**
* @brieft Initialise the HMC5843 sensor
* @brief Initialise the HMC5843 sensor
*/
void PIOS_HMC5843_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable DRDY GPIO clock */
RCC_APB2PeriphClockCmd(PIOS_HMC5843_DRDY_CLK | RCC_APB2Periph_AFIO, ENABLE);
/* Configure EOC pin as input floating */
GPIO_InitStructure.GPIO_Pin = PIOS_HMC5843_DRDY_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(PIOS_HMC5843_DRDY_GPIO_PORT, &GPIO_InitStructure);
/* Configure the End Of Conversion (EOC) interrupt */
GPIO_EXTILineConfig(PIOS_HMC5843_DRDY_PORT_SOURCE, PIOS_HMC5843_DRDY_PIN_SOURCE);
EXTI_InitStructure.EXTI_Line = PIOS_HMC5843_DRDY_EXTI_LINE;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set EOC EXTI Interrupt to the lowest priority */
NVIC_InitStructure.NVIC_IRQChannel = PIOS_HMC5843_DRDY_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_HMC5843_DRDY_PRIO;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
PIOS_EXTI_Init(&pios_exti_hmc5843_cfg);
/* Configure the HMC5843 Sensor */
PIOS_HMC5843_ConfigTypeDef HMC5843_InitStructure;
@ -362,11 +375,6 @@ static bool PIOS_HMC5843_Write(uint8_t address, uint8_t buffer)
return PIOS_I2C_Transfer(PIOS_I2C_MAIN_ADAPTER, txn_list, NELEMENTS(txn_list));
}
void PIOS_HMC5843_IRQHandler(void)
{
pios_hmc5843_data_ready = true;
}
#endif
/**

View File

@ -155,7 +155,7 @@ typedef struct
*/
void EXTI_DeInit(void);
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_Init(const EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct);
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line);
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);

View File

@ -97,7 +97,7 @@ void EXTI_DeInit(void)
* that contains the configuration information for the EXTI peripheral.
* @retval None
*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
void EXTI_Init(const EXTI_InitTypeDef* EXTI_InitStruct)
{
uint32_t tmp = 0;

View File

@ -5,7 +5,6 @@
* @{
* @addtogroup PIOS_EXTI External Interrupt Handlers
* @brief External interrupt handler functions
* @note Currently deals with BMP085 readings
* @{
*
* @file pios_exti.c
@ -35,61 +34,196 @@
#if defined(PIOS_INCLUDE_EXTI)
/**
* Handle external lines 15 to 10 interrupt requests
*/
void EXTI15_10_IRQHandler(void)
/* Map EXTI line to full config */
#define EXTI_MAX_LINES 16
#define PIOS_EXTI_INVALID 0xFF
static uint8_t pios_exti_line_to_cfg_map[EXTI_MAX_LINES] = {
[0 ... EXTI_MAX_LINES-1] = PIOS_EXTI_INVALID,
};
/* Table of exti configs registered at compile time */
extern struct pios_exti_cfg __start__exti __attribute__((weak));
extern struct pios_exti_cfg __stop__exti __attribute__((weak));
static uint8_t PIOS_EXTI_line_to_index (uint32_t line)
{
#if defined(PIOS_INCLUDE_FREERTOS)
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
#endif
#if defined(PIOS_INCLUDE_BMP085) && defined(PIOS_BMP085_HAS_GPIOS)
if (EXTI_GetITStatus(PIOS_BMP085_EOC_EXTI_LINE) != RESET) {
/* Read the ADC Value */
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreGiveFromISR(PIOS_BMP085_EOC, &xHigherPriorityTaskWoken);
#else
PIOS_BMP085_EOC=1;
#endif
/* Clear the EXTI line pending bit */
EXTI_ClearITPendingBit(PIOS_BMP085_EOC_EXTI_LINE);
switch (line) {
case EXTI_Line0: return 0;
case EXTI_Line1: return 1;
case EXTI_Line2: return 2;
case EXTI_Line3: return 3;
case EXTI_Line4: return 4;
case EXTI_Line5: return 5;
case EXTI_Line6: return 6;
case EXTI_Line7: return 7;
case EXTI_Line8: return 8;
case EXTI_Line9: return 9;
case EXTI_Line10: return 10;
case EXTI_Line11: return 11;
case EXTI_Line12: return 12;
case EXTI_Line13: return 13;
case EXTI_Line14: return 14;
case EXTI_Line15: return 15;
}
#endif
#if defined(PIOS_INCLUDE_FREERTOS)
/* Yield From ISR if needed */
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
#endif
PIOS_Assert(0);
return 0xFF;
}
/**
* Handle external lines 9 to 5 interrupt requests
*/
extern void PIOS_HMC5843_IRQHandler(void);
void EXTI9_5_IRQHandler(void)
uint8_t PIOS_EXTI_gpio_port_to_exti_source_port(GPIO_TypeDef * gpio_port)
{
#if defined(PIOS_INCLUDE_HMC5843)
if (EXTI_GetITStatus(PIOS_HMC5843_DRDY_EXTI_LINE) != RESET) {
PIOS_HMC5843_IRQHandler();
EXTI_ClearITPendingBit(PIOS_HMC5843_DRDY_EXTI_LINE);
switch((uint32_t)gpio_port) {
case (uint32_t)GPIOA: return (GPIO_PortSourceGPIOA);
case (uint32_t)GPIOB: return (GPIO_PortSourceGPIOB);
case (uint32_t)GPIOC: return (GPIO_PortSourceGPIOC);
case (uint32_t)GPIOD: return (GPIO_PortSourceGPIOD);
case (uint32_t)GPIOE: return (GPIO_PortSourceGPIOE);
case (uint32_t)GPIOF: return (GPIO_PortSourceGPIOF);
case (uint32_t)GPIOG: return (GPIO_PortSourceGPIOG);
}
#endif
PIOS_Assert(0);
return 0xFF;
}
/**
* Handle external line 4 interrupt requests
*/
#if defined(PIOS_INCLUDE_USB)
void EXTI4_IRQHandler(void)
uint8_t PIOS_EXTI_gpio_pin_to_exti_source_pin(uint32_t gpio_pin)
{
if (EXTI_GetITStatus(PIOS_USB_DETECT_EXTI_LINE) != RESET) {
/* Clear the EXTI line pending bit */
EXTI_ClearITPendingBit(PIOS_USB_DETECT_EXTI_LINE);
switch((uint32_t)gpio_pin) {
case GPIO_Pin_0: return (GPIO_PinSource0);
case GPIO_Pin_1: return (GPIO_PinSource1);
case GPIO_Pin_2: return (GPIO_PinSource2);
case GPIO_Pin_3: return (GPIO_PinSource3);
case GPIO_Pin_4: return (GPIO_PinSource4);
case GPIO_Pin_5: return (GPIO_PinSource5);
case GPIO_Pin_6: return (GPIO_PinSource6);
case GPIO_Pin_7: return (GPIO_PinSource7);
case GPIO_Pin_8: return (GPIO_PinSource8);
case GPIO_Pin_9: return (GPIO_PinSource9);
case GPIO_Pin_10: return (GPIO_PinSource10);
case GPIO_Pin_11: return (GPIO_PinSource11);
case GPIO_Pin_12: return (GPIO_PinSource12);
case GPIO_Pin_13: return (GPIO_PinSource13);
case GPIO_Pin_14: return (GPIO_PinSource14);
case GPIO_Pin_15: return (GPIO_PinSource15);
}
PIOS_Assert(0);
return 0xFF;
}
#endif
int32_t PIOS_EXTI_Init(const struct pios_exti_cfg * cfg)
{
PIOS_Assert(cfg);
PIOS_Assert(&__start__exti);
PIOS_Assert(cfg >= &__start__exti);
PIOS_Assert(cfg < &__stop__exti);
uint8_t cfg_index = cfg - &__start__exti;
/* Connect this config to the requested vector */
uint8_t line_index = PIOS_EXTI_line_to_index(cfg->line);
if (pios_exti_line_to_cfg_map[line_index] != PIOS_EXTI_INVALID) {
/* Someone else already has this mapped */
goto out_fail;
}
/* Bind the config to the exti line */
pios_exti_line_to_cfg_map[line_index] = cfg_index;
/* Initialize the GPIO pin */
GPIO_Init(cfg->pin.gpio, &cfg->pin.init);
/* Set up the EXTI interrupt source */
uint8_t exti_source_port = PIOS_EXTI_gpio_port_to_exti_source_port(cfg->pin.gpio);
uint8_t exti_source_pin = PIOS_EXTI_gpio_pin_to_exti_source_pin(cfg->pin.init.GPIO_Pin);
GPIO_EXTILineConfig(exti_source_port, exti_source_pin);
EXTI_Init(&cfg->exti.init);
/* Enable the interrupt channel */
NVIC_Init(&cfg->irq.init);
return 0;
out_fail:
return -1;
}
static void PIOS_EXTI_generic_irq_handler(uint8_t line_index)
{
uint8_t cfg_index = pios_exti_line_to_cfg_map[line_index];
PIOS_Assert(&__start__exti);
if (cfg_index > NELEMENTS(pios_exti_line_to_cfg_map) ||
cfg_index == PIOS_EXTI_INVALID) {
/* Unconfigured interrupt just fired! */
return;
}
struct pios_exti_cfg * cfg = &__start__exti + cfg_index;
cfg->vector();
}
/* Bind Interrupt Handlers */
#define PIOS_EXTI_HANDLE_LINE(line) \
if (EXTI_GetITStatus(EXTI_Line##line) != RESET) { \
EXTI_ClearITPendingBit(EXTI_Line##line); \
PIOS_EXTI_generic_irq_handler(line); \
}
static void PIOS_EXTI_0_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(0);
}
void EXTI0_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_0_irq_handler")));
static void PIOS_EXTI_1_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(1);
}
void EXTI1_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_1_irq_handler")));
static void PIOS_EXTI_2_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(2);
}
void EXTI2_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_2_irq_handler")));
static void PIOS_EXTI_3_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(3);
}
void EXTI3_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_3_irq_handler")));
static void PIOS_EXTI_4_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(4);
}
void EXTI4_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_4_irq_handler")));
static void PIOS_EXTI_9_5_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(5);
PIOS_EXTI_HANDLE_LINE(6);
PIOS_EXTI_HANDLE_LINE(7);
PIOS_EXTI_HANDLE_LINE(8);
PIOS_EXTI_HANDLE_LINE(9);
}
void EXTI9_5_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_9_5_irq_handler")));
static void PIOS_EXTI_15_10_irq_handler (void)
{
PIOS_EXTI_HANDLE_LINE(10);
PIOS_EXTI_HANDLE_LINE(11);
PIOS_EXTI_HANDLE_LINE(12);
PIOS_EXTI_HANDLE_LINE(13);
PIOS_EXTI_HANDLE_LINE(14);
PIOS_EXTI_HANDLE_LINE(15);
}
void EXTI15_10_IRQHandler(void) __attribute__ ((alias ("PIOS_EXTI_15_10_irq_handler")));
#endif
/**

View File

@ -33,6 +33,21 @@
/* Public Functions */
#include <pios_stm32.h>
struct pios_exti_cfg {
void (* vector)(void);
uint32_t line; /* use EXTI_LineN macros */
struct stm32_gpio pin;
struct stm32_irq irq;
struct stm32_exti exti;
};
/* must be added to any pios_exti_cfg definition for it to be valid */
#define __exti_config __attribute__((section("_exti")))
extern int32_t PIOS_EXTI_Init(const struct pios_exti_cfg * cfg);
#endif /* PIOS_EXTI_H */
/**

View File

@ -36,6 +36,10 @@ struct stm32_irq {
NVIC_InitTypeDef init;
};
struct stm32_exti {
EXTI_InitTypeDef init;
};
struct stm32_dma_chan {
DMA_Channel_TypeDef *channel;
DMA_InitTypeDef init;