|
|
@@ -40,7 +40,6 @@ |
|
|
|
#define RX_BUFFER_SIZE 64 |
|
|
|
#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest |
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////// |
|
|
|
// changes not recommended below this point.... |
|
|
|
//////////////////////////////////////////////////////////////// |
|
|
@@ -74,7 +73,11 @@ static volatile uint8_t rx_buffer_tail = 0; |
|
|
|
// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS |
|
|
|
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer |
|
|
|
|
|
|
|
#ifdef KINETISK_UART1_FIFO |
|
|
|
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE |
|
|
|
#else |
|
|
|
#define C2_ENABLE UART_C2_TE | UART_C2_RE | UART_C2_RIE |
|
|
|
#endif |
|
|
|
#define C2_TX_ACTIVE C2_ENABLE | UART_C2_TIE |
|
|
|
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE |
|
|
|
#define C2_TX_INACTIVE C2_ENABLE |
|
|
@@ -92,8 +95,15 @@ void serial2_begin(uint32_t divisor) |
|
|
|
UART1_BDH = (divisor >> 13) & 0x1F; |
|
|
|
UART1_BDL = (divisor >> 5) & 0xFF; |
|
|
|
UART1_C4 = divisor & 0x1F; |
|
|
|
#ifdef KINETISK_UART1_FIFO |
|
|
|
UART1_C1 = UART_C1_ILT; |
|
|
|
UART1_TWFIFO = 2; // tx watermark, causes S1_TDRE to set |
|
|
|
UART1_RWFIFO = 4; // rx watermark, causes S1_RDRF to set |
|
|
|
UART1_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE; |
|
|
|
#else |
|
|
|
UART1_C1 = 0; |
|
|
|
UART1_PFIFO = 0; |
|
|
|
#endif |
|
|
|
UART1_C2 = C2_TX_INACTIVE; |
|
|
|
NVIC_SET_PRIORITY(IRQ_UART1_STATUS, IRQ_PRIORITY); |
|
|
|
NVIC_ENABLE_IRQ(IRQ_UART1_STATUS); |
|
|
@@ -142,7 +152,7 @@ void serial2_end(void) |
|
|
|
|
|
|
|
void serial2_putchar(uint32_t c) |
|
|
|
{ |
|
|
|
uint32_t head; |
|
|
|
uint32_t head, n; |
|
|
|
|
|
|
|
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; |
|
|
|
head = tx_buffer_head; |
|
|
@@ -153,7 +163,9 @@ void serial2_putchar(uint32_t c) |
|
|
|
if ((UART1_S1 & UART_S1_TDRE)) { |
|
|
|
uint32_t tail = tx_buffer_tail; |
|
|
|
if (++tail >= TX_BUFFER_SIZE) tail = 0; |
|
|
|
UART1_D = tx_buffer[tail]; |
|
|
|
n = tx_buffer[tail]; |
|
|
|
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2); |
|
|
|
UART1_D = n; |
|
|
|
tx_buffer_tail = tail; |
|
|
|
} |
|
|
|
} else if (priority >= 256) { |
|
|
@@ -166,11 +178,48 @@ void serial2_putchar(uint32_t c) |
|
|
|
UART1_C2 = C2_TX_ACTIVE; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef KINETISK_UART1_FIFO |
|
|
|
void serial2_write(const void *buf, unsigned int count) |
|
|
|
{ |
|
|
|
const uint8_t *p = (const uint8_t *)buf; |
|
|
|
const uint8_t *end = p + count; |
|
|
|
uint32_t head, n; |
|
|
|
|
|
|
|
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; |
|
|
|
while (p < end) { |
|
|
|
head = tx_buffer_head; |
|
|
|
if (++head >= TX_BUFFER_SIZE) head = 0; |
|
|
|
if (tx_buffer_tail == head) { |
|
|
|
UART1_C2 = C2_TX_ACTIVE; |
|
|
|
do { |
|
|
|
int priority = nvic_execution_priority(); |
|
|
|
if (priority <= IRQ_PRIORITY) { |
|
|
|
if ((UART1_S1 & UART_S1_TDRE)) { |
|
|
|
uint32_t tail = tx_buffer_tail; |
|
|
|
if (++tail >= TX_BUFFER_SIZE) tail = 0; |
|
|
|
n = tx_buffer[tail]; |
|
|
|
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2); |
|
|
|
UART1_D = n; |
|
|
|
tx_buffer_tail = tail; |
|
|
|
} |
|
|
|
} else if (priority >= 256) { |
|
|
|
yield(); |
|
|
|
} |
|
|
|
} while (tx_buffer_tail == head); |
|
|
|
} |
|
|
|
tx_buffer[head] = *p++; |
|
|
|
transmitting = 1; |
|
|
|
tx_buffer_head = head; |
|
|
|
} |
|
|
|
UART1_C2 = C2_TX_ACTIVE; |
|
|
|
} |
|
|
|
#else |
|
|
|
void serial2_write(const void *buf, unsigned int count) |
|
|
|
{ |
|
|
|
const uint8_t *p = (const uint8_t *)buf; |
|
|
|
while (count-- > 0) serial2_putchar(*p++); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
void serial2_flush(void) |
|
|
|
{ |
|
|
@@ -224,6 +273,12 @@ int serial2_peek(void) |
|
|
|
|
|
|
|
void serial2_clear(void) |
|
|
|
{ |
|
|
|
#ifdef KINETISK_UART1_FIFO |
|
|
|
if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; |
|
|
|
UART1_C2 &= ~(UART_C2_RE | UART_C2_RIE | UART_C2_ILIE); |
|
|
|
UART1_CFIFO = UART_CFIFO_RXFLUSH; |
|
|
|
UART1_C2 |= (UART_C2_RE | UART_C2_RIE | UART_C2_ILIE); |
|
|
|
#endif |
|
|
|
rx_buffer_head = rx_buffer_tail; |
|
|
|
} |
|
|
|
|
|
|
@@ -239,10 +294,66 @@ void uart1_status_isr(void) |
|
|
|
{ |
|
|
|
uint32_t head, tail, n; |
|
|
|
uint8_t c; |
|
|
|
#ifdef KINETISK_UART1_FIFO |
|
|
|
uint32_t newhead; |
|
|
|
uint8_t avail; |
|
|
|
|
|
|
|
//digitalWriteFast(4, HIGH); |
|
|
|
if (UART1_S1 & (UART_S1_RDRF | UART_S1_IDLE)) { |
|
|
|
__disable_irq(); |
|
|
|
avail = UART1_RCFIFO; |
|
|
|
if (avail == 0) { |
|
|
|
// The only way to clear the IDLE interrupt flag is |
|
|
|
// to read the data register. But reading with no |
|
|
|
// data causes a FIFO underrun, which causes the |
|
|
|
// FIFO to return corrupted data. If anyone from |
|
|
|
// Freescale reads this, what a poor design! There |
|
|
|
// write should be a write-1-to-clear for IDLE. |
|
|
|
c = UART1_D; |
|
|
|
// flushing the fifo recovers from the underrun, |
|
|
|
// but there's a possible race condition where a |
|
|
|
// new character could be received between reading |
|
|
|
// RCFIFO == 0 and flushing the FIFO. To minimize |
|
|
|
// the chance, interrupts are disabled so a higher |
|
|
|
// priority interrupt (hopefully) doesn't delay. |
|
|
|
// TODO: change this to disabling the IDLE interrupt |
|
|
|
// which won't be simple, since we already manage |
|
|
|
// which transmit interrupts are enabled. |
|
|
|
UART1_CFIFO = UART_CFIFO_RXFLUSH; |
|
|
|
__enable_irq(); |
|
|
|
} else { |
|
|
|
__enable_irq(); |
|
|
|
head = rx_buffer_head; |
|
|
|
tail = rx_buffer_tail; |
|
|
|
do { |
|
|
|
n = UART1_D; |
|
|
|
if (use9Bits && (UART1_C3 & 0x80)) n |= 0x100; |
|
|
|
newhead = head + 1; |
|
|
|
if (newhead >= RX_BUFFER_SIZE) newhead = 0; |
|
|
|
if (newhead != tail) { |
|
|
|
head = newhead; |
|
|
|
rx_buffer[head] = n; |
|
|
|
} |
|
|
|
} while (--avail > 0); |
|
|
|
rx_buffer_head = head; |
|
|
|
} |
|
|
|
} |
|
|
|
c = UART1_C2; |
|
|
|
if ((c & UART_C2_TIE) && (UART1_S1 & UART_S1_TDRE)) { |
|
|
|
head = tx_buffer_head; |
|
|
|
tail = tx_buffer_tail; |
|
|
|
do { |
|
|
|
if (tail == head) break; |
|
|
|
if (++tail >= TX_BUFFER_SIZE) tail = 0; |
|
|
|
avail = UART1_S1; |
|
|
|
n = tx_buffer[tail]; |
|
|
|
if (use9Bits) UART1_C3 = (UART1_C3 & ~0x40) | ((n & 0x100) >> 2); |
|
|
|
UART1_D = n; |
|
|
|
} while (UART1_TCFIFO < 8); |
|
|
|
tx_buffer_tail = tail; |
|
|
|
if (UART1_S1 & UART_S1_TDRE) UART1_C2 = C2_TX_COMPLETING; |
|
|
|
} |
|
|
|
#else |
|
|
|
if (UART1_S1 & UART_S1_RDRF) { |
|
|
|
//digitalWriteFast(5, HIGH); |
|
|
|
n = UART1_D; |
|
|
|
if (use9Bits && (UART1_C3 & 0x80)) n |= 0x100; |
|
|
|
head = rx_buffer_head + 1; |
|
|
@@ -251,11 +362,9 @@ void uart1_status_isr(void) |
|
|
|
rx_buffer[head] = n; |
|
|
|
rx_buffer_head = head; |
|
|
|
} |
|
|
|
//digitalWriteFast(5, LOW); |
|
|
|
} |
|
|
|
c = UART1_C2; |
|
|
|
if ((c & UART_C2_TIE) && (UART1_S1 & UART_S1_TDRE)) { |
|
|
|
//digitalWriteFast(5, HIGH); |
|
|
|
head = tx_buffer_head; |
|
|
|
tail = tx_buffer_tail; |
|
|
|
if (head == tail) { |
|
|
@@ -267,13 +376,12 @@ void uart1_status_isr(void) |
|
|
|
UART1_D = n; |
|
|
|
tx_buffer_tail = tail; |
|
|
|
} |
|
|
|
//digitalWriteFast(5, LOW); |
|
|
|
} |
|
|
|
#endif |
|
|
|
if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { |
|
|
|
transmitting = 0; |
|
|
|
UART1_C2 = C2_TX_INACTIVE; |
|
|
|
} |
|
|
|
//digitalWriteFast(4, LOW); |
|
|
|
} |
|
|
|
|
|
|
|
|