commit
07e4083ab8
28
source/shoh/src/Fmutex.cpp
Normal file
28
source/shoh/src/Fmutex.cpp
Normal file
@ -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);
|
||||||
|
}
|
||||||
24
source/shoh/src/Fmutex.h
Normal file
24
source/shoh/src/Fmutex.h
Normal file
@ -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_ */
|
||||||
@ -6,12 +6,17 @@
|
|||||||
#include "ThreadCommon.h"
|
#include "ThreadCommon.h"
|
||||||
#include "Master.h"
|
#include "Master.h"
|
||||||
#include "Rotary.h"
|
#include "Rotary.h"
|
||||||
|
#include "retarget_uart.h"
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
SystemCoreClockUpdate();
|
SystemCoreClockUpdate();
|
||||||
Board_Init();
|
Board_Init();
|
||||||
|
|
||||||
|
retarget_init();
|
||||||
|
|
||||||
|
printf("Hello there!\r\n");
|
||||||
|
|
||||||
ThreadCommon::ThreadManager* manager = new ThreadCommon::ThreadManager;
|
ThreadCommon::ThreadManager* manager = new ThreadCommon::ThreadManager;
|
||||||
ThreadCommon::QueueManager* qmanager = new ThreadCommon::QueueManager;
|
ThreadCommon::QueueManager* qmanager = new ThreadCommon::QueueManager;
|
||||||
//Creating queues
|
//Creating queues
|
||||||
|
|||||||
228
source/shoh/src/peripherals/LpcDebugUart.cpp
Normal file
228
source/shoh/src/peripherals/LpcDebugUart.cpp
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* LpcDebugUart.cpp
|
||||||
|
*
|
||||||
|
* Created on: 6.5.2023
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
#include "LpcDebugUart.h"
|
||||||
|
|
||||||
|
/* shoh: Important differences
|
||||||
|
* We don't have movable pins -> not needed.
|
||||||
|
*
|
||||||
|
* USART0 (the only debug uart):
|
||||||
|
* 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 LpcDebugUart *u0;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
/**
|
||||||
|
* @brief UART interrupt handler using ring buffers
|
||||||
|
* @return Nothing
|
||||||
|
*/
|
||||||
|
void USART0_IRQHandler(void)
|
||||||
|
{
|
||||||
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
if(u0) {
|
||||||
|
u0->isr(&xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
|
||||||
|
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LpcDebugUart::isr(portBASE_TYPE *hpw) {
|
||||||
|
// get interrupt status for notifications
|
||||||
|
uint32_t istat = Chip_UART0_ReadLineStatus(uart);
|
||||||
|
|
||||||
|
// chip library is used to handle receive and transmit
|
||||||
|
Chip_UART0_IRQRBHandler(uart, &rxring, &txring);
|
||||||
|
|
||||||
|
// notify (hopefully) of the events handled
|
||||||
|
if(notify_rx && (istat & UART0_LSR_RDR) ) vTaskNotifyGiveFromISR(notify_rx, hpw);
|
||||||
|
if(notify_tx && (istat & UART0_LSR_THRE) ) vTaskNotifyGiveFromISR(notify_tx, hpw);
|
||||||
|
if(on_receive && (istat & UART0_LSR_RDR) ) on_receive();
|
||||||
|
}
|
||||||
|
|
||||||
|
LpcDebugUart::LpcDebugUart(const LpcDebugUartConfig &cfg) {
|
||||||
|
uart = nullptr; // set default value before checking which UART to configure
|
||||||
|
|
||||||
|
if(cfg.pUART == LPC_USART0) {
|
||||||
|
if(u0) return; // already exists
|
||||||
|
else u0 = this;
|
||||||
|
irqn = USART0_IRQn;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uart = cfg.pUART; // set the actual value after validity checking
|
||||||
|
|
||||||
|
|
||||||
|
if(cfg.tx.port >= 0) {
|
||||||
|
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_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_rx = nullptr;
|
||||||
|
notify_tx = nullptr;
|
||||||
|
on_receive = nullptr;
|
||||||
|
/* Setup UART */
|
||||||
|
Chip_UART0_Init(uart);
|
||||||
|
Chip_UART0_SetBaud(LPC_USART0, cfg.speed);
|
||||||
|
Chip_UART0_ConfigData(LPC_USART0, cfg.data);
|
||||||
|
Chip_UART0_SetupFIFOS(LPC_USART0, (UART0_FCR_FIFO_EN | UART0_FCR_TRG_LEV2));
|
||||||
|
Chip_UART0_TXEnable(uart);
|
||||||
|
|
||||||
|
/* Before using the ring buffers, initialize them using the ring
|
||||||
|
buffer init function */
|
||||||
|
RingBuffer_Init(&rxring, rxbuff, 1, UART_RB_SIZE);
|
||||||
|
RingBuffer_Init(&txring, txbuff, 1, UART_RB_SIZE);
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable receive data and line status interrupt */
|
||||||
|
Chip_UART0_IntEnable(uart, UART0_IER_RBRINT | UART0_IER_RLSINT);
|
||||||
|
|
||||||
|
NVIC_SetPriority(irqn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||||
|
/* Enable UART interrupt */
|
||||||
|
NVIC_EnableIRQ(irqn);
|
||||||
|
}
|
||||||
|
|
||||||
|
LpcDebugUart::~LpcDebugUart() {
|
||||||
|
if(uart != nullptr) {
|
||||||
|
NVIC_DisableIRQ(irqn);
|
||||||
|
Chip_UART0_IntDisable(uart, UART0_IER_RBRINT | UART0_IER_RLSINT);
|
||||||
|
|
||||||
|
if(uart == LPC_USART0) {
|
||||||
|
u0 = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LpcDebugUart::set_on_receive(void(*cb)(void))
|
||||||
|
{
|
||||||
|
on_receive = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LpcDebugUart::free()
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(write_mutex);
|
||||||
|
|
||||||
|
return UART_RB_SIZE - RingBuffer_GetCount(&txring);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::peek()
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(read_mutex);
|
||||||
|
|
||||||
|
return RingBuffer_GetCount(&rxring);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::read(char &c)
|
||||||
|
{
|
||||||
|
return read(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::read(char *buffer, int len)
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(read_mutex);
|
||||||
|
|
||||||
|
if(RingBuffer_GetCount(&rxring) <= 0) {
|
||||||
|
notify_rx = xTaskGetCurrentTaskHandle();
|
||||||
|
while(RingBuffer_GetCount(&rxring) <= 0) {
|
||||||
|
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
}
|
||||||
|
notify_rx = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Chip_UART0_ReadRB(uart, &rxring, buffer, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int LpcDebugUart::read(char *buffer, int len, TickType_t total_timeout, TickType_t ic_timeout)
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(read_mutex);
|
||||||
|
|
||||||
|
// we can't read more than ring buffer size at a time
|
||||||
|
if(len > UART_RB_SIZE) len = UART_RB_SIZE;
|
||||||
|
|
||||||
|
TimeOut_t timeoutState;
|
||||||
|
vTaskSetTimeOutState(&timeoutState);
|
||||||
|
|
||||||
|
notify_rx = xTaskGetCurrentTaskHandle();
|
||||||
|
while(RingBuffer_GetCount(&rxring) < len && xTaskCheckForTimeOut(&timeoutState, &total_timeout) == pdFALSE) {
|
||||||
|
TickType_t timeout = total_timeout > ic_timeout ? ic_timeout : total_timeout;
|
||||||
|
if(ulTaskNotifyTake( pdTRUE, timeout ) == 0) break;
|
||||||
|
}
|
||||||
|
notify_rx = nullptr;
|
||||||
|
|
||||||
|
return Chip_UART0_ReadRB(uart, &rxring, buffer, len);;
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::write(char c)
|
||||||
|
{
|
||||||
|
return write(&c, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::write(const char *s)
|
||||||
|
{
|
||||||
|
return write(s, strlen(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
int LpcDebugUart::write(const char *buffer, int len)
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(write_mutex);
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
notify_tx = xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
|
while(len > pos) {
|
||||||
|
// restrict single write to ring buffer size
|
||||||
|
int size = (len - pos) > UART_RB_SIZE ? UART_RB_SIZE : (len - pos);
|
||||||
|
|
||||||
|
// wait until we have space in the ring buffer
|
||||||
|
while(UART_RB_SIZE - RingBuffer_GetCount(&txring) < size) {
|
||||||
|
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
||||||
|
}
|
||||||
|
pos += Chip_UART0_SendRB(uart, &txring, buffer+pos, size);
|
||||||
|
}
|
||||||
|
notify_tx = nullptr;
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LpcDebugUart::txbreak(bool brk)
|
||||||
|
{
|
||||||
|
// break handling not implemented yet
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LpcDebugUart::rxbreak()
|
||||||
|
{
|
||||||
|
// break handling not implemented yet
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LpcDebugUart::speed(int bps)
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lockw(write_mutex);
|
||||||
|
std::lock_guard<Fmutex> lockr(read_mutex);
|
||||||
|
|
||||||
|
Chip_UART0_SetBaud(uart, bps);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LpcDebugUart::txempty()
|
||||||
|
{
|
||||||
|
std::lock_guard<Fmutex> lock(write_mutex);
|
||||||
|
|
||||||
|
return (RingBuffer_GetCount(&txring) == 0);
|
||||||
|
}
|
||||||
63
source/shoh/src/peripherals/LpcDebugUart.h
Normal file
63
source/shoh/src/peripherals/LpcDebugUart.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* LpcDebugUart.h
|
||||||
|
*
|
||||||
|
* Created on: 6.5.2023
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LPCDEBUGUART_H_
|
||||||
|
#define LPCDEBUGUART_H_
|
||||||
|
|
||||||
|
#include "chip.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "task.h"
|
||||||
|
#include "semphr.h"
|
||||||
|
#include "Fmutex.h"
|
||||||
|
#include "LpcUart.h"
|
||||||
|
|
||||||
|
struct LpcDebugUartConfig {
|
||||||
|
LPC_USART0_T *pUART;
|
||||||
|
uint32_t speed;
|
||||||
|
uint32_t data;
|
||||||
|
LpcPinMap tx;
|
||||||
|
LpcPinMap rx;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LpcDebugUart {
|
||||||
|
public:
|
||||||
|
LpcDebugUart(const LpcDebugUartConfig &cfg);
|
||||||
|
LpcDebugUart(const LpcDebugUart &) = delete;
|
||||||
|
virtual ~LpcDebugUart();
|
||||||
|
int free(); /* get amount of free space in transmit buffer */
|
||||||
|
int peek(); /* get number of received characters in receive buffer */
|
||||||
|
int write(char c);
|
||||||
|
int write(const char *s);
|
||||||
|
int write(const char *buffer, int len);
|
||||||
|
int read(char &c); /* get a single character. Returns number of characters read --> returns 0 if no character is available */
|
||||||
|
int read(char *buffer, int len);
|
||||||
|
int read(char *buffer, int len, TickType_t total_timeout, TickType_t ic_timeout = portMAX_DELAY);
|
||||||
|
void txbreak(bool brk); /* set break signal on */
|
||||||
|
bool rxbreak(); /* check if break is received */
|
||||||
|
void speed(int bps); /* change transmission speed */
|
||||||
|
bool txempty();
|
||||||
|
void set_on_receive(void(*cb)(void));
|
||||||
|
|
||||||
|
void isr(portBASE_TYPE *hpw); /* ISR handler. This will be called by the HW ISR handler. Do not call from application */
|
||||||
|
private:
|
||||||
|
LPC_USART0_T *uart;
|
||||||
|
IRQn_Type irqn;
|
||||||
|
/* currently we support only fixed size ring buffers */
|
||||||
|
static const int UART_RB_SIZE = 128;
|
||||||
|
/* Transmit and receive ring buffers */
|
||||||
|
RINGBUFF_T txring;
|
||||||
|
RINGBUFF_T rxring;
|
||||||
|
uint8_t rxbuff[UART_RB_SIZE];
|
||||||
|
uint8_t txbuff[UART_RB_SIZE];
|
||||||
|
TaskHandle_t notify_rx;
|
||||||
|
TaskHandle_t notify_tx;
|
||||||
|
void (*on_receive)(void); // callback for received data notifications
|
||||||
|
Fmutex read_mutex;
|
||||||
|
Fmutex write_mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LPCUART_H_ */
|
||||||
@ -9,32 +9,31 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "LpcUart.h"
|
#include "LpcUart.h"
|
||||||
|
|
||||||
// Remove this when code will be reworked.
|
/* shoh: Important differences
|
||||||
#ifndef LPCUART_NOT_FIXED
|
* We don't have movable pins -> not needed.
|
||||||
// Remove this when code will be reworked.
|
*
|
||||||
|
* Muxing is like this:
|
||||||
|
* Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 14, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
* Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 13, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
*
|
||||||
|
* USART0 (the only debug uart):
|
||||||
|
* 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 *u1;
|
||||||
static LpcUart *u2;
|
static LpcUart *u2;
|
||||||
|
static LpcUart *u3;
|
||||||
|
static LpcUart *u4;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/**
|
/**
|
||||||
* @brief UART interrupt handler using ring buffers
|
* @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
|
* @return Nothing
|
||||||
*/
|
*/
|
||||||
void UART0_IRQHandler(void)
|
void USART1_4_IRQHandler(void)
|
||||||
{
|
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
if(u0) {
|
|
||||||
u0->isr(&xHigherPriorityTaskWoken);
|
|
||||||
}
|
|
||||||
|
|
||||||
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UART1_IRQHandler(void)
|
|
||||||
{
|
{
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
@ -42,10 +41,14 @@ void UART1_IRQHandler(void)
|
|||||||
u1->isr(&xHigherPriorityTaskWoken);
|
u1->isr(&xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(u4) {
|
||||||
|
u4->isr(&xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
|
||||||
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UART2_IRQHandler(void)
|
void USART2_3_IRQHandler(void)
|
||||||
{
|
{
|
||||||
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
@ -53,6 +56,10 @@ void UART2_IRQHandler(void)
|
|||||||
u2->isr(&xHigherPriorityTaskWoken);
|
u2->isr(&xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(u3) {
|
||||||
|
u3->isr(&xHigherPriorityTaskWoken);
|
||||||
|
}
|
||||||
|
|
||||||
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,26 +68,23 @@ void UART2_IRQHandler(void)
|
|||||||
|
|
||||||
void LpcUart::isr(portBASE_TYPE *hpw) {
|
void LpcUart::isr(portBASE_TYPE *hpw) {
|
||||||
// get interrupt status for notifications
|
// 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 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
|
// notify of the events handled
|
||||||
if(notify_rx && (istat & UART_STAT_RXRDY) ) vTaskNotifyGiveFromISR(notify_rx, hpw);
|
if(notify_rx && (istat & UARTN_STAT_RXRDY) ) vTaskNotifyGiveFromISR(notify_rx, hpw);
|
||||||
if(notify_tx && (istat & UART_STAT_TXRDY) ) vTaskNotifyGiveFromISR(notify_tx, hpw);
|
if(notify_tx && (istat & UARTN_STAT_TXRDY) ) vTaskNotifyGiveFromISR(notify_tx, hpw);
|
||||||
if(on_receive && (istat & UART_STAT_RXRDY) ) on_receive();
|
if(on_receive && (istat & UARTN_STAT_RXRDY) ) on_receive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LpcUart::init = false;
|
bool LpcUart::init = false;
|
||||||
|
|
||||||
LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
||||||
CHIP_SWM_PIN_MOVABLE_T tx;
|
//shoh: removed handshakes and movable pins.
|
||||||
CHIP_SWM_PIN_MOVABLE_T rx;
|
bool use_rts = false; //(cfg.rts.port >= 0);
|
||||||
CHIP_SWM_PIN_MOVABLE_T cts;
|
bool use_cts = false; //(cfg.cts.port >= 0);
|
||||||
CHIP_SWM_PIN_MOVABLE_T rts;
|
|
||||||
bool use_rts = (cfg.rts.port >= 0);
|
|
||||||
bool use_cts = (cfg.cts.port >= 0);
|
|
||||||
|
|
||||||
if(!init) {
|
if(!init) {
|
||||||
init = true;
|
init = true;
|
||||||
@ -90,37 +94,30 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
|||||||
* UARTs.
|
* UARTs.
|
||||||
* */
|
* */
|
||||||
/* Use main clock rate as base for UART baud rate divider */
|
/* 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); //(115200 * 256), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
uart = nullptr; // set default value before checking which UART to configure
|
uart = nullptr; // set default value before checking which UART to configure
|
||||||
|
|
||||||
if(cfg.pUART == LPC_USART0) {
|
if(cfg.pUART == LPC_USART1) {
|
||||||
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(u1) return; // already exists
|
if(u1) return; // already exists
|
||||||
else u1 = this;
|
else u1 = this;
|
||||||
tx = SWM_UART1_TXD_O;
|
irqn = USART1_4_IRQn; //Shares interrupt with 4
|
||||||
rx = SWM_UART1_RXD_I;
|
|
||||||
rts = SWM_UART1_RTS_O;
|
|
||||||
cts = SWM_UART1_CTS_I;
|
|
||||||
irqn = UART1_IRQn;
|
|
||||||
}
|
}
|
||||||
else if(cfg.pUART == LPC_USART2) {
|
else if(cfg.pUART == LPC_USART2) {
|
||||||
if(u2) return; // already exists
|
if(u2) return; // already exists
|
||||||
else u2 = this;
|
else u2 = this;
|
||||||
tx = SWM_UART2_TXD_O;
|
irqn = USART2_3_IRQn; //Shares interrupt with 3
|
||||||
rx = SWM_UART2_RXD_I;
|
}
|
||||||
use_rts = false; // UART2 does not support handshakes
|
else if(cfg.pUART == LPC_USART3) {
|
||||||
use_cts = false;
|
if(u3) return; // already exists
|
||||||
irqn = UART2_IRQn;
|
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 {
|
else {
|
||||||
return;
|
return;
|
||||||
@ -130,32 +127,28 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
|||||||
|
|
||||||
|
|
||||||
if(cfg.tx.port >= 0) {
|
if(cfg.tx.port >= 0) {
|
||||||
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.tx.port, cfg.tx.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.tx.port, cfg.tx.pin, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
Chip_SWM_MovablePortPinAssign(tx, cfg.tx.port, cfg.tx.pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cfg.rx.port >= 0) {
|
if(cfg.rx.port >= 0) {
|
||||||
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rx.port, cfg.rx.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rx.port, cfg.rx.pin, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
Chip_SWM_MovablePortPinAssign(rx, cfg.rx.port, cfg.rx.pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(use_cts) {
|
if(use_cts) {
|
||||||
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.cts.port, cfg.cts.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.cts.port, cfg.cts.pin, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
Chip_SWM_MovablePortPinAssign(cts, cfg.cts.port, cfg.cts.pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(use_rts) {
|
if(use_rts) {
|
||||||
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rts.port, cfg.rts.pin, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
Chip_IOCON_PinMuxSet(LPC_IOCON, cfg.rts.port, cfg.rts.pin, (IOCON_FUNC4 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
Chip_SWM_MovablePortPinAssign(rts, cfg.rts.port, cfg.rts.pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notify_rx = nullptr;
|
notify_rx = nullptr;
|
||||||
notify_tx = nullptr;
|
notify_tx = nullptr;
|
||||||
on_receive = nullptr;
|
on_receive = nullptr;
|
||||||
/* Setup UART */
|
/* Setup UART */
|
||||||
Chip_UART_Init(uart);
|
Chip_UARTN_Init(uart);
|
||||||
Chip_UART_ConfigData(uart, cfg.data);
|
Chip_UARTN_ConfigData(uart, cfg.data);
|
||||||
Chip_UART_SetBaud(uart, cfg.speed);
|
Chip_UARTN_SetBaud(uart, cfg.speed);
|
||||||
|
|
||||||
if(use_rts && cfg.rs485) {
|
if(use_rts && cfg.rs485) {
|
||||||
uart->CFG |= (1 << 20); // enable rs485 mode
|
uart->CFG |= (1 << 20); // enable rs485 mode
|
||||||
@ -163,8 +156,8 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
|||||||
uart->CFG |= (1 << 21);// driver enable polarity (active high)
|
uart->CFG |= (1 << 21);// driver enable polarity (active high)
|
||||||
}
|
}
|
||||||
|
|
||||||
Chip_UART_Enable(uart);
|
Chip_UARTN_Enable(uart);
|
||||||
Chip_UART_TXEnable(uart);
|
Chip_UARTN_TXEnable(uart);
|
||||||
|
|
||||||
/* Before using the ring buffers, initialize them using the ring
|
/* Before using the ring buffers, initialize them using the ring
|
||||||
buffer init function */
|
buffer init function */
|
||||||
@ -173,8 +166,8 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
|||||||
|
|
||||||
|
|
||||||
/* Enable receive data and line status interrupt */
|
/* Enable receive data and line status interrupt */
|
||||||
Chip_UART_IntEnable(uart, UART_INTEN_RXRDY);
|
Chip_UARTN_IntEnable(uart, UARTN_INTEN_RXRDY);
|
||||||
Chip_UART_IntDisable(uart, UART_INTEN_TXRDY); /* May not be needed */
|
Chip_UARTN_IntDisable(uart, UARTN_INTEN_TXRDY); /* May not be needed */
|
||||||
|
|
||||||
NVIC_SetPriority(irqn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
NVIC_SetPriority(irqn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1);
|
||||||
/* Enable UART interrupt */
|
/* Enable UART interrupt */
|
||||||
@ -184,18 +177,21 @@ LpcUart::LpcUart(const LpcUartConfig &cfg) {
|
|||||||
LpcUart::~LpcUart() {
|
LpcUart::~LpcUart() {
|
||||||
if(uart != nullptr) {
|
if(uart != nullptr) {
|
||||||
NVIC_DisableIRQ(irqn);
|
NVIC_DisableIRQ(irqn);
|
||||||
Chip_UART_IntDisable(uart, UART_INTEN_RXRDY);
|
Chip_UARTN_IntDisable(uart, UARTN_INTEN_RXRDY);
|
||||||
Chip_UART_IntDisable(uart, UART_INTEN_TXRDY);
|
Chip_UARTN_IntDisable(uart, UARTN_INTEN_TXRDY);
|
||||||
|
|
||||||
if(uart == LPC_USART0) {
|
if(uart == LPC_USART1) {
|
||||||
u0 = nullptr;
|
|
||||||
}
|
|
||||||
else if(uart == LPC_USART1) {
|
|
||||||
u1 = nullptr;
|
u1 = nullptr;
|
||||||
}
|
}
|
||||||
else if(uart == LPC_USART2) {
|
else if(uart == LPC_USART2) {
|
||||||
u2 = nullptr;
|
u2 = nullptr;
|
||||||
}
|
}
|
||||||
|
else if(uart == LPC_USART3) {
|
||||||
|
u3 = nullptr;
|
||||||
|
}
|
||||||
|
else if(uart == LPC_USART4) {
|
||||||
|
u4 = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +232,7 @@ int LpcUart::read(char *buffer, int len)
|
|||||||
notify_rx = nullptr;
|
notify_rx = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Chip_UART_ReadRB(uart, &rxring, buffer, len);
|
return Chip_UARTN_ReadRB(uart, &rxring, buffer, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -257,7 +253,7 @@ int LpcUart::read(char *buffer, int len, TickType_t total_timeout, TickType_t i
|
|||||||
}
|
}
|
||||||
notify_rx = nullptr;
|
notify_rx = nullptr;
|
||||||
|
|
||||||
return Chip_UART_ReadRB(uart, &rxring, buffer, len);;
|
return Chip_UARTN_ReadRB(uart, &rxring, buffer, len);;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LpcUart::write(char c)
|
int LpcUart::write(char c)
|
||||||
@ -285,7 +281,7 @@ int LpcUart::write(const char *buffer, int len)
|
|||||||
while(UART_RB_SIZE - RingBuffer_GetCount(&txring) < size) {
|
while(UART_RB_SIZE - RingBuffer_GetCount(&txring) < size) {
|
||||||
ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
|
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;
|
notify_tx = nullptr;
|
||||||
|
|
||||||
@ -308,7 +304,7 @@ void LpcUart::speed(int bps)
|
|||||||
std::lock_guard<Fmutex> lockw(write_mutex);
|
std::lock_guard<Fmutex> lockw(write_mutex);
|
||||||
std::lock_guard<Fmutex> lockr(read_mutex);
|
std::lock_guard<Fmutex> lockr(read_mutex);
|
||||||
|
|
||||||
Chip_UART_SetBaud(uart, bps);
|
Chip_UARTN_SetBaud(uart, bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LpcUart::txempty()
|
bool LpcUart::txempty()
|
||||||
@ -317,7 +313,3 @@ bool LpcUart::txempty()
|
|||||||
|
|
||||||
return (RingBuffer_GetCount(&txring) == 0);
|
return (RingBuffer_GetCount(&txring) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
#endif /* LPCUART_NOT_FIXED */
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
|
|||||||
@ -8,12 +8,6 @@
|
|||||||
#ifndef LPCUART_H_
|
#ifndef LPCUART_H_
|
||||||
#define LPCUART_H_
|
#define LPCUART_H_
|
||||||
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
#define LPCUART_NOT_FIXED
|
|
||||||
#ifndef LPCUART_NOT_FIXED
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
|
|
||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
@ -26,13 +20,13 @@ struct LpcPinMap {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct LpcUartConfig {
|
struct LpcUartConfig {
|
||||||
LPC_USART_T *pUART;
|
LPC_USARTN_T *pUART;
|
||||||
uint32_t speed;
|
uint32_t speed;
|
||||||
uint32_t data;
|
uint32_t data;
|
||||||
bool rs485;
|
bool rs485;
|
||||||
LpcPinMap tx;
|
LpcPinMap tx;
|
||||||
LpcPinMap rx;
|
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;
|
LpcPinMap cts;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -58,7 +52,7 @@ public:
|
|||||||
|
|
||||||
void isr(portBASE_TYPE *hpw); /* ISR handler. This will be called by the HW ISR handler. Do not call from application */
|
void isr(portBASE_TYPE *hpw); /* ISR handler. This will be called by the HW ISR handler. Do not call from application */
|
||||||
private:
|
private:
|
||||||
LPC_USART_T *uart;
|
LPC_USARTN_T *uart;
|
||||||
IRQn_Type irqn;
|
IRQn_Type irqn;
|
||||||
/* currently we support only fixed size ring buffers */
|
/* currently we support only fixed size ring buffers */
|
||||||
static const int UART_RB_SIZE = 128;
|
static const int UART_RB_SIZE = 128;
|
||||||
@ -75,8 +69,4 @@ private:
|
|||||||
Fmutex write_mutex;
|
Fmutex write_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
#endif /* LPCUART_NOT_FIXED */
|
|
||||||
// Remove this when code will be reworked.
|
|
||||||
|
|
||||||
#endif /* LPCUART_H_ */
|
#endif /* LPCUART_H_ */
|
||||||
|
|||||||
91
source/shoh/src/peripherals/retarget_uart.cpp
Normal file
91
source/shoh/src/peripherals/retarget_uart.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* retarget_uart.cpp
|
||||||
|
*
|
||||||
|
* Created on: 28.9.2021
|
||||||
|
* Author: keijo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "LpcDebugUart.h"
|
||||||
|
|
||||||
|
static LpcDebugUart *dbgu;
|
||||||
|
|
||||||
|
void retarget_init()
|
||||||
|
{
|
||||||
|
LpcPinMap none = {-1, -1}; // unused pin has negative values in it
|
||||||
|
//Sadly, it seems that only USART0 is redirected to USB.
|
||||||
|
//It means that those are pins PIO0_18 and PIO0_19
|
||||||
|
LpcPinMap txpin = { 0, 19 }; // transmit pin that goes to debugger's UART->USB converter
|
||||||
|
LpcPinMap rxpin = { 0, 18 }; // receive pin that goes to debugger's UART->USB converter
|
||||||
|
LpcDebugUartConfig cfg = { LPC_USART0, 115200, (UART0_LCR_WLEN8 | UART0_LCR_SBS_1BIT), txpin, rxpin };
|
||||||
|
dbgu = new LpcDebugUart(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// Redlib C Library function : __sys_write
|
||||||
|
// Newlib C library function : _write
|
||||||
|
//
|
||||||
|
// Function called by bottom level of printf routine within C library.
|
||||||
|
// With the default semihosting stub, this would write the
|
||||||
|
// character(s) to the debugger console window (which acts as
|
||||||
|
// stdout). But this version writes the character(s) to UART
|
||||||
|
// ******************************************************************
|
||||||
|
#if defined (__REDLIB__)
|
||||||
|
int __sys_write(int iFileHandle, char *pcBuffer, int iLength) {
|
||||||
|
#elif defined (__NEWLIB__)
|
||||||
|
int _write(int iFileHandle, char *pcBuffer, int iLength) {
|
||||||
|
#endif
|
||||||
|
if(dbgu) {
|
||||||
|
int len = iLength;
|
||||||
|
while(len > 0) {
|
||||||
|
if(*pcBuffer == '\n') { // send a CR before every LF
|
||||||
|
while(dbgu->write('\r')==0);
|
||||||
|
}
|
||||||
|
while(dbgu->write(*pcBuffer)==0);
|
||||||
|
++pcBuffer;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Function returns number of bytes written
|
||||||
|
return iLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined (__REDLIB__)
|
||||||
|
// ******************************************************************
|
||||||
|
// Redlib C Library function : __sys_readc
|
||||||
|
//
|
||||||
|
// Called by bottom level of scanf routine within RedLib C library
|
||||||
|
// to read a character. With the default semihosting stub, this
|
||||||
|
// would read the character from the debugger console window (which
|
||||||
|
// acts as stdin). But this version reads the character from UART
|
||||||
|
// ******************************************************************
|
||||||
|
|
||||||
|
int __sys_readc(void) {
|
||||||
|
char c;
|
||||||
|
if(dbgu && dbgu->read(c)) return c;
|
||||||
|
else return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
// #endif REDLIB __sys_readc()
|
||||||
|
|
||||||
|
#elif defined (__NEWLIB__)
|
||||||
|
// ******************************************************************
|
||||||
|
// Function _read
|
||||||
|
//
|
||||||
|
// Called by bottom level of scanf routine within Newlib C library
|
||||||
|
// to read multiple characters. With the default semihosting stub, this
|
||||||
|
// would read characters from the debugger console window (which
|
||||||
|
// acts as stdin). But this version reads the characters from UART
|
||||||
|
// ******************************************************************
|
||||||
|
int _read(int iFileHandle, char *pcBuffer, int iLength) {
|
||||||
|
|
||||||
|
// TODO : Should potentially check that iFileHandle == 0 to confirm
|
||||||
|
// that read is from stdin
|
||||||
|
if(!dbgu) return 0;
|
||||||
|
return dbgu->read(pcBuffer, iLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // NEWLIB _read()
|
||||||
|
|
||||||
|
}
|
||||||
14
source/shoh/src/peripherals/retarget_uart.h
Normal file
14
source/shoh/src/peripherals/retarget_uart.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* retarget_uart.h
|
||||||
|
*
|
||||||
|
* Created on: 28.9.2021
|
||||||
|
* Author: keijo
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RETARGET_UART_H_
|
||||||
|
#define RETARGET_UART_H_
|
||||||
|
|
||||||
|
void retarget_init();
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* RETARGET_UART_H_ */
|
||||||
@ -21,15 +21,19 @@ void Master::taskFunction() {
|
|||||||
{
|
{
|
||||||
case ThreadCommon::RotaryAction::Right:
|
case ThreadCommon::RotaryAction::Right:
|
||||||
Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
|
Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
|
||||||
|
printf("Right\r\n");
|
||||||
break;
|
break;
|
||||||
case ThreadCommon::RotaryAction::Left:
|
case ThreadCommon::RotaryAction::Left:
|
||||||
Board_LED_Set(ThreadCommon::RotaryAction::Left, LedState);
|
Board_LED_Set(ThreadCommon::RotaryAction::Left, LedState);
|
||||||
|
printf("Left\r\n");
|
||||||
break;
|
break;
|
||||||
case ThreadCommon::RotaryAction::Press:
|
case ThreadCommon::RotaryAction::Press:
|
||||||
Board_LED_Set(ThreadCommon::RotaryAction::Press, LedState);
|
Board_LED_Set(ThreadCommon::RotaryAction::Press, LedState);
|
||||||
|
printf("Press\r\n");
|
||||||
break;
|
break;
|
||||||
case ThreadCommon::RotaryAction::Idle:
|
case ThreadCommon::RotaryAction::Idle:
|
||||||
Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
|
Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
|
||||||
|
printf("Idle\r\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
LedState = !LedState;
|
LedState = !LedState;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user