From 620439fff49b32fd4c03ec695d8bd94d7947aae3 Mon Sep 17 00:00:00 2001 From: RedHawk Date: Fri, 28 Apr 2023 14:32:25 +0300 Subject: [PATCH] LpcUart: [#22] rewritten wrapper for lpc11u68. * We have UART1-4 (from UARTN, UART0 handling is different.) * Added Fmutex * Removed movable pins. * Disabled handshakes. (Not sure how to configure those.) * 1 and 4, as well as 2 and 3 share their interrupts with each other. (Again, not sure how it should work.) --- source/shoh/src/Fmutex.cpp | 28 +++++ source/shoh/src/Fmutex.h | 24 ++++ source/shoh/src/peripherals/LpcUart.cpp | 146 +++++++++++------------- source/shoh/src/peripherals/LpcUart.h | 8 +- 4 files changed, 123 insertions(+), 83 deletions(-) create mode 100644 source/shoh/src/Fmutex.cpp create mode 100644 source/shoh/src/Fmutex.h diff --git a/source/shoh/src/Fmutex.cpp b/source/shoh/src/Fmutex.cpp new file mode 100644 index 0000000..de725e8 --- /dev/null +++ b/source/shoh/src/Fmutex.cpp @@ -0,0 +1,28 @@ +/* + * Fmutex.cpp + * + * Created on: 15.8.2017 + * Author: krl + */ + +#include "Fmutex.h" + +Fmutex::Fmutex() { + // TODO Auto-generated constructor stub + mutex = xSemaphoreCreateMutex(); +} + +Fmutex::~Fmutex() { + // TODO Auto-generated destructor stub + vSemaphoreDelete(mutex); +} + +void Fmutex::lock() +{ + xSemaphoreTake(mutex, portMAX_DELAY); +} + +void Fmutex::unlock() +{ + xSemaphoreGive(mutex); +} diff --git a/source/shoh/src/Fmutex.h b/source/shoh/src/Fmutex.h new file mode 100644 index 0000000..94563c7 --- /dev/null +++ b/source/shoh/src/Fmutex.h @@ -0,0 +1,24 @@ +/* + * Fmutex.h + * + * Created on: 15.8.2017 + * Author: krl + */ + +#ifndef FMUTEX_H_ +#define FMUTEX_H_ + +#include "FreeRTOS.h" +#include "semphr.h" + +class Fmutex { +public: + Fmutex(); + virtual ~Fmutex(); + void lock(); + void unlock(); +private: + SemaphoreHandle_t mutex; +}; + +#endif /* FMUTEX_H_ */ diff --git a/source/shoh/src/peripherals/LpcUart.cpp b/source/shoh/src/peripherals/LpcUart.cpp index 7e4e08d..aee3544 100644 --- a/source/shoh/src/peripherals/LpcUart.cpp +++ b/source/shoh/src/peripherals/LpcUart.cpp @@ -9,32 +9,27 @@ #include #include "LpcUart.h" -// Remove this when code will be reworked. -#ifndef LPCUART_NOT_FIXED -// Remove this when code will be reworked. +/* shoh: Important differences + * We don't have movable pins -> not needed. + * + * Muxing is like this: + * Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 18, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); + * Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 19, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); + */ - -static LpcUart *u0; static LpcUart *u1; static LpcUart *u2; +static LpcUart *u3; +static LpcUart *u4; extern "C" { /** * @brief UART interrupt handler using ring buffers + * @par shoh: Unlike in lpc15xx, lpc11u68 has shared interrupts for 1 and 4, 2 and 3. + * shoh: Not sure how exactly it should be handled. UART0 is completely different compared to 1-4. * @return Nothing */ -void UART0_IRQHandler(void) -{ - portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - - if(u0) { - u0->isr(&xHigherPriorityTaskWoken); - } - - portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); -} - -void UART1_IRQHandler(void) +void USART1_4_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; @@ -42,10 +37,14 @@ void UART1_IRQHandler(void) u1->isr(&xHigherPriorityTaskWoken); } + if(u4) { + u4->isr(&xHigherPriorityTaskWoken); + } + portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } -void UART2_IRQHandler(void) +void USART2_3_IRQHandler(void) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; @@ -53,6 +52,10 @@ void UART2_IRQHandler(void) u2->isr(&xHigherPriorityTaskWoken); } + if(u3) { + u3->isr(&xHigherPriorityTaskWoken); + } + portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); } @@ -61,26 +64,23 @@ void UART2_IRQHandler(void) void LpcUart::isr(portBASE_TYPE *hpw) { // get interrupt status for notifications - uint32_t istat = Chip_UART_GetIntStatus(uart); + uint32_t istat = Chip_UARTN_GetIntStatus(uart); // chip library is used to handle receive and transmit - Chip_UART_IRQRBHandler(uart, &rxring, &txring); + Chip_UARTN_IRQRBHandler(uart, &rxring, &txring); // notify of the events handled - if(notify_rx && (istat & UART_STAT_RXRDY) ) vTaskNotifyGiveFromISR(notify_rx, hpw); - if(notify_tx && (istat & UART_STAT_TXRDY) ) vTaskNotifyGiveFromISR(notify_tx, hpw); - if(on_receive && (istat & UART_STAT_RXRDY) ) on_receive(); + if(notify_rx && (istat & UARTN_STAT_RXRDY) ) vTaskNotifyGiveFromISR(notify_rx, hpw); + if(notify_tx && (istat & UARTN_STAT_TXRDY) ) vTaskNotifyGiveFromISR(notify_tx, hpw); + if(on_receive && (istat & UARTN_STAT_RXRDY) ) on_receive(); } bool LpcUart::init = false; LpcUart::LpcUart(const LpcUartConfig &cfg) { - CHIP_SWM_PIN_MOVABLE_T tx; - CHIP_SWM_PIN_MOVABLE_T rx; - CHIP_SWM_PIN_MOVABLE_T cts; - CHIP_SWM_PIN_MOVABLE_T rts; - bool use_rts = (cfg.rts.port >= 0); - bool use_cts = (cfg.cts.port >= 0); + //shoh: removed handshakes and movable pins. + bool use_rts = false; //(cfg.rts.port >= 0); + bool use_cts = false; //(cfg.cts.port >= 0); if(!init) { init = true; @@ -90,37 +90,30 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) { * UARTs. * */ /* Use main clock rate as base for UART baud rate divider */ - Chip_Clock_SetUARTBaseClockRate(Chip_Clock_GetMainClockRate(), false); + Chip_Clock_SetUSARTNBaseClockRate(Chip_Clock_GetMainClockRate(), false); } uart = nullptr; // set default value before checking which UART to configure - if(cfg.pUART == LPC_USART0) { - if(u0) return; // already exists - else u0 = this; - tx = SWM_UART0_TXD_O; - rx = SWM_UART0_RXD_I; - rts = SWM_UART0_RTS_O; - cts = SWM_UART0_CTS_I; - irqn = UART0_IRQn; - } - else if(cfg.pUART == LPC_USART1) { + if(cfg.pUART == LPC_USART1) { if(u1) return; // already exists else u1 = this; - tx = SWM_UART1_TXD_O; - rx = SWM_UART1_RXD_I; - rts = SWM_UART1_RTS_O; - cts = SWM_UART1_CTS_I; - irqn = UART1_IRQn; + irqn = USART1_4_IRQn; //Shares interrupt with 4 } else if(cfg.pUART == LPC_USART2) { if(u2) return; // already exists else u2 = this; - tx = SWM_UART2_TXD_O; - rx = SWM_UART2_RXD_I; - use_rts = false; // UART2 does not support handshakes - use_cts = false; - irqn = UART2_IRQn; + irqn = USART2_3_IRQn; //Shares interrupt with 3 + } + else if(cfg.pUART == LPC_USART3) { + if(u3) return; // already exists + else u3 = this; + irqn = USART2_3_IRQn; + } + else if(cfg.pUART == LPC_USART4) { + if(u4) return; // already exists + else u4 = this; + irqn = USART1_4_IRQn; } else { return; @@ -130,32 +123,28 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) { if(cfg.tx.port >= 0) { - Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.tx.port, cfg.tx.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN)); - Chip_SWM_MovablePortPinAssign(tx, cfg.tx.port, cfg.tx.pin); + Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.tx.port, cfg.tx.pin, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); } if(cfg.rx.port >= 0) { - Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rx.port, cfg.rx.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN)); - Chip_SWM_MovablePortPinAssign(rx, cfg.rx.port, cfg.rx.pin); + Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rx.port, cfg.rx.pin, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); } if(use_cts) { - Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.cts.port, cfg.cts.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN)); - Chip_SWM_MovablePortPinAssign(cts, cfg.cts.port, cfg.cts.pin); + Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.cts.port, cfg.cts.pin, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); } if(use_rts) { - Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rts.port, cfg.rts.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN)); - Chip_SWM_MovablePortPinAssign(rts, cfg.rts.port, cfg.rts.pin); + Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rts.port, cfg.rts.pin, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN)); } notify_rx = nullptr; notify_tx = nullptr; on_receive = nullptr; /* Setup UART */ - Chip_UART_Init(uart); - Chip_UART_ConfigData(uart, cfg.data); - Chip_UART_SetBaud(uart, cfg.speed); + Chip_UARTN_Init(uart); + Chip_UARTN_ConfigData(uart, cfg.data); + Chip_UARTN_SetBaud(uart, cfg.speed); if(use_rts && cfg.rs485) { uart->CFG |= (1 << 20); // enable rs485 mode @@ -163,8 +152,8 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) { uart->CFG |= (1 << 21);// driver enable polarity (active high) } - Chip_UART_Enable(uart); - Chip_UART_TXEnable(uart); + Chip_UARTN_Enable(uart); + Chip_UARTN_TXEnable(uart); /* Before using the ring buffers, initialize them using the ring buffer init function */ @@ -173,8 +162,8 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) { /* Enable receive data and line status interrupt */ - Chip_UART_IntEnable(uart, UART_INTEN_RXRDY); - Chip_UART_IntDisable(uart, UART_INTEN_TXRDY); /* May not be needed */ + Chip_UARTN_IntEnable(uart, UARTN_INTEN_RXRDY); + Chip_UARTN_IntDisable(uart, UARTN_INTEN_TXRDY); /* May not be needed */ NVIC_SetPriority(irqn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1); /* Enable UART interrupt */ @@ -184,18 +173,21 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) { LpcUart::~LpcUart() { if(uart != nullptr) { NVIC_DisableIRQ(irqn); - Chip_UART_IntDisable(uart, UART_INTEN_RXRDY); - Chip_UART_IntDisable(uart, UART_INTEN_TXRDY); + Chip_UARTN_IntDisable(uart, UARTN_INTEN_RXRDY); + Chip_UARTN_IntDisable(uart, UARTN_INTEN_TXRDY); - if(uart == LPC_USART0) { - u0 = nullptr; - } - else if(uart == LPC_USART1) { + if(uart == LPC_USART1) { u1 = nullptr; } else if(uart == LPC_USART2) { u2 = nullptr; } + else if(uart == LPC_USART3) { + u3 = nullptr; + } + else if(uart == LPC_USART4) { + u4 = nullptr; + } } } @@ -236,7 +228,7 @@ int LpcUart::read(char *buffer, int len) notify_rx = nullptr; } - return Chip_UART_ReadRB(uart, &rxring, buffer, len); + return Chip_UARTN_ReadRB(uart, &rxring, buffer, len); } @@ -257,7 +249,7 @@ int LpcUart::read(char *buffer, int len, TickType_t total_timeout, TickType_t i } notify_rx = nullptr; - return Chip_UART_ReadRB(uart, &rxring, buffer, len);; + return Chip_UARTN_ReadRB(uart, &rxring, buffer, len);; } int LpcUart::write(char c) @@ -285,7 +277,7 @@ int LpcUart::write(const char *buffer, int len) while(UART_RB_SIZE - RingBuffer_GetCount(&txring) < size) { ulTaskNotifyTake( pdTRUE, portMAX_DELAY ); } - pos += Chip_UART_SendRB(uart, &txring, buffer+pos, size); + pos += Chip_UARTN_SendRB(uart, &txring, buffer+pos, size); } notify_tx = nullptr; @@ -308,7 +300,7 @@ void LpcUart::speed(int bps) std::lock_guard lockw(write_mutex); std::lock_guard lockr(read_mutex); - Chip_UART_SetBaud(uart, bps); + Chip_UARTN_SetBaud(uart, bps); } bool LpcUart::txempty() @@ -317,7 +309,3 @@ bool LpcUart::txempty() return (RingBuffer_GetCount(&txring) == 0); } - -// Remove this when code will be reworked. -#endif /* LPCUART_NOT_FIXED */ -// Remove this when code will be reworked. diff --git a/source/shoh/src/peripherals/LpcUart.h b/source/shoh/src/peripherals/LpcUart.h index 38a88ac..7ee4ab4 100644 --- a/source/shoh/src/peripherals/LpcUart.h +++ b/source/shoh/src/peripherals/LpcUart.h @@ -9,7 +9,7 @@ #define LPCUART_H_ // Remove this when code will be reworked. -#define LPCUART_NOT_FIXED +//#define LPCUART_NOT_FIXED #ifndef LPCUART_NOT_FIXED // Remove this when code will be reworked. @@ -26,13 +26,13 @@ struct LpcPinMap { }; struct LpcUartConfig { - LPC_USART_T *pUART; + LPC_USARTN_T *pUART; uint32_t speed; uint32_t data; bool rs485; LpcPinMap tx; LpcPinMap rx; - LpcPinMap rts; /* used as output enable if RS-485 mode is enabled */ + LpcPinMap rts; /* used as output enable if RS-485 mode is enabled */ //shoh: Psst. Actually, not used anywhere. LpcPinMap cts; }; @@ -58,7 +58,7 @@ public: void isr(portBASE_TYPE *hpw); /* ISR handler. This will be called by the HW ISR handler. Do not call from application */ private: - LPC_USART_T *uart; + LPC_USARTN_T *uart; IRQn_Type irqn; /* currently we support only fixed size ring buffers */ static const int UART_RB_SIZE = 128;