1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-20 10:54:14 +01:00

OP-1275 - Fix CPU usage due to uncleared irq flags

This commit is contained in:
Alessio Morale 2014-09-07 16:29:00 +02:00
parent 94c39caa50
commit 20273e77aa

View File

@ -65,9 +65,14 @@ struct pios_usart_dev {
uint32_t rx_dropped;
};
static bool PIOS_USART_validate(struct pios_usart_dev *usart_dev)
static struct pios_usart_dev *PIOS_USART_validate(uint32_t usart_id)
{
return usart_dev->magic == PIOS_USART_DEV_MAGIC;
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = (usart_dev->magic == PIOS_USART_DEV_MAGIC);
PIOS_Assert(valid);
return usart_dev;
}
#if defined(PIOS_INCLUDE_FREERTOS)
@ -145,7 +150,7 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
usart_dev = (struct pios_usart_dev *)PIOS_USART_alloc();
if (!usart_dev) {
goto out_fail;
return -1;
}
/* Bind the configuration to the device instance */
@ -153,78 +158,54 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* Enable the USART Pins Software Remapping */
if (usart_dev->cfg->remap) {
GPIO_PinAFConfig(usart_dev->cfg->rx.gpio,
__builtin_ctz(usart_dev->cfg->rx.init.GPIO_Pin),
usart_dev->cfg->remap);
GPIO_PinAFConfig(usart_dev->cfg->tx.gpio,
__builtin_ctz(usart_dev->cfg->tx.init.GPIO_Pin),
usart_dev->cfg->remap);
GPIO_PinAFConfig(cfg->rx.gpio, __builtin_ctz(cfg->rx.init.GPIO_Pin), cfg->remap);
GPIO_PinAFConfig(cfg->tx.gpio, __builtin_ctz(cfg->tx.init.GPIO_Pin), cfg->remap);
}
/* Initialize the USART Rx and Tx pins */
GPIO_Init(usart_dev->cfg->rx.gpio, (GPIO_InitTypeDef *)&usart_dev->cfg->rx.init);
GPIO_Init(usart_dev->cfg->tx.gpio, (GPIO_InitTypeDef *)&usart_dev->cfg->tx.init);
GPIO_Init(cfg->rx.gpio, (GPIO_InitTypeDef *)&cfg->rx.init);
GPIO_Init(cfg->tx.gpio, (GPIO_InitTypeDef *)&cfg->tx.init);
/* Enable USART clock */
switch ((uint32_t)usart_dev->cfg->regs) {
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
PIOS_USART_1_id = (uint32_t)usart_dev;
break;
case (uint32_t)USART2:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
PIOS_USART_2_id = (uint32_t)usart_dev;
break;
case (uint32_t)USART3:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
PIOS_USART_3_id = (uint32_t)usart_dev;
break;
}
/* Configure the USART */
USART_Init(usart_dev->cfg->regs, (USART_InitTypeDef *)&usart_dev->cfg->init);
USART_Init(cfg->regs, (USART_InitTypeDef *)&cfg->init);
*usart_id = (uint32_t)usart_dev;
/* Configure USART Interrupts */
switch ((uint32_t)usart_dev->cfg->regs) {
case (uint32_t)USART1:
PIOS_USART_1_id = (uint32_t)usart_dev;
break;
case (uint32_t)USART2:
PIOS_USART_2_id = (uint32_t)usart_dev;
break;
case (uint32_t)USART3:
PIOS_USART_3_id = (uint32_t)usart_dev;
break;
}
NVIC_Init((NVIC_InitTypeDef *)&usart_dev->cfg->irq.init);
USART_ITConfig(usart_dev->cfg->regs, USART_IT_RXNE, ENABLE);
USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE);
NVIC_Init((NVIC_InitTypeDef *)&cfg->irq.init);
USART_ITConfig(cfg->regs, USART_IT_RXNE, ENABLE);
USART_ITConfig(cfg->regs, USART_IT_TXE, ENABLE);
USART_ITConfig(cfg->regs, USART_IT_ORE, DISABLE);
USART_ITConfig(cfg->regs, USART_IT_TC, DISABLE);
/* Enable USART */
USART_Cmd(usart_dev->cfg->regs, ENABLE);
USART_Cmd(cfg->regs, ENABLE);
return 0;
out_fail:
return -1;
}
static void PIOS_USART_RxStart(uint32_t usart_id, __attribute__((unused)) uint16_t rx_bytes_avail)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
const struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
USART_ITConfig(usart_dev->cfg->regs, USART_IT_RXNE, ENABLE);
}
static void PIOS_USART_TxStart(uint32_t usart_id, __attribute__((unused)) uint16_t tx_bytes_avail)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
const struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, ENABLE);
}
@ -236,11 +217,7 @@ static void PIOS_USART_TxStart(uint32_t usart_id, __attribute__((unused)) uint16
*/
static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
const struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
USART_InitTypeDef USART_InitStructure;
@ -258,12 +235,7 @@ static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud)
static void PIOS_USART_RegisterRxCallback(uint32_t usart_id, pios_com_callback rx_in_cb, uint32_t context)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
/*
* Order is important in these assignments since ISR uses _cb
* field to determine if it's ok to dereference _cb and _context
@ -274,11 +246,7 @@ static void PIOS_USART_RegisterRxCallback(uint32_t usart_id, pios_com_callback r
static void PIOS_USART_RegisterTxCallback(uint32_t usart_id, pios_com_callback tx_out_cb, uint32_t context)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
/*
* Order is important in these assignments since ISR uses _cb
@ -290,20 +258,16 @@ static void PIOS_USART_RegisterTxCallback(uint32_t usart_id, pios_com_callback t
static void PIOS_USART_generic_irq_handler(uint32_t usart_id)
{
struct pios_usart_dev *usart_dev = (struct pios_usart_dev *)usart_id;
bool valid = PIOS_USART_validate(usart_dev);
PIOS_Assert(valid);
struct pios_usart_dev *usart_dev = PIOS_USART_validate(usart_id);
/* Force read of dr after sr to make sure to clear error flags */
volatile uint16_t sr = usart_dev->cfg->regs->ISR;
volatile uint8_t dr = usart_dev->cfg->regs->RDR;
/* Check if RXNE flag is set */
bool rx_need_yield = false;
if (sr & USART_ISR_RXNE) {
uint8_t byte = dr;
if(USART_GetITStatus(usart_dev->cfg->regs, USART_IT_RXNE) != RESET) {
uint8_t byte = USART_ReceiveData(usart_dev->cfg->regs) & 0x00FF;
if (usart_dev->rx_in_cb) {
uint16_t rc;
rc = (usart_dev->rx_in_cb)(usart_dev->rx_in_context, &byte, 1, NULL, &rx_need_yield);
@ -316,7 +280,7 @@ static void PIOS_USART_generic_irq_handler(uint32_t usart_id)
/* Check if TXE flag is set */
bool tx_need_yield = false;
if (sr & USART_ISR_TXE) {
if (USART_GetITStatus(usart_dev->cfg->regs, USART_IT_TXE) != RESET) {
if (usart_dev->tx_out_cb) {
uint8_t b;
uint16_t bytes_to_send;
@ -325,7 +289,7 @@ static void PIOS_USART_generic_irq_handler(uint32_t usart_id)
if (bytes_to_send > 0) {
/* Send the byte we've been given */
usart_dev->cfg->regs->TDR = b;
USART_SendData(usart_dev->cfg->regs, b);
} else {
/* No bytes to send, disable TXE interrupt */
USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE);
@ -335,7 +299,8 @@ static void PIOS_USART_generic_irq_handler(uint32_t usart_id)
USART_ITConfig(usart_dev->cfg->regs, USART_IT_TXE, DISABLE);
}
}
USART_ClearITPendingBit(usart_dev->cfg->regs, USART_IT_ORE);
USART_ClearITPendingBit(usart_dev->cfg->regs, USART_IT_TC);
#if defined(PIOS_INCLUDE_FREERTOS)
if (rx_need_yield || tx_need_yield) {
vPortYield();