Simple mbed library with macros
Dependents: SimpleTimer SimpleUART SimpleTimer Stoppuhr1
serial.h@7:8443cecf62d1, 2010-11-13 (annotated)
- Committer:
- Alkorin
- Date:
- Sat Nov 13 21:33:11 2010 +0000
- Revision:
- 7:8443cecf62d1
- Parent:
- 6:9e1310782abf
- Child:
- 8:f8b47457fdcf
All UARTs should now work
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Alkorin | 4:afddc4848b6c | 1 | #ifndef __SERIAL_H__ |
Alkorin | 4:afddc4848b6c | 2 | #define __SERIAL_H__ |
Alkorin | 4:afddc4848b6c | 3 | |
Alkorin | 4:afddc4848b6c | 4 | #include "mbed_globals.h" |
Alkorin | 5:b3aa0a49e21f | 5 | #include "interrupts.h" |
Alkorin | 4:afddc4848b6c | 6 | |
Alkorin | 5:b3aa0a49e21f | 7 | /* Simple Serial Managment * |
Alkorin | 5:b3aa0a49e21f | 8 | * The interrupt handler is : * |
Alkorin | 7:8443cecf62d1 | 9 | * SERIAL_INTERRUPT_HANDLER(void) * |
Alkorin | 7:8443cecf62d1 | 10 | * UART0 : Serial over USB * |
Alkorin | 7:8443cecf62d1 | 11 | * UART1 : TX p13, RX p14 * |
Alkorin | 7:8443cecf62d1 | 12 | * UART2 : TX p28, RX p27 * |
Alkorin | 7:8443cecf62d1 | 13 | * UART3 : TX p9, RX p10 */ |
Alkorin | 5:b3aa0a49e21f | 14 | |
Alkorin | 7:8443cecf62d1 | 15 | // Serial port (Choose UARTn (0,1,2,3)) |
Alkorin | 5:b3aa0a49e21f | 16 | #define UART_NUMBER UART0 |
Alkorin | 5:b3aa0a49e21f | 17 | #define UART_BASE TOKENPASTE2(LPC_,UART_NUMBER) |
Alkorin | 5:b3aa0a49e21f | 18 | |
Alkorin | 5:b3aa0a49e21f | 19 | // Peripheral Clock Selection registers (See 4.7.3 p56) |
Alkorin | 7:8443cecf62d1 | 20 | #define UART0_PCLK_REG (LPC_SC->PCLKSEL0) |
Alkorin | 7:8443cecf62d1 | 21 | #define UART1_PCLK_REG (LPC_SC->PCLKSEL0) |
Alkorin | 7:8443cecf62d1 | 22 | #define UART2_PCLK_REG (LPC_SC->PCLKSEL1) |
Alkorin | 7:8443cecf62d1 | 23 | #define UART3_PCLK_REG (LPC_SC->PCLKSEL1) |
Alkorin | 7:8443cecf62d1 | 24 | #define UART_PCLK_REG TOKENPASTE2(UART_NUMBER,_PCLK_REG) |
Alkorin | 7:8443cecf62d1 | 25 | |
Alkorin | 7:8443cecf62d1 | 26 | #define UART0_PCLK_OFFSET 6 |
Alkorin | 7:8443cecf62d1 | 27 | #define UART1_PCLK_OFFSET 8 |
Alkorin | 7:8443cecf62d1 | 28 | #define UART2_PCLK_OFFSET 16 |
Alkorin | 7:8443cecf62d1 | 29 | #define UART3_PCLK_OFFSET 18 |
Alkorin | 7:8443cecf62d1 | 30 | #define UART_PCLK_OFFSET TOKENPASTE2(UART_NUMBER,_PCLK_OFFSET) |
Alkorin | 7:8443cecf62d1 | 31 | |
Alkorin | 5:b3aa0a49e21f | 32 | #define UART0_PCLK ((LPC_SC->PCLKSEL0 >> 6) & 0x03) |
Alkorin | 7:8443cecf62d1 | 33 | #define UART1_PCLK ((LPC_SC->PCLKSEL0 >> 8) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 34 | #define UART2_PCLK ((LPC_SC->PCLKSEL1 >> 16) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 35 | #define UART3_PCLK ((LPC_SC->PCLKSEL1 >> 18) & 0x03) |
Alkorin | 5:b3aa0a49e21f | 36 | #define UART_PCLK TOKENPASTE2(UART_NUMBER,_PCLK) |
Alkorin | 5:b3aa0a49e21f | 37 | |
Alkorin | 7:8443cecf62d1 | 38 | // Pin Function Select register (See 8.5.1-8 p108) |
Alkorin | 7:8443cecf62d1 | 39 | #define UART0RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 40 | #define UART1RX_PINSEL_REG (LPC_PINCON->PINSEL1) |
Alkorin | 7:8443cecf62d1 | 41 | #define UART2RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 42 | #define UART3RX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 43 | #define UARTRX_PINSEL_REG TOKENPASTE2(UART_NUMBER,RX_PINSEL_REG) |
Alkorin | 7:8443cecf62d1 | 44 | |
Alkorin | 7:8443cecf62d1 | 45 | #define UART0TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 46 | #define UART1TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 47 | #define UART2TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 48 | #define UART3TX_PINSEL_REG (LPC_PINCON->PINSEL0) |
Alkorin | 7:8443cecf62d1 | 49 | #define UARTTX_PINSEL_REG TOKENPASTE2(UART_NUMBER,TX_PINSEL_REG) |
Alkorin | 7:8443cecf62d1 | 50 | |
Alkorin | 7:8443cecf62d1 | 51 | #define UART0RX_PINSEL_OFFSET 6 |
Alkorin | 7:8443cecf62d1 | 52 | #define UART1RX_PINSEL_OFFSET 0 |
Alkorin | 7:8443cecf62d1 | 53 | #define UART2RX_PINSEL_OFFSET 22 |
Alkorin | 7:8443cecf62d1 | 54 | #define UART3RX_PINSEL_OFFSET 2 |
Alkorin | 7:8443cecf62d1 | 55 | #define UARTRX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,RX_PINSEL_OFFSET) |
Alkorin | 7:8443cecf62d1 | 56 | |
Alkorin | 7:8443cecf62d1 | 57 | #define UART0TX_PINSEL_OFFSET 4 |
Alkorin | 7:8443cecf62d1 | 58 | #define UART1TX_PINSEL_OFFSET 30 |
Alkorin | 7:8443cecf62d1 | 59 | #define UART2TX_PINSEL_OFFSET 20 |
Alkorin | 7:8443cecf62d1 | 60 | #define UART3TX_PINSEL_OFFSET 0 |
Alkorin | 7:8443cecf62d1 | 61 | #define UARTTX_PINSEL_OFFSET TOKENPASTE2(UART_NUMBER,TX_PINSEL_OFFSET) |
Alkorin | 7:8443cecf62d1 | 62 | |
Alkorin | 7:8443cecf62d1 | 63 | #define UART0_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 64 | #define UART1_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 65 | #define UART2_PINSEL_VALUE 1UL |
Alkorin | 7:8443cecf62d1 | 66 | #define UART3_PINSEL_VALUE 2UL |
Alkorin | 7:8443cecf62d1 | 67 | #define UART_PINSEL_VALUE TOKENPASTE2(UART_NUMBER,_PINSEL_VALUE) |
Alkorin | 7:8443cecf62d1 | 68 | |
Alkorin | 5:b3aa0a49e21f | 69 | // Interrupt handlers |
Alkorin | 5:b3aa0a49e21f | 70 | #define SERIAL_INTERRUPT_HANDLER extern "C" void __irq TOKENPASTE2(UART_NUMBER,_IRQHandler) |
Alkorin | 4:afddc4848b6c | 71 | |
Alkorin | 4:afddc4848b6c | 72 | /** Bits **/ |
Alkorin | 4:afddc4848b6c | 73 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 4:afddc4848b6c | 74 | #define RBR_INT_BIT 0 |
Alkorin | 4:afddc4848b6c | 75 | // Receiver Data Ready (UnLSR, 14.4.8 p306) |
Alkorin | 4:afddc4848b6c | 76 | #define RDR_BIT 0 |
Alkorin | 4:afddc4848b6c | 77 | // Transmitter Holding Register Empty (UnLSR, 14.4.8 p306) |
Alkorin | 4:afddc4848b6c | 78 | #define THRE_BIT 5 |
Alkorin | 5:b3aa0a49e21f | 79 | // RBR Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 5:b3aa0a49e21f | 80 | #define SERIAL_INT_RX 1 |
Alkorin | 5:b3aa0a49e21f | 81 | // THRE Interrupt Enable (UnIER, 14.4.4 p302) |
Alkorin | 5:b3aa0a49e21f | 82 | #define SERIAL_INT_TX 2 |
Alkorin | 5:b3aa0a49e21f | 83 | // Divisor Latch Access Bit (UnLCR, 14.4.7 p306) |
Alkorin | 5:b3aa0a49e21f | 84 | #define DLA_BIT 7 |
Alkorin | 7:8443cecf62d1 | 85 | // Power Control for Peripherals (PCONP, 4.8.7.1 p63) |
Alkorin | 7:8443cecf62d1 | 86 | #define UART0_PCONP_BIT 3 |
Alkorin | 7:8443cecf62d1 | 87 | #define UART1_PCONP_BIT 4 |
Alkorin | 7:8443cecf62d1 | 88 | #define UART2_PCONP_BIT 24 |
Alkorin | 7:8443cecf62d1 | 89 | #define UART3_PCONP_BIT 25 |
Alkorin | 4:afddc4848b6c | 90 | |
Alkorin | 4:afddc4848b6c | 91 | /** Macros **/ |
Alkorin | 5:b3aa0a49e21f | 92 | #define SERIAL_PUTCHAR(c) while (GET_BIT_VALUE(UART_BASE->LSR, THRE_BIT) == 0); \ |
Alkorin | 5:b3aa0a49e21f | 93 | UART_BASE->THR = c; |
Alkorin | 5:b3aa0a49e21f | 94 | |
Alkorin | 5:b3aa0a49e21f | 95 | #define SERIAL_DATA_TO_READ() (GET_BIT_VALUE(UART_BASE->LSR, RDR_BIT) == 1) |
Alkorin | 5:b3aa0a49e21f | 96 | |
Alkorin | 5:b3aa0a49e21f | 97 | #define SERIAL_GETCHAR() (UART_BASE->RBR) |
Alkorin | 4:afddc4848b6c | 98 | |
Alkorin | 5:b3aa0a49e21f | 99 | // Enable interrupt for RX or TX (SERIAL_INT_RX and SERIAL_INT_TX) |
Alkorin | 5:b3aa0a49e21f | 100 | #define SERIAL_ENABLE_INTERRUPT(value) UART_BASE->IER = value; \ |
Alkorin | 5:b3aa0a49e21f | 101 | ENABLE_INTERRUPT(TOKENPASTE2(UART_NUMBER,_IRQn)); |
Alkorin | 6:9e1310782abf | 102 | |
Alkorin | 7:8443cecf62d1 | 103 | inline void SERIAL_INIT() |
Alkorin | 7:8443cecf62d1 | 104 | { |
Alkorin | 7:8443cecf62d1 | 105 | // Enable UARTn |
Alkorin | 7:8443cecf62d1 | 106 | SET_BIT_VALUE(LPC_SC->PCONP, TOKENPASTE2(UART_NUMBER,_PCONP_BIT) , 1); |
Alkorin | 7:8443cecf62d1 | 107 | // Enable FIFO and reset RX/TX FIFO (See 14.4.6 p305) |
Alkorin | 7:8443cecf62d1 | 108 | UART_BASE->FCR = 0x07; |
Alkorin | 7:8443cecf62d1 | 109 | // 8-bits, No Parity, 1 stop bit (See 14.4.7 p306) |
Alkorin | 7:8443cecf62d1 | 110 | UART_BASE->LCR = 0x03; |
Alkorin | 7:8443cecf62d1 | 111 | // Set CCLK as Peripheral Clock for UART (96MHz with mbed library) |
Alkorin | 7:8443cecf62d1 | 112 | UART_PCLK_REG = UART_PCLK_REG & ~(3UL << UART_PCLK_OFFSET) | (1UL << UART_PCLK_OFFSET); |
Alkorin | 7:8443cecf62d1 | 113 | // Define Pin's functions as UART |
Alkorin | 7:8443cecf62d1 | 114 | UARTRX_PINSEL_REG = UARTRX_PINSEL_REG & ~(3UL << UARTRX_PINSEL_OFFSET) | (UART_PINSEL_VALUE << UARTRX_PINSEL_OFFSET); |
Alkorin | 7:8443cecf62d1 | 115 | UARTTX_PINSEL_REG = UARTTX_PINSEL_REG & ~(3UL << UARTTX_PINSEL_OFFSET) | (UART_PINSEL_VALUE << UARTTX_PINSEL_OFFSET); |
Alkorin | 7:8443cecf62d1 | 116 | } |
Alkorin | 4:afddc4848b6c | 117 | |
Alkorin | 4:afddc4848b6c | 118 | // See 14.4.5 p303 |
Alkorin | 4:afddc4848b6c | 119 | inline int SERIAL_CHECK_INTERRUPT(void) { |
Alkorin | 4:afddc4848b6c | 120 | uint32_t serialStatus = UART_BASE->IIR; |
Alkorin | 4:afddc4848b6c | 121 | |
Alkorin | 4:afddc4848b6c | 122 | if (serialStatus & 1) // IntStatus, 1 = No Interrupt is pending. |
Alkorin | 4:afddc4848b6c | 123 | return 0; |
Alkorin | 4:afddc4848b6c | 124 | |
Alkorin | 4:afddc4848b6c | 125 | serialStatus = (serialStatus >> 1) & 0x3; // IntId, 2 = More than threshold data to read, 6 = Some caracters to read |
Alkorin | 4:afddc4848b6c | 126 | if (serialStatus != 2 && serialStatus != 6) |
Alkorin | 4:afddc4848b6c | 127 | return 0; |
Alkorin | 4:afddc4848b6c | 128 | |
Alkorin | 4:afddc4848b6c | 129 | return 1; |
Alkorin | 4:afddc4848b6c | 130 | } |
Alkorin | 4:afddc4848b6c | 131 | |
Alkorin | 5:b3aa0a49e21f | 132 | inline void SERIAL_SETBAUD(unsigned int baud) { |
Alkorin | 5:b3aa0a49e21f | 133 | // Peripheral Clock Selection register bit values (See Table 42, p57) |
Alkorin | 5:b3aa0a49e21f | 134 | static int divisors[4] = { 4, 1, 2, 8 }; |
Alkorin | 5:b3aa0a49e21f | 135 | |
Alkorin | 5:b3aa0a49e21f | 136 | uint16_t divisorValue = ((SystemCoreClock / 16 / baud) * divisors[UART_PCLK]); |
Alkorin | 5:b3aa0a49e21f | 137 | |
Alkorin | 6:9e1310782abf | 138 | UART_BASE->LCR |= (1 << DLA_BIT); |
Alkorin | 5:b3aa0a49e21f | 139 | UART_BASE->DLM = (uint8_t) (divisorValue >> 8); |
Alkorin | 5:b3aa0a49e21f | 140 | UART_BASE->DLL = (uint8_t) divisorValue; |
Alkorin | 6:9e1310782abf | 141 | UART_BASE->LCR &= ~(1 << DLA_BIT); |
Alkorin | 5:b3aa0a49e21f | 142 | } |
Alkorin | 4:afddc4848b6c | 143 | |
Alkorin | 0:aa3c3d1a5918 | 144 | #endif |