1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-01 09:24:10 +01:00

LP-512 pios_usart: Shared ports support: Initializing same uart multiple times will return shared driver instance. Added uart configuration locking ioctl.

This commit is contained in:
Vladimir Zidar 2017-05-30 14:50:46 +02:00
parent 45448875d4
commit 1680b436cd
6 changed files with 233 additions and 87 deletions

View File

@ -483,6 +483,12 @@ void PIOS_BOARD_IO_Configure_UART(const struct pios_usart_cfg *hw_config, PIOS_B
PIOS_Assert(0);
}
/* lock uart config */
if (pios_usart_com_driver.ioctl) {
bool lock = true;
pios_usart_com_driver.ioctl(usart_id, PIOS_IOCTL_USART_LOCK_CONFIG, &lock);
}
pios_rcvr_group_map[uart_function_map[function].rcvr_group] = rcvr_id;
}
#endif /* PIOS_INCLUDE_RCVR */

View File

@ -55,6 +55,7 @@ enum PIOS_USART_Inverted {
#define PIOS_IOCTL_USART_GET_DSMBIND COM_IOCTL(COM_IOCTL_TYPE_USART, 7, struct stm32_gpio)
#define PIOS_IOCTL_USART_LOCK_CONFIG COM_IOCTL(COM_IOCTL_TYPE_USART, 8, bool)
#endif /* PIOS_USART_H */

View File

@ -173,6 +173,32 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
PIOS_DEBUG_Assert(usart_id);
PIOS_DEBUG_Assert(cfg);
uint32_t *local_id;
uint8_t irq_channel;
/* Enable USART clock */
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
local_id = &PIOS_USART_1_id;
irq_channel = USART1_IRQn;
break;
case (uint32_t)USART2:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
local_id = &PIOS_USART_2_id;
irq_channel = USART2_IRQn;
break;
#if defined(STM32F072)
case (uint32_t)USART3:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
local_id = &PIOS_USART_3_id;
irq_channel = USART3_4_IRQn;
break;
#endif
default:
goto out_fail;
}
struct pios_usart_dev *usart_dev;
usart_dev = (struct pios_usart_dev *)PIOS_USART_alloc();
@ -182,6 +208,7 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* Bind the configuration to the device instance */
usart_dev->cfg = cfg;
usart_dev->irq_channel = irq_channel;
/* Initialize the comm parameter structure */
USART_StructInit(&usart_dev->init); // 9600 8n1
@ -189,28 +216,8 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* We will set modes later, depending on installed callbacks */
usart_dev->init.USART_Mode = 0;
/* Enable USART clock */
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
PIOS_USART_1_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART1_IRQn;
break;
case (uint32_t)USART2:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
PIOS_USART_2_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART2_IRQn;
break;
#if defined(STM32F072)
case (uint32_t)USART3:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
PIOS_USART_3_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART3_4_IRQn;
break;
#endif
}
*usart_id = (uint32_t)usart_dev;
*local_id = (uint32_t)usart_dev;
PIOS_USART_SetIrqPrio(usart_dev, PIOS_IRQ_PRIO_MID);
@ -218,6 +225,9 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
USART_OverrunDetectionConfig(usart_dev->cfg->regs, USART_OVRDetection_Disable);
return 0;
out_fail:
return -1;
}
static void PIOS_USART_Setup(struct pios_usart_dev *usart_dev)
@ -247,7 +257,15 @@ static void PIOS_USART_Setup(struct pios_usart_dev *usart_dev)
}
/* Write new configuration */
USART_Init(usart_dev->cfg->regs, &usart_dev->init);
{ // fix parity stuff
USART_InitTypeDef init = usart_dev->init;
if ((init.USART_Parity != USART_Parity_No) && (init.USART_WordLength == USART_WordLength_8b)) {
init.USART_WordLength = USART_WordLength_9b;
}
USART_Init(usart_dev->cfg->regs, &init);
}
/*
* Re enable USART.

View File

@ -67,7 +67,7 @@ struct pios_usart_dev {
uint32_t rx_in_context;
pios_com_callback tx_out_cb;
uint32_t tx_out_context;
bool config_locked;
uint32_t rx_dropped;
uint8_t irq_channel;
};
@ -172,6 +172,35 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
PIOS_DEBUG_Assert(usart_id);
PIOS_DEBUG_Assert(cfg);
uint32_t *local_id;
uint8_t irq_channel;
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
local_id = &PIOS_USART_1_id;
irq_channel = USART1_IRQn;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
break;
case (uint32_t)USART2:
local_id = &PIOS_USART_2_id;
irq_channel = USART2_IRQn;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
break;
case (uint32_t)USART3:
local_id = &PIOS_USART_3_id;
irq_channel = USART3_IRQn;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
break;
default:
goto out_fail;
}
if (*local_id) {
/* this port is already open */
*usart_id = *local_id;
return 0;
}
struct pios_usart_dev *usart_dev;
usart_dev = (struct pios_usart_dev *)PIOS_USART_alloc();
@ -181,6 +210,7 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* Bind the configuration to the device instance */
usart_dev->cfg = cfg;
usart_dev->irq_channel = irq_channel;
/* Initialize the comm parameter structure */
USART_StructInit(&usart_dev->init); // 9600 8n1
@ -206,29 +236,11 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
}
#endif
/* Configure USART Interrupts */
switch ((uint32_t)usart_dev->cfg->regs) {
case (uint32_t)USART1:
PIOS_USART_1_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART1_IRQn;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
break;
case (uint32_t)USART2:
PIOS_USART_2_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART2_IRQn;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
break;
case (uint32_t)USART3:
PIOS_USART_3_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART3_IRQn;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
break;
}
*usart_id = (uint32_t)usart_dev;
*local_id = (uint32_t)usart_dev;
PIOS_USART_SetIrqPrio(usart_dev, PIOS_IRQ_PRIO_MID);
*usart_id = (uint32_t)usart_dev;
return 0;
out_fail:
@ -258,7 +270,16 @@ static void PIOS_USART_Setup(struct pios_usart_dev *usart_dev)
}
/* Write new configuration */
USART_Init(usart_dev->cfg->regs, &usart_dev->init);
{ // fix parity stuff
USART_InitTypeDef init = usart_dev->init;
if ((init.USART_Parity != USART_Parity_No) && (init.USART_WordLength == USART_WordLength_8b)) {
init.USART_WordLength = USART_WordLength_9b;
}
USART_Init(usart_dev->cfg->regs, &init);
}
/*
* Re enable USART.
@ -301,6 +322,10 @@ static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud)
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
/* Use our working copy of the usart init structure */
usart_dev->init.USART_BaudRate = baud;
@ -329,6 +354,10 @@ static void PIOS_USART_ChangeConfig(uint32_t usart_id,
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
switch (word_len) {
case PIOS_COM_Word_length_8b:
usart_dev->init.USART_WordLength = USART_WordLength_8b;
@ -519,6 +548,9 @@ static int32_t PIOS_USART_Ioctl(uint32_t usart_id, uint32_t ctl, void *param)
case PIOS_IOCTL_USART_SET_HALFDUPLEX:
USART_HalfDuplexCmd(usart_dev->cfg->regs, *(bool *)param ? ENABLE : DISABLE);
break;
case PIOS_IOCTL_USART_LOCK_CONFIG:
usart_dev->config_locked = *(bool *)param;
break;
default:
return COM_IOCTL_ENOSYS; /* unknown ioctl */
}

View File

@ -65,7 +65,7 @@ struct pios_usart_dev {
uint32_t rx_in_context;
pios_com_callback tx_out_cb;
uint32_t tx_out_context;
bool config_locked;
uint32_t rx_dropped;
uint8_t irq_channel;
};
@ -176,33 +176,33 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
uint32_t *local_id;
uint8_t irq_channel;
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
local_id = &PIOS_USART_1_id;
local_id = &PIOS_USART_1_id;
irq_channel = USART1_IRQn;
break;
case (uint32_t)USART2:
local_id = &PIOS_USART_2_id;
local_id = &PIOS_USART_2_id;
irq_channel = USART2_IRQn;
break;
case (uint32_t)USART3:
local_id = &PIOS_USART_3_id;
local_id = &PIOS_USART_3_id;
irq_channel = USART3_IRQn;
break;
case (uint32_t)UART4:
local_id = &PIOS_UART_4_id;
local_id = &PIOS_UART_4_id;
irq_channel = UART4_IRQn;
break;
case (uint32_t)UART5:
local_id = &PIOS_UART_5_id;
local_id = &PIOS_UART_5_id;
irq_channel = UART5_IRQn;
break;
default:
goto out_fail;
}
if(*local_id) {
if (*local_id) {
/* this port is already open */
*usart_id = *local_id;
return 0;
@ -225,6 +225,8 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* We will set modes later, depending on installed callbacks */
usart_dev->init.USART_Mode = 0;
/* DTR handling? */
*usart_id = (uint32_t)usart_dev;
*local_id = (uint32_t)usart_dev;
@ -266,7 +268,51 @@ static void PIOS_USART_Setup(struct pios_usart_dev *usart_dev)
}
/* Write new configuration */
USART_Init(usart_dev->cfg->regs, &usart_dev->init);
#if 0
const char *dbg_parity = "?";
switch (usart_dev->init.USART_Parity) {
case USART_Parity_No: dbg_parity = "N"; break;
case USART_Parity_Even: dbg_parity = "E"; break;
case USART_Parity_Odd: dbg_parity = "O"; break;
}
const char *dbg_mode = "???";
switch (usart_dev->init.USART_Mode) {
case USART_Mode_Rx: dbg_mode = "rx"; break;
case USART_Mode_Tx: dbg_mode = "tx"; break;
case USART_Mode_Rx | USART_Mode_Tx: dbg_mode = "rx_tx"; break;
}
const char *dbg_flow_control = "???";
switch (usart_dev->init.USART_HardwareFlowControl) {
case USART_HardwareFlowControl_None: dbg_flow_control = "none"; break;
case USART_HardwareFlowControl_RTS: dbg_flow_control = "rts"; break;
case USART_HardwareFlowControl_CTS: dbg_flow_control = "cts"; break;
case USART_HardwareFlowControl_RTS_CTS: dbg_flow_control = "rts_cts"; break;
}
const char *dbg_stop_bits = "???";
switch (usart_dev->init.USART_StopBits) {
case USART_StopBits_1: dbg_stop_bits = "1"; break;
case USART_StopBits_2: dbg_stop_bits = "2"; break;
case USART_StopBits_1_5: dbg_stop_bits = "1.5"; break;
}
DEBUG_PRINTF(0, "PIOS_USART_Setup: 0x%08x %u %u%s%s mode=%s flow_control=%s\r\n",
(uint32_t)usart_dev,
usart_dev->init.USART_BaudRate,
usart_dev->init.USART_WordLength == USART_WordLength_8b ? 8 : 9,
dbg_parity,
dbg_stop_bits,
dbg_mode,
dbg_flow_control);
#endif /* if 0 */
{ // fix parity stuff
USART_InitTypeDef init = usart_dev->init;
if ((init.USART_Parity != USART_Parity_No) && (init.USART_WordLength == USART_WordLength_8b)) {
init.USART_WordLength = USART_WordLength_9b;
}
USART_Init(usart_dev->cfg->regs, &init);
}
/*
* Re enable USART.
@ -308,6 +354,10 @@ static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud)
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
usart_dev->init.USART_BaudRate = baud;
PIOS_USART_Setup(usart_dev);
@ -333,6 +383,10 @@ static void PIOS_USART_ChangeConfig(uint32_t usart_id,
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
switch (word_len) {
case PIOS_COM_Word_length_8b:
usart_dev->init.USART_WordLength = USART_WordLength_8b;
@ -527,6 +581,9 @@ static int32_t PIOS_USART_Ioctl(uint32_t usart_id, uint32_t ctl, void *param)
case PIOS_IOCTL_USART_GET_TXGPIO:
*(struct stm32_gpio *)param = usart_dev->cfg->tx;
break;
case PIOS_IOCTL_USART_LOCK_CONFIG:
usart_dev->config_locked = *(bool *)param;
break;
default:
return -1;
}

View File

@ -72,7 +72,8 @@ struct pios_usart_dev {
uint32_t rx_in_context;
pios_com_callback tx_out_cb;
uint32_t tx_out_context;
uint8_t irq_channel;
bool config_locked;
uint8_t irq_channel;
};
static bool PIOS_USART_validate(struct pios_usart_dev *usart_dev)
@ -196,6 +197,46 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
PIOS_DEBUG_Assert(usart_id);
PIOS_DEBUG_Assert(cfg);
uint32_t *local_id;
uint8_t irq_channel;
switch ((uint32_t)cfg->regs) {
case (uint32_t)USART1:
local_id = &PIOS_USART_1_id;
irq_channel = USART1_IRQn;
break;
case (uint32_t)USART2:
local_id = &PIOS_USART_2_id;
irq_channel = USART2_IRQn;
break;
#if !defined(STM32F411xE)
case (uint32_t)USART3:
local_id = &PIOS_USART_3_id;
irq_channel = USART3_IRQn;
break;
case (uint32_t)UART4:
local_id = &PIOS_USART_4_id;
irq_channel = UART4_IRQn;
break;
case (uint32_t)UART5:
local_id = &PIOS_USART_5_id;
irq_channel = UART5_IRQn;
break;
#endif /* STM32F411xE */
case (uint32_t)USART6:
local_id = &PIOS_USART_6_id;
irq_channel = USART6_IRQn;
break;
default:
goto out_fail;
}
if (*local_id) {
/* this port is already open */
*usart_id = *local_id;
return 0;
}
struct pios_usart_dev *usart_dev;
usart_dev = (struct pios_usart_dev *)PIOS_USART_alloc();
@ -205,6 +246,7 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
/* Bind the configuration to the device instance */
usart_dev->cfg = cfg;
usart_dev->irq_channel = irq_channel;
/* Initialize the comm parameter structure */
USART_StructInit(&usart_dev->init); // 9600 8n1
@ -236,38 +278,10 @@ int32_t PIOS_USART_Init(uint32_t *usart_id, const struct pios_usart_cfg *cfg)
}
#endif
/* Configure USART Interrupts */
switch ((uint32_t)usart_dev->cfg->regs) {
case (uint32_t)USART1:
PIOS_USART_1_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART1_IRQn;
break;
case (uint32_t)USART2:
PIOS_USART_2_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART2_IRQn;
break;
#if !defined(STM32F411xE)
case (uint32_t)USART3:
PIOS_USART_3_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART3_IRQn;
break;
case (uint32_t)UART4:
PIOS_USART_4_id = (uint32_t)usart_dev;
usart_dev->irq_channel = UART4_IRQn;
break;
case (uint32_t)UART5:
PIOS_USART_5_id = (uint32_t)usart_dev;
usart_dev->irq_channel = UART5_IRQn;
break;
#endif /* STM32F411xE */
case (uint32_t)USART6:
PIOS_USART_6_id = (uint32_t)usart_dev;
usart_dev->irq_channel = USART6_IRQn;
break;
}
PIOS_USART_SetIrqPrio(usart_dev, PIOS_IRQ_PRIO_MID);
*usart_id = (uint32_t)usart_dev;
*local_id = (uint32_t)usart_dev;
PIOS_USART_SetIrqPrio(usart_dev, PIOS_IRQ_PRIO_MID);
return 0;
@ -303,7 +317,15 @@ static void PIOS_USART_Setup(struct pios_usart_dev *usart_dev)
}
/* Write new configuration */
USART_Init(usart_dev->cfg->regs, &usart_dev->init);
{ // fix parity stuff
USART_InitTypeDef init = usart_dev->init;
if ((init.USART_Parity != USART_Parity_No) && (init.USART_WordLength == USART_WordLength_8b)) {
init.USART_WordLength = USART_WordLength_9b;
}
USART_Init(usart_dev->cfg->regs, &init);
}
/*
* Re enable USART.
@ -345,6 +367,9 @@ static void PIOS_USART_ChangeBaud(uint32_t usart_id, uint32_t baud)
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
/* Use our working copy of the usart init structure */
usart_dev->init.USART_BaudRate = baud;
@ -374,6 +399,10 @@ static void PIOS_USART_ChangeConfig(uint32_t usart_id,
PIOS_Assert(valid);
if (usart_dev->config_locked) {
return;
}
switch (word_len) {
case PIOS_COM_Word_length_8b:
usart_dev->init.USART_WordLength = USART_WordLength_8b;
@ -575,6 +604,9 @@ static int32_t PIOS_USART_Ioctl(uint32_t usart_id, uint32_t ctl, void *param)
case PIOS_IOCTL_USART_SET_HALFDUPLEX:
USART_HalfDuplexCmd(usart_dev->cfg->regs, *(bool *)param ? ENABLE : DISABLE);
break;
case PIOS_IOCTL_USART_LOCK_CONFIG:
usart_dev->config_locked = *(bool *)param;
break;
default:
return COM_IOCTL_ENOSYS; /* unknown ioctl */
}