YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
uart_msp432.cpp
1#include <cstring>
2#include <cassert>
3
4#include "uart_msp432.h"
5#include "gpio_msp432.h"
6#include "irq_dispatcher.h"
7#include "task.h"
8#include "msp.h"
9
10// If existing, use the global SubsystemMasterClock. If not, use our own
11// copy of the SystemCoreClock, assuming that MCLK equals SMCLK ...
12uint32_t UART_CLK = SystemCoreClock;
13extern uint32_t SubsystemMasterClock __attribute__((weak,alias("UART_CLK")));
14
15
16function<void(char)> uart_msp432::_intHandler[4] = {nullptr, nullptr, nullptr, nullptr};
17
18uart_msp432::uart_msp432(EUSCI_A_Type * module, uint32_t baud,uart_mode_t mode)
19: _init(false), _EUSCI(module), _baud(baud), _mode(mode),
20 _port(0), _rx_pin(0), _tx_pin(0) {
21 // make sure the irq_dispatcher gets linked in
22 irq_dispatcher::link_in();
23}
24
25void uart_msp432::init() {
26 // Configure hardware characteristics of the 4 UART modules
28 if (_EUSCI==EUSCI_A0) { _port = 1; _rx_pin = 2; _tx_pin = 3; }
29 else if (_EUSCI==EUSCI_A1) { _port = 2; _rx_pin = 2; _tx_pin = 3; }
30 else if (_EUSCI==EUSCI_A2) { _port = 3; _rx_pin = 2; _tx_pin = 3; }
31 else if (_EUSCI==EUSCI_A3) { _port = 9; _rx_pin = 6; _tx_pin = 7; }
32 else assert(false);
33 gpio_msp432 rx_pin(PORT_PIN(_port,_rx_pin));
34 gpio_msp432 tx_pin(PORT_PIN(_port,_tx_pin));
35 rx_pin.setSEL(1);
36 tx_pin.setSEL(1);
37
38 // put EUSCI module in reset state
40 _EUSCI->CTLW0 = EUSCI_A_CTLW0_SWRST;
41
42 // Configure SMCLK as clock source
45
46 // Disable modulation stages
48 _EUSCI->MCTLW &= ~(EUSCI_A_MCTLW_BRS_MASK |
51
52 // Disable interrupts
54 _EUSCI->IE &= ~(EUSCI_A_IE_RXIE |
58
59 // Configure UART protocol (default 8N1)
61 uartMode(_mode);
62
63 // Set baud rate
65 setBaudrate(_baud);
66
67 _init = true;
68}
69
70uart_msp432::~uart_msp432() {
71 // Check if we need to de-configure
72 if (!_init) return;
73 // Wait for pending operations
74 while (_EUSCI->STATW & EUSCI_A_STATW_BUSY);
75 // Reset CTLW0 register to default values
76 // (EUSCI_A is in reset state)
78 _EUSCI->CTLW0 = EUSCI_A_CTLW0_SWRST;
79 // De-configure the digital RX/TX lines
81 gpio_msp432 rx_pin(PORT_PIN(_port,_rx_pin));
82 gpio_msp432 tx_pin(PORT_PIN(_port,_tx_pin));
83 rx_pin.setSEL(0);
84 tx_pin.setSEL(0);
85}
86
87bool uart_msp432::available() {
88 if (!_init) init();
89 return _EUSCI->IFG & EUSCI_A_IFG_RXIFG;
90}
91
92char uart_msp432::getc() {
93 if (!_init) init();
94 // Wait until the RX Buffer is filled....
95 while( (_EUSCI->IFG & EUSCI_A_IFG_RXIFG) == 0);
96 // Transfer single char from RX buffer
97 return _EUSCI->RXBUF;;
98}
99
100void uart_msp432::putc(char c) {
101 if (!_init) init();
102 // Wait until the TX Buffer is empty....
103 while( (_EUSCI->IFG & EUSCI_A_IFG_TXIFG) == 0);
104 // Transfer single char to TX buffer
105 _EUSCI->TXBUF = (uint16_t)c;
106}
107
108size_t uart_msp432::puts(const char *s) {
109 size_t i, len;
110 len = strlen(s);
111 for (i=0; i < len; i++) putc(s[i]);
112 return len;
113}
114
115void uart_msp432::uartMode(uart_mode_t mode) {
116 _mode = mode;
117
118 // put module in reset state
119 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_SWRST;
120
121 if (mode & UART::BITS_7) {
122 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_SEVENBIT;
123 }
124 if (mode & UART::BITS_8) {
125 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SEVENBIT;
126 }
127 if (mode & UART::NO_PARITY) {
128 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_PEN;
129 }
130 if (mode & UART::EVEN_PARITY) {
131 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_PEN;
132 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_PAR;
133 }
134 if (mode & UART::ODD_PARITY) {
135 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_PEN;
136 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_PAR;
137 }
138 if (mode & UART::STOPBITS_1) {
139 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SPB;
140 }
141 if (mode & UART::STOPBITS_2) {
142 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_SPB;
143 }
144
145 // enable the UART module again
146 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_SWRST;
147}
148
149void uart_msp432::setBaudrate(uint32_t baud) {
150 _baud = baud;
151 _EUSCI->BRW = (uint16_t)(SubsystemMasterClock / baud);
152}
153
154void uart_msp432::sendBreak(uint16_t ms) {
155 if (ms == 0) {
156 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_TXBRK;
157 } else if (ms == 0xffff) {
158 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_TXBRK;
159 } else {
160 _EUSCI->CTLW0 |= EUSCI_A_CTLW0_TXBRK;
161 task::sleep_ms(ms);
162 _EUSCI->CTLW0 &= ~EUSCI_A_CTLW0_TXBRK;
163 }
164}
165
166void uart_msp432::setDTR(bool) {
167 assert(false && "Not implemented");
168}
169
170void uart_msp432::setRTS(bool) {
171 assert(false && "Not implemented");
172}
173
174void uart_msp432::uartAttachIrq(function<void(char)> f) {
175 if (!_init) init();
176 uint8_t index = (((uint32_t)_EUSCI) >> 10) & 0x3;
177 _intHandler[index] = f;
178 _EUSCI->IE = EUSCI_A_IE_RXIE;
179 NVIC_EnableIRQ((IRQn_Type)(16 + index));
180}
181
182void uart_msp432::uartDetachIrq () {
183 if (!_init) init();
184 uint8_t index = (((uint32_t)_EUSCI) >> 10) & 0x3;
185 _EUSCI->IE = 0;
186 NVIC_DisableIRQ((IRQn_Type)(16 + index));
187 _intHandler[index] = nullptr;
188}
189
190void uart_msp432::uartEnableIrq () {
191 _EUSCI->IE = EUSCI_A_IE_RXIE;
192}
193
194void uart_msp432::uartDisableIrq() {
195 _EUSCI->IE = 0;
196}
197
198void uart_msp432::enableFIFO(bool val) {
199 // no-op
200 (void)(val);
201}
202
203void uart_msp432::handleIrq(EUSCI_A_Type * uart) {
204 char c = uart->RXBUF;
205 uint8_t index = (((uint32_t)uart) >> 10) & 0x3;
206 if (_intHandler[index])
207 _intHandler[index](c);
208}
209
210
211// Interrupt handler for EUSCIA0..4
213extern "C" {
214void EUSCIA0_UART_IRQHandler(void) {
215 uart_msp432::handleIrq(EUSCI_A0);
216}
217void EUSCIA1_UART_IRQHandler(void) {
218 uart_msp432::handleIrq(EUSCI_A1);
219}
220void EUSCIA2_UART_IRQHandler(void) {
221 uart_msp432::handleIrq(EUSCI_A2);
222}
223void EUSCIA3_UART_IRQHandler(void) {
224 uart_msp432::handleIrq(EUSCI_A3);
225}
226} // extern "C"
227
__IO uint16_t IFG
__IO uint16_t STATW
#define EUSCI_A_CTLW0_PAR
__IO uint16_t CTLW0
#define EUSCI_A_MCTLW_BRF_MASK
#define EUSCI_A_CTLW0_SPB
#define EUSCI_A_IFG_RXIFG
#define EUSCI_A_STATW_BUSY
#define EUSCI_A_IFG_TXIFG
#define EUSCI_A_CTLW0_TXBRK
#define EUSCI_A_CTLW0_SWRST
#define EUSCI_A_MCTLW_BRS_MASK
__IO uint16_t TXBUF
#define EUSCI_A_IE_STTIE
#define EUSCI_A_MCTLW_OS16
__IO uint16_t MCTLW
#define EUSCI_A_CTLW0_SSEL__SMCLK
#define EUSCI_A_CTLW0_PEN
#define EUSCI_A_IE_RXIE
__IO uint16_t IE
#define EUSCI_A_CTLW0_SEVENBIT
__IO uint16_t BRW
#define EUSCI_A_IE_TXCPTIE
__I uint16_t RXBUF
#define EUSCI_A_IE_TXIE
void __attribute__((noreturn))(*rom_reset_usb_boot_fn)(uint32_t
Reboot the device into BOOTSEL mode.
Definition bootrom.h:66