More work on RP SIO driver. Support for peripheral resets.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14089 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-03-27 08:20:09 +00:00
parent 525f89f0e3
commit d6c3fe0d46
4 changed files with 226 additions and 278 deletions

View File

@ -84,6 +84,12 @@ typedef enum {
* @name Peripheral structures
* @{
*/
typedef struct {
__IO uint32_t RESET;
__IO uint32_t WDSEL;
__I uint32_t RESET_DONE;
} RESETS_TypeDef;
typedef struct {
__IO uint32_t TIMEHW;
__IO uint32_t TIMELW;
@ -143,20 +149,52 @@ typedef struct {
#define APBPERIPH_BASE 0x40000000U
#define AHBPERIPH_BASE 0x50000000U
#define __IOPORT_BASE 0xA0000000U
#define __TIMER_BASE (APBPERIPH_BASE + 0x00054000)
#define __UART0_BASE (APBPERIPH_BASE + 0x00034000)
#define __UART1_BASE (APBPERIPH_BASE + 0x00038000)
#define __RESETS_BASE (APBPERIPH_BASE + 0x0000C000U)
#define __TIMER_BASE (APBPERIPH_BASE + 0x00054000U)
#define __UART0_BASE (APBPERIPH_BASE + 0x00034000U)
#define __UART1_BASE (APBPERIPH_BASE + 0x00038000U)
/** @} */
/**
* @name Peripherals
* @{
*/
#define RESETS ((RESETS_TypeDef *)__RESETS_BASE)
#define TIMER ((TIMER_TypeDef *)__TIMER_BASE)
#define UART0 ((UART_TypeDef *)__UART0_BASE)
#define UART1 ((UART_TypeDef *)__UART1_BASE)
/** @} */
/**
* @name RESETS bits definitions
*/
#define RESETS_ALLREG_USBCTRL (1U << 24)
#define RESETS_ALLREG_UART1 (1U << 23)
#define RESETS_ALLREG_UART0 (1U << 22)
#define RESETS_ALLREG_TIMER (1U << 21)
#define RESETS_ALLREG_TBMAN (1U << 20)
#define RESETS_ALLREG_SYSINFO (1U << 19)
#define RESETS_ALLREG_SYSCFG (1U << 18)
#define RESETS_ALLREG_SPI1 (1U << 17)
#define RESETS_ALLREG_SPI0 (1U << 16)
#define RESETS_ALLREG_RTC (1U << 15)
#define RESETS_ALLREG_PWM (1U << 14)
#define RESETS_ALLREG_PLL_USB (1U << 13)
#define RESETS_ALLREG_PLL_SYS (1U << 12)
#define RESETS_ALLREG_PIO1 (1U << 11)
#define RESETS_ALLREG_PIO0 (1U << 10)
#define RESETS_ALLREG_PADS_QSPI (1U << 9)
#define RESETS_ALLREG_PADS_BANK0 (1U << 8)
#define RESETS_ALLREG_JTAG (1U << 7)
#define RESETS_ALLREG_IO_QSPI (1U << 6)
#define RESETS_ALLREG_IO_BANK0 (1U << 5)
#define RESETS_ALLREG_I2C1 (1U << 4)
#define RESETS_ALLREG_I2C0 (1U << 3)
#define RESETS_ALLREG_DMA (1U << 2)
#define RESETS_ALLREG_BUSCTRL (1U << 1)
#define RESETS_ALLREG_ADC (1U << 0)
/** @} */
/**
* @name TIMER bits definitions
*/
@ -455,39 +493,73 @@ typedef struct {
#define UART_UARTRIS_RIRMIS_Msk (1U << UART_UARTRIS_RIRMIS_Pos)
#define UART_UARTRIS_RIRMIS UART_UARTIMSC_RIRMIS_Msk
#define UART_UARTMIS_OEMIS_Pos 10U
#define UART_UARTMIS_OEMIS_Msk (1U << UART_UARTMIS_OEMIS_Pos)
#define UART_UARTMIS_OEMIS UART_UARTMIS_OEMIS_Msk
#define UART_UARTMIS_BEMIS_Pos 9U
#define UART_UARTMIS_BEMIS_Msk (1U << UART_UARTMIS_BEMIS_Pos)
#define UART_UARTMIS_BEMIS UART_UARTMIS_BEMIS_Msk
#define UART_UARTMIS_PEMIS_Pos 8U
#define UART_UARTMIS_PEMIS_Msk (1U << UART_UARTMIS_PEMIS_Pos)
#define UART_UARTMIS_PEMIS UART_UARTMIS_PEMIS_Msk
#define UART_UARTMIS_FEMIS_Pos 7U
#define UART_UARTMIS_FEMIS_Msk (1U << UART_UARTMIS_FEMIS_Pos)
#define UART_UARTMIS_FEMIS UART_UARTMIS_FEMIS_Msk
#define UART_UARTMIS_RTMIS_Pos 6U
#define UART_UARTMIS_RTMIS_Msk (1U << UART_UARTMIS_RTMIS_Pos)
#define UART_UARTMIS_RTMIS UART_UARTMIS_RTMIS_Msk
#define UART_UARTMIS_TXMIS_Pos 5U
#define UART_UARTMIS_TXMIS_Msk (1U << UART_UARTMIS_TXMIS_Pos)
#define UART_UARTMIS_TXMIS UART_UARTMIS_TXMIS_Msk
#define UART_UARTMIS_RXMIS_Pos 4U
#define UART_UARTMIS_RXMIS_Msk (1U << UART_UARTMIS_RXMIS_Pos)
#define UART_UARTMIS_RXMIS UART_UARTMIS_RXMIS_Msk
#define UART_UARTMIS_DSRMMIS_Pos 3U
#define UART_UARTMIS_DSRMMIS_Msk (1U << UART_UARTMIS_DSRMMIS_Pos)
#define UART_UARTMIS_DSRRMIS UART_UARTMIS_DSRMMIS_Msk
#define UART_UARTMIS_DCDMMIS_Pos 2U
#define UART_UARTMIS_DCDMMIS_Msk (1U << UART_UARTMIS_DCDMMIS_Pos)
#define UART_UARTMIS_DCDMMIS UART_UARTMIS_DCDMMIS_Msk
#define UART_UARTMIS_CTSMMIS_Pos 1U
#define UART_UARTMIS_CTSMMIS_Msk (1U << UART_UARTMIS_CTSMMIS_Pos)
#define UART_UARTMIS_CTSMMIS UART_UARTMIS_CTSMMIS_Msk
#define UART_UARTMIS_RIMMIS_Pos 0U
#define UART_UARTMIS_RIMMIS_Msk (1U << UART_UARTMIS_RIMMIS_Pos)
#define UART_UARTMIS_RIMMIS UART_UARTIMSC_RIMMIS_Msk
#define UART_UARTICR_OEIC_Pos 10U
#define UART_UARTICR_OEIC_Msk (1U << UART_UARTICR_OEIC_Pos)
#define UART_UARTICR_OEIM UART_UARTICR_OEIC_Msk
#define UART_UARTICR_OEIC UART_UARTICR_OEIC_Msk
#define UART_UARTICR_BEIC_Pos 9U
#define UART_UARTICR_BEIC_Msk (1U << UART_UARTICR_BEIC_Pos)
#define UART_UARTICR_BEIM UART_UARTICR_BEIC_Msk
#define UART_UARTICR_BEIC UART_UARTICR_BEIC_Msk
#define UART_UARTICR_PEIC_Pos 8U
#define UART_UARTICR_PEIC_Msk (1U << UART_UARTICR_PEIC_Pos)
#define UART_UARTICR_PEIM UART_UARTICR_PEIC_Msk
#define UART_UARTICR_PEIC UART_UARTICR_PEIC_Msk
#define UART_UARTICR_FEIC_Pos 7U
#define UART_UARTICR_FEIC_Msk (1U << UART_UARTICR_FEIC_Pos)
#define UART_UARTICR_FEIM UART_UARTICR_FEIC_Msk
#define UART_UARTICR_FEIC UART_UARTICR_FEIC_Msk
#define UART_UARTICR_RTIC_Pos 6U
#define UART_UARTICR_RTIC_Msk (1U << UART_UARTICR_RTIC_Pos)
#define UART_UARTICR_RTIM UART_UARTICR_RTIC_Msk
#define UART_UARTICR_RTIC UART_UARTICR_RTIC_Msk
#define UART_UARTICR_TXIC_Pos 5U
#define UART_UARTICR_TXIC_Msk (1U << UART_UARTICR_TXIC_Pos)
#define UART_UARTICR_TXIM UART_UARTICR_TXIC_Msk
#define UART_UARTICR_TXIC UART_UARTICR_TXIC_Msk
#define UART_UARTICR_RXIC_Pos 4U
#define UART_UARTICR_RXIC_Msk (1U << UART_UARTICR_RXIC_Pos)
#define UART_UARTICR_RXIM UART_UARTICR_RXIC_Msk
#define UART_UARTICR_RXIC UART_UARTICR_RXIC_Msk
#define UART_UARTICR_DSRMIC_Pos 3U
#define UART_UARTICR_DSRMIC_Msk (1U << UART_UARTICR_DSRMIC_Pos)
#define UART_UARTICR_DSRMIM UART_UARTICR_DSRMIC_Msk
#define UART_UARTICR_DSRMIC UART_UARTICR_DSRMIC_Msk
#define UART_UARTICR_DCDMIC_Pos 2U
#define UART_UARTICR_DCDMIC_Msk (1U << UART_UARTICR_DCDMIC_Pos)
#define UART_UARTICR_DCDMIM UART_UARTICR_DCDMIC_Msk
#define UART_UARTICR_DCDMIC UART_UARTICR_DCDMIC_Msk
#define UART_UARTICR_CTSMIC_Pos 1U
#define UART_UARTICR_CTSMIC_Msk (1U << UART_UARTICR_CTSMIC_Pos)
#define UART_UARTICR_CTSMIM UART_UARTICR_CTSMIC_Msk
#define UART_UARTICR_CTSMIC UART_UARTICR_CTSMIC_Msk
#define UART_UARTICR_RIMIC_Pos 0U
#define UART_UARTICR_RIMIC_Msk (1U << UART_UARTICR_RIMIC_Pos)
#define UART_UARTICR_RIMIM UART_UARTICR_RIMIC_Msk
#define UART_UARTICR_RIMIC UART_UARTICR_RIMIC_Msk
#define UART_UARTDMACR_DMAONERR_Pos 2U
#define UART_UARTDMACR_DMAONERR_Msk (1U << UART_UARTDMACR_DMAONERR_Pos)

View File

@ -30,6 +30,13 @@
/* Driver local definitions. */
/*===========================================================================*/
#define UART_LCRH_CFG_FORBIDDEN (UART_UARTLCR_H_BRK)
#define UART_CR_CFG_FORBIDDEN (UART_UARTCR_RXE | \
UART_UARTCR_TXE | \
UART_UARTCR_SIRLP | \
UART_UARTCR_SIREN | \
UART_UARTCR_UARTEN)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@ -57,68 +64,79 @@ SIODriver SIOD2;
* @note In this implementation it is: 38400-8-N-1.
*/
static const SIOConfig default_config = {
.baud = SIO_DEFAULT_BITRATE
.baud = SIO_DEFAULT_BITRATE,
.UARTLCR_H = UART_UARTLCR_H_WLEN_8BITS | UART_UARTLCR_H_FEN,
.UARTCR = 0U,
.UARTIFLS = UART_UARTIFLS_RXIFLSEL_1_2F | UART_UARTIFLS_TXIFLSEL_1_2E,
.UARTDMACR = 0U
};
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
__STATIC_INLINE void usart_enable_rx_irq(SIODriver *siop) {
__STATIC_INLINE void uart_enable_rx_irq(SIODriver *siop) {
#if SIO_USE_SYNCHRONIZATION == TRUE
siop->usart->CR1 |= USART_CR1_RXNEIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_RXIM;
#else
if (siop->operation->rx_cb != NULL) {
siop->usart->CR1 |= USART_CR1_RXNEIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_RXIM;
}
#endif
}
__STATIC_INLINE void usart_enable_rx_evt_irq(SIODriver *siop) {
__STATIC_INLINE void uart_enable_rx_evt_irq(SIODriver *siop) {
#if SIO_USE_SYNCHRONIZATION == TRUE
siop->usart->CR1 |= USART_CR1_PEIE;
siop->usart->CR2 |= USART_CR2_LBDIE;
siop->usart->CR3 |= USART_CR3_EIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_OEIM | UART_UARTIMSC_BEIM |
UART_UARTIMSC_PEIM | UART_UARTIMSC_FEIM;
#else
if (siop->operation->rx_evt_cb != NULL) {
siop->usart->CR1 |= USART_CR1_PEIE;
siop->usart->CR2 |= USART_CR2_LBDIE;
siop->usart->CR3 |= USART_CR3_EIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_OEIM | UART_UARTIMSC_BEIM |
UART_UARTIMSC_PEIM | UART_UARTIMSC_FEIM;
}
#endif
}
__STATIC_INLINE void usart_enable_tx_irq(SIODriver *siop) {
__STATIC_INLINE void uart_enable_tx_irq(SIODriver *siop) {
#if SIO_USE_SYNCHRONIZATION == TRUE
siop->usart->CR1 |= USART_CR1_TXEIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_TXIM;
#else
if (siop->operation->tx_cb != NULL) {
siop->usart->CR1 |= USART_CR1_TXEIE;
}
#endif
}
__STATIC_INLINE void usart_enable_tx_end_irq(SIODriver *siop) {
#if SIO_USE_SYNCHRONIZATION == TRUE
siop->usart->CR1 |= USART_CR1_TCIE;
#else
if (siop->operation->tx_end_cb != NULL) {
siop->usart->CR1 |= USART_CR1_TCIE;
siop->uart->UARTIMSC |= UART_UARTIMSC_TXIM;
}
#endif
}
/**
* @brief USART initialization.
* @brief UART initialization.
* @details This function must be invoked with interrupts disabled.
*
* @param[in] siop pointer to a @p SIODriver object
*/
__STATIC_INLINE void usart_init(SIODriver *siop) {
__STATIC_INLINE void uart_init(SIODriver *siop) {
uint32_t clock, div, idiv, fdiv;
clock = hal_lld_get_clock(clk_peri);
osalDbgAssert(clock > 0U, "no clock");
div = (8U * clock) / siop->config->baud;
idiv = div >> 7;
fdiv = ((div & 0x7FU) + 1U) / 2U;
osalDbgAssert((idiv > 0U) && (idiv <= 0xFFFFU), "invalid baud rate");
siop->uart->UARTIBRD = idiv;
siop->uart->UARTFBRD = fdiv;
/* Registers settings, the LCR_H write also latches dividers values.*/
siop->uart->UARTLCR_H = siop->config->UARTLCR_H & ~UART_LCRH_CFG_FORBIDDEN;
siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN;
#if 0
USART_TypeDef *u = siop->usart;
uint32_t presc, brr;
@ -157,6 +175,7 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
u->CR1 = siop->config->cr1 & ~USART_CR1_CFG_FORBIDDEN;
u->CR2 = siop->config->cr2 & ~USART_CR2_CFG_FORBIDDEN;
u->CR3 = siop->config->cr3 & ~USART_CR3_CFG_FORBIDDEN;
#endif
}
/*===========================================================================*/
@ -175,52 +194,14 @@ __STATIC_INLINE void usart_init(SIODriver *siop) {
void sio_lld_init(void) {
/* Driver instances initialization.*/
#if RP_SIO_USE_USART1 == TRUE
#if RP_SIO_USE_UART0 == TRUE
sioObjectInit(&SIOD1);
SIOD1.usart = USART1;
SIOD1.clock = RP_USART1CLK;
SIOD1.uart = UART0;
#endif
#if RP_SIO_USE_USART2 == TRUE
#if RP_SIO_USE_UART1 == TRUE
sioObjectInit(&SIOD2);
SIOD2.usart = USART2;
SIOD2.clock = RP_USART2CLK;
SIOD2.uart = UART1;
#endif
#if RP_SIO_USE_USART3 == TRUE
sioObjectInit(&SIOD3);
SIOD3.usart = USART3;
SIOD3.clock = RP_USART3CLK;
#endif
#if RP_SIO_USE_UART4 == TRUE
sioObjectInit(&SIOD4);
SIOD4.usart = UART4;
SIOD4.clock = RP_UART4CLK;
#endif
#if RP_SIO_USE_UART5 == TRUE
sioObjectInit(&SIOD5);
SIOD5.usart = UART5;
SIOD5.clock = RP_UART5CLK;
#endif
#if RP_SIO_USE_USART6 == TRUE
sioObjectInit(&SIOD6);
SIOD6.usart = USART6;
SIOD6.clock = RP_USART6CLK;
#endif
#if RP_SIO_USE_UART7 == TRUE
sioObjectInit(&SIOD7);
SIOD7.usart = UART7;
SIOD7.clock = RP_UART7CLK;
#endif
#if RP_SIO_USE_UART8 == TRUE
sioObjectInit(&SIOD8);
SIOD8.usart = UART8;
SIOD8.clock = RP_UART8CLK;
#endif
#if RP_SIO_USE_LPUART1 == TRUE
sioObjectInit(&LPSIOD1);
LPSIOD1.usart = LPUART1;
LPSIOD1.clock = RP_LPUART1CLK;
#endif
}
/**
@ -246,62 +227,18 @@ bool sio_lld_start(SIODriver *siop) {
/* Enables the peripheral.*/
if (false) {
}
#if RP_SIO_USE_USART1 == TRUE
#if RP_SIO_USE_UART0 == TRUE
else if (&SIOD1 == siop) {
rccResetUSART1();
rccEnableUSART1(true);
hal_lld_peripheral_unreset(RESETS_ALLREG_UART0);
}
#endif
#if RP_SIO_USE_USART2 == TRUE
#if RP_SIO_USE_UART1 == TRUE
else if (&SIOD2 == siop) {
rccResetUSART2();
rccEnableUSART2(true);
}
#endif
#if RP_SIO_USE_USART3 == TRUE
else if (&SIOD3 == siop) {
rccResetUSART3();
rccEnableUSART3(true);
}
#endif
#if RP_SIO_USE_UART4 == TRUE
else if (&SIOD4 == siop) {
rccResetUART4();
rccEnableUART4(true);
}
#endif
#if RP_SIO_USE_UART5 == TRUE
else if (&SIOD5 == siop) {
rccResetUART5();
rccEnableUART5(true);
}
#endif
#if RP_SIO_USE_USART6 == TRUE
else if (&SIOD6 == siop) {
rccResetUSART6();
rccEnableUSART6(true);
}
#endif
#if RP_SIO_USE_UART7 == TRUE
else if (&SIOD7 == siop) {
rccResetUART7();
rccEnableUART7(true);
}
#endif
#if RP_SIO_USE_UART8 == TRUE
else if (&SIOD8 == siop) {
rccResetUART8();
rccEnableUART8(true);
}
#endif
#if RP_SIO_USE_LPUART1 == TRUE
else if (&LPSIOD1 == siop) {
rccResetLPUART1();
rccEnableLPUART1(true);
hal_lld_peripheral_unreset(RESETS_ALLREG_UART1);
}
#endif
else {
osalDbgAssert(false, "invalid USART instance");
osalDbgAssert(false, "invalid SIO instance");
}
/* Driver object low level initializations.*/
@ -314,7 +251,7 @@ bool sio_lld_start(SIODriver *siop) {
}
/* Configures the peripheral.*/
usart_init(siop);
uart_init(siop);
return false;
}
@ -335,62 +272,20 @@ void sio_lld_stop(SIODriver *siop) {
/* Disables the peripheral.*/
if (false) {
}
#if RP_SIO_USE_USART1 == TRUE
#if RP_SIO_USE_UART0 == TRUE
else if (&SIOD1 == siop) {
rccResetUSART1();
rccDisableUSART1();
hal_lld_peripheral_reset(RESETS_ALLREG_UART0);
// rccDisableUSART1();
}
#endif
#if RP_SIO_USE_USART2 == TRUE
#if RP_SIO_USE_UART1 == TRUE
else if (&SIOD2 == siop) {
rccResetUSART2();
rccDisableUSART2();
}
#endif
#if RP_SIO_USE_USART3 == TRUE
else if (&SIOD3 == siop) {
rccResetUSART3();
rccDisableUSART3();
}
#endif
#if RP_SIO_USE_UART4 == TRUE
else if (&SIOD4 == siop) {
rccResetUART4();
rccDisableUART4();
}
#endif
#if RP_SIO_USE_UART5 == TRUE
else if (&SIOD5 == siop) {
rccResetUART5();
rccDisableUART5();
}
#endif
#if RP_SIO_USE_USART6 == TRUE
else if (&SIOD6 == siop) {
rccResetUSART6();
rccDisableUSART6();
}
#endif
#if RP_SIO_USE_UART7 == TRUE
else if (&SIOD7 == siop) {
rccResetUART7();
rccDisableUART7();
}
#endif
#if RP_SIO_USE_UART8 == TRUE
else if (&SIOD8 == siop) {
rccResetUART8();
rccDisableUART8();
}
#endif
#if RP_SIO_USE_LPUART1 == TRUE
else if (&LPSIOD1 == siop) {
rccResetLPUART1();
rccDisableLPUART1();
hal_lld_peripheral_reset(RESETS_ALLREG_UART1);
// rccDisableUSART2();
}
#endif
else {
osalDbgAssert(false, "invalid USART instance");
osalDbgAssert(false, "invalid SIO instance");
}
}
}
@ -403,43 +298,40 @@ void sio_lld_stop(SIODriver *siop) {
* @api
*/
void sio_lld_start_operation(SIODriver *siop) {
uint32_t cr1irq, cr2irq, cr3irq;
uint32_t imsc;
#if SIO_USE_SYNCHRONIZATION == TRUE
/* With synchronization all interrupts are required.*/
cr1irq = USART_CR1_RXNEIE | USART_CR1_TXEIE | USART_CR1_PEIE |
USART_CR1_TCIE | USART_CR1_IDLEIE;
cr2irq = USART_CR2_LBDIE;
cr3irq = USART_CR3_EIE;
imsc = UART_UARTIMSC_OEIM | UART_UARTIMSC_BEIM |
UART_UARTIMSC_PEIM | UART_UARTIMSC_FEIM |
UART_UARTIMSC_RXIM | UART_UARTIMSC_RTIM |
UART_UARTIMSC_TXIM;
#else
/* When using just callbacks we can select only those really required.*/
cr1irq = 0U;
cr2irq = 0U;
cr3irq = 0U;
imsc = 0U;
if (siop->operation->rx_cb != NULL) {
cr1irq |= USART_CR1_RXNEIE;
imsc |= UART_UARTIMSC_RXIM;
}
if (siop->operation->rx_idle_cb != NULL) {
cr1irq |= USART_CR1_IDLEIE;
imsc |= UART_UARTIMSC_RTIM;
}
if (siop->operation->tx_cb != NULL) {
cr1irq |= USART_CR1_TXEIE;
imsc |= UART_UARTIMSC_TXIM;
}
if (siop->operation->tx_end_cb != NULL) {
cr1irq |= USART_CR1_TCIE;
osalDbgAssert(false, "unsupported callback");
}
if (siop->operation->rx_evt_cb != NULL) {
cr1irq |= USART_CR1_PEIE;
cr2irq |= USART_CR2_LBDIE;
cr3irq |= USART_CR3_EIE;
imsc |= UART_UARTIMSC_OEIM | UART_UARTIMSC_BEIM |
UART_UARTIMSC_PEIM | UART_UARTIMSC_FEIM;
}
#endif
/* Setting up the operation.*/
siop->usart->ICR = siop->usart->ISR;
siop->usart->CR2 |= cr2irq;
siop->usart->CR3 |= cr3irq;
siop->usart->CR1 |= cr1irq | USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
siop->uart->UARTICR = siop->uart->UARTRIS;
siop->uart->UARTIMSC |= imsc;
siop->uart->UARTCR = siop->config->UARTCR |
UART_UARTCR_RXE | UART_UARTCR_TXE | UART_UARTCR_UARTEN;
}
/**
@ -452,9 +344,8 @@ void sio_lld_start_operation(SIODriver *siop) {
void sio_lld_stop_operation(SIODriver *siop) {
/* Stop operation.*/
siop->usart->CR1 &= USART_CR1_CFG_FORBIDDEN;
siop->usart->CR2 &= USART_CR2_CFG_FORBIDDEN;
siop->usart->CR3 &= USART_CR3_CFG_FORBIDDEN;
siop->uart->UARTIMSC = 0U;
siop->uart->UARTCR = siop->config->UARTCR & ~UART_CR_CFG_FORBIDDEN;
}
/**
@ -467,31 +358,28 @@ void sio_lld_stop_operation(SIODriver *siop) {
*/
sio_events_mask_t sio_lld_get_and_clear_events(SIODriver *siop) {
sio_events_mask_t evtmask;
uint32_t isr;
uint32_t ris;
/* Getting and clearing all relevant ISR flags (and only those).*/
isr = siop->usart->ISR & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE |
USART_ISR_ORE | USART_ISR_NE);
siop->usart->ICR = isr;
ris = siop->uart->UARTRIS & (UART_UARTRIS_OERIS | UART_UARTRIS_BERIS |
UART_UARTRIS_PERIS | UART_UARTRIS_FERIS);
siop->uart->UARTICR = ris;
/* Status flags cleared, now the related interrupts can be enabled again.*/
usart_enable_rx_evt_irq(siop);
uart_enable_rx_evt_irq(siop);
/* Translating the status flags in SIO events.*/
evtmask = 0U;
if ((isr & USART_ISR_LBDF) != 0U) {
if ((ris & UART_UARTRIS_BERIS) != 0U) {
evtmask |= SIO_BREAK_DETECTED;
}
if ((isr & USART_ISR_ORE) != 0U) {
if ((ris & UART_UARTRIS_OERIS) != 0U) {
evtmask |= SIO_OVERRUN_ERROR;
}
if ((isr & USART_ISR_NE) != 0U) {
evtmask |= SIO_NOISE_ERROR;
}
if ((isr & USART_ISR_FE) != 0U) {
if ((ris & UART_UARTRIS_FERIS) != 0U) {
evtmask |= SIO_FRAMING_ERROR;
}
if ((isr & USART_ISR_PE) != 0U) {
if ((ris & UART_UARTRIS_PERIS) != 0U) {
evtmask |= SIO_PARITY_ERROR;
}
@ -517,7 +405,7 @@ size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n) {
/* If the RX FIFO has been emptied then the interrupt is enabled again.*/
if (sio_lld_is_rx_empty(siop)) {
usart_enable_rx_irq(siop);
uart_enable_rx_irq(siop);
break;
}
@ -526,7 +414,7 @@ size_t sio_lld_read(SIODriver *siop, uint8_t *buffer, size_t n) {
break;
}
*buffer++ = (uint8_t)siop->usart->RDR;
*buffer++ = (uint8_t)siop->uart->UARTDR;
rd++;
}
@ -552,7 +440,7 @@ size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n) {
/* If the TX FIFO has been filled then the interrupt is enabled again.*/
if (sio_lld_is_tx_full(siop)) {
usart_enable_tx_irq(siop);
uart_enable_tx_irq(siop);
break;
}
@ -561,12 +449,12 @@ size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n) {
break;
}
siop->usart->TDR = (uint32_t)*buffer++;
siop->uart->UARTDR = (uint32_t)*buffer++;
wr++;
}
/* The transmit complete interrupt is always re-enabled on write.*/
usart_enable_tx_end_irq(siop);
/* none */
return wr;
}
@ -583,11 +471,11 @@ size_t sio_lld_write(SIODriver *siop, const uint8_t *buffer, size_t n) {
msg_t sio_lld_get(SIODriver *siop) {
msg_t msg;
msg = (msg_t)siop->usart->RDR;
msg = (msg_t)(siop->uart->UARTDR & 0xFFU);
/* If the RX FIFO has been emptied then the interrupt is enabled again.*/
if (sio_lld_is_rx_empty(siop)) {
usart_enable_rx_irq(siop);
uart_enable_rx_irq(siop);
}
return msg;
@ -604,15 +492,15 @@ msg_t sio_lld_get(SIODriver *siop) {
*/
void sio_lld_put(SIODriver *siop, uint_fast16_t data) {
siop->usart->TDR = data;
siop->uart->UARTDR = data;
/* If the TX FIFO has been filled then the interrupt is enabled again.*/
if (sio_lld_is_tx_full(siop)) {
usart_enable_tx_irq(siop);
uart_enable_tx_irq(siop);
}
/* The transmit complete interrupt is always re-enabled on write.*/
usart_enable_tx_end_irq(siop);
/* none */
}
/**
@ -646,61 +534,49 @@ msg_t sio_lld_control(SIODriver *siop, unsigned int operation, void *arg) {
* @notapi
*/
void sio_lld_serve_interrupt(SIODriver *siop) {
USART_TypeDef *u = siop->usart;
uint32_t isr, cr1, cr3, evtmask;
UART_TypeDef *u = siop->uart;
uint32_t mis, msc, evtmask;
osalDbgAssert(siop->state == SIO_ACTIVE, "invalid state");
/* Note, ISR flags are just read but not cleared, ISR sources are
disabled instead.*/
isr = u->ISR;
mis = u->UARTMIS;
/* One read on control registers.*/
cr1 = u->CR1;
cr3 = u->CR3;
msc = u->UARTIMSC;
/* Enabled errors/events handling.*/
evtmask = isr & (USART_ISR_PE | USART_ISR_LBDF | USART_ISR_FE |
USART_ISR_ORE | USART_ISR_NE);
evtmask = mis & (UART_UARTMIS_OEMIS | UART_UARTMIS_BEMIS |
UART_UARTMIS_PEMIS | UART_UARTMIS_FEMIS);
if (evtmask != 0U) {
uint32_t cr2;
/* One read on control registers.*/
cr2 = u->CR2;
/* Disabling event sources.*/
msc &= ~(UART_UARTIMSC_OEIM | UART_UARTIMSC_BEIM |
UART_UARTIMSC_PEIM | UART_UARTIMSC_FEIM);
/* The callback is invoked if defined.*/
__sio_callback_rx_evt(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, SIO_MSG_ERRORS);
/* Disabling event sources until errors are recognized by the
application.*/
cr1 &= ~USART_CR1_PEIE;
cr2 &= ~USART_CR2_LBDIE;
cr3 &= ~USART_CR3_EIE;
/* One write on control registers.*/
u->CR2 = cr2;
}
/* RX FIFO is non-empty.*/
if (((cr1 & USART_CR1_RXNEIE) != 0U) &&
(isr & USART_ISR_RXNE) != 0U) {
if ((mis & UART_UARTMIS_RXMIS) != 0U) {
/* Disabling event sources.*/
msc &= ~UART_UARTIMSC_RXIM;
/* The callback is invoked if defined.*/
__sio_callback_rx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_rx(siop, MSG_OK);
/* Called once then the interrupt source is disabled.*/
cr1 &= ~USART_CR1_RXNEIE;
}
/* RX idle condition.*/
if (((cr1 & USART_CR1_IDLEIE) != 0U) &&
(isr & USART_ISR_IDLE) != 0U) {
if ((mis & UART_UARTMIS_RTMIS) != 0U) {
/* The callback is invoked if defined.*/
__sio_callback_rx_idle(siop);
@ -709,40 +585,24 @@ void sio_lld_serve_interrupt(SIODriver *siop) {
__sio_wakeup_rx(siop, SIO_MSG_IDLE);
/* The idle flag requires clearing, it stays enabled.*/
u->ICR = USART_ISR_IDLE;
u->UARTICR = UART_UARTICR_RTIC;
}
/* TX FIFO is non-full.*/
if (((cr1 & USART_CR1_TXEIE) != 0U) &&
(isr & USART_ISR_TXE) != 0U) {
if ((mis & UART_UARTMIS_TXMIS) != 0U) {
/* Disabling event sources.*/
msc &= ~UART_UARTIMSC_TXIM;
/* The callback is invoked if defined.*/
__sio_callback_tx(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_tx(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TXEIE;
}
/* Physical transmission end.*/
if (((cr1 & USART_CR1_TCIE) != 0U) &&
(isr & USART_ISR_TC) != 0U) {
/* The callback is invoked if defined.*/
__sio_callback_tx_end(siop);
/* Waiting thread woken, if any.*/
__sio_wakeup_txend(siop, MSG_OK);
/* Called once then the interrupt is disabled.*/
cr1 &= ~USART_CR1_TCIE;
}
/* One write on control registers.*/
u->CR1 = cr1;
u->CR3 = cr3;
u->UARTIMSC = msc;
}
#endif /* HAL_USE_SIO == TRUE */

View File

@ -101,16 +101,19 @@ typedef uint32_t sio_events_mask_t;
*/
#define sio_lld_driver_fields \
/* Pointer to the USARTx registers block.*/ \
UART_TypeDef *uart; \
/* USART clock frequency.*/ \
uint32_t clock
UART_TypeDef *uart
/**
* @brief Low level fields of the SIO configuration structure.
*/
#define sio_lld_config_fields \
/* Desired baud rate.*/ \
uint32_t baud;
uint32_t baud; \
/* Low level registers settings.*/ \
uint32_t UARTLCR_H; \
uint32_t UARTCR; \
uint32_t UARTIFLS; \
uint32_t UARTDMACR
/**
* @brief Determines the state of the RX FIFO.

View File

@ -142,6 +142,19 @@ __STATIC_INLINE uint32_t hal_lld_get_clock(clock_index_t clk_index) {
return clock_get_hz(clk_index);
}
__STATIC_INLINE void hal_lld_peripheral_reset(uint32_t mask) {
RESETS->RESET |= mask;
}
__STATIC_INLINE void hal_lld_peripheral_unreset(uint32_t mask) {
RESETS->RESET &= ~mask;
while ((RESETS->RESET_DONE & mask) != 0U) {
/* Waiting for reset.*/
}
}
#endif /* HAL_LLD_H */
/** @} */