EFM32 Pearl Gecko 12 Software Documentation  efm32pg12-doc-5.1.2
retargetserial.c
Go to the documentation of this file.
1 /***************************************************************************/
17 #include <stdio.h>
18 #include "em_device.h"
19 #include "em_cmu.h"
20 #include "em_core.h"
21 #include "em_gpio.h"
22 #include "retargetserial.h"
23 
24 /***************************************************************************/
29 #if defined(RETARGET_USART)
30 #include "em_usart.h"
31 #endif
32 
33 #if defined(RETARGET_LEUART)
34 #include "em_leuart.h"
35 #endif
36 
37 /* Receive buffer */
38 #define RXBUFSIZE 8
39 static volatile int rxReadIndex = 0;
40 static volatile int rxWriteIndex = 0;
41 static volatile int rxCount = 0;
42 static volatile uint8_t rxBuffer[RXBUFSIZE];
43 static uint8_t LFtoCRLF = 0;
44 static bool initialized = false;
46 /**************************************************************************/
49 void RETARGET_IRQ_NAME(void)
50 {
51 #if defined(RETARGET_USART)
52  if (RETARGET_UART->STATUS & USART_STATUS_RXDATAV)
53  {
54 #else
55  if (RETARGET_UART->IF & LEUART_IF_RXDATAV)
56  {
57 #endif
58 
59  /* Store Data */
60  rxBuffer[rxWriteIndex] = RETARGET_RX(RETARGET_UART);
61  rxWriteIndex++;
62  rxCount++;
63  if (rxWriteIndex == RXBUFSIZE)
64  {
65  rxWriteIndex = 0;
66  }
67  /* Check for overflow - flush buffer */
68  if (rxCount > RXBUFSIZE)
69  {
70  rxWriteIndex = 0;
71  rxCount = 0;
72  rxReadIndex = 0;
73  }
74  }
75 }
76 
79 /**************************************************************************/
83 void RETARGET_SerialCrLf(int on)
84 {
85  if (on)
86  LFtoCRLF = 1;
87  else
88  LFtoCRLF = 0;
89 }
90 
91 
92 /**************************************************************************/
96 {
97  /* Enable peripheral clocks */
99  /* Configure GPIO pins */
101  /* To avoid false start, configure output as high */
102  GPIO_PinModeSet(RETARGET_TXPORT, RETARGET_TXPIN, gpioModePushPull, 1);
103  GPIO_PinModeSet(RETARGET_RXPORT, RETARGET_RXPIN, gpioModeInput, 0);
104 
105 #if defined(RETARGET_USART)
106  USART_TypeDef *usart = RETARGET_UART;
108 
109  /* Enable DK RS232/UART switch */
110  RETARGET_PERIPHERAL_ENABLE();
111 
112  CMU_ClockEnable(RETARGET_CLK, true);
113 
114  /* Configure USART for basic async operation */
115  init.enable = usartDisable;
116  USART_InitAsync(usart, &init);
117 
118  /* Enable pins at correct UART/USART location. */
119  #if defined( USART_ROUTEPEN_RXPEN )
121  usart->ROUTELOC0 = ( usart->ROUTELOC0 &
124  | ( RETARGET_TX_LOCATION << _USART_ROUTELOC0_TXLOC_SHIFT )
125  | ( RETARGET_RX_LOCATION << _USART_ROUTELOC0_RXLOC_SHIFT );
126  #else
127  usart->ROUTE = USART_ROUTE_RXPEN | USART_ROUTE_TXPEN | RETARGET_LOCATION;
128  #endif
129 
130  /* Clear previous RX interrupts */
131  USART_IntClear(RETARGET_UART, USART_IF_RXDATAV);
132  NVIC_ClearPendingIRQ(RETARGET_IRQn);
133 
134  /* Enable RX interrupts */
135  USART_IntEnable(RETARGET_UART, USART_IF_RXDATAV);
136  NVIC_EnableIRQ(RETARGET_IRQn);
137 
138  /* Finally enable it */
139  USART_Enable(usart, usartEnable);
140 
141 #else
142  LEUART_TypeDef *leuart = RETARGET_UART;
144 
145  /* Enable DK LEUART/RS232 switch */
146  RETARGET_PERIPHERAL_ENABLE();
147 
148  /* Enable CORE LE clock in order to access LE modules */
149  CMU_ClockEnable(cmuClock_CORELE, true);
150 
151 #if defined(RETARGET_VCOM)
152  /* Select HFXO/2 for LEUARTs (and wait for it to stabilize) */
153 #if defined(_CMU_LFCLKSEL_LFB_HFCORECLKLEDIV2)
154  CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_CORELEDIV2);
155 #else
157 #endif
158 #else
159  /* Select LFXO for LEUARTs (and wait for it to stabilize) */
161 #endif
162 
163  CMU_ClockEnable(RETARGET_CLK, true);
164 
165  /* Do not prescale clock */
166  CMU_ClockDivSet(RETARGET_CLK, cmuClkDiv_1);
167 
168  /* Configure LEUART */
169  init.enable = leuartDisable;
170 #if defined(RETARGET_VCOM)
171  init.baudrate = 115200;
172 #endif
173  LEUART_Init(leuart, &init);
174  /* Enable pins at default location */
175  #if defined( LEUART_ROUTEPEN_RXPEN )
177  leuart->ROUTELOC0 = ( leuart->ROUTELOC0 &
180  | ( RETARGET_TX_LOCATION << _LEUART_ROUTELOC0_TXLOC_SHIFT )
181  | ( RETARGET_RX_LOCATION << _LEUART_ROUTELOC0_RXLOC_SHIFT );
182  #else
183  leuart->ROUTE = LEUART_ROUTE_RXPEN | LEUART_ROUTE_TXPEN | RETARGET_LOCATION;
184  #endif
185 
186  /* Clear previous RX interrupts */
187  LEUART_IntClear(RETARGET_UART, LEUART_IF_RXDATAV);
188  NVIC_ClearPendingIRQ(RETARGET_IRQn);
189 
190  /* Enable RX interrupts */
191  LEUART_IntEnable(RETARGET_UART, LEUART_IF_RXDATAV);
192  NVIC_EnableIRQ(RETARGET_IRQn);
193 
194  /* Finally enable it */
195  LEUART_Enable(leuart, leuartEnable);
196 #endif
197 
198 #if !defined(__CROSSWORKS_ARM) && defined(__GNUC__)
199  setvbuf(stdout, NULL, _IONBF, 0); /*Set unbuffered mode for stdout (newlib)*/
200 #endif
201 
202  initialized = true;
203 }
204 
205 
206 /**************************************************************************/
211 {
212  int c = -1;
214 
215  if (initialized == false)
216  {
218  }
219 
221  if (rxCount > 0)
222  {
223  c = rxBuffer[rxReadIndex];
224  rxReadIndex++;
225  if (rxReadIndex == RXBUFSIZE)
226  {
227  rxReadIndex = 0;
228  }
229  rxCount--;
230  }
232 
233  return c;
234 }
235 
236 /**************************************************************************/
242 {
243  if (initialized == false)
244  {
246  }
247 
248  /* Add CR or LF to CRLF if enabled */
249  if (LFtoCRLF && (c == '\n'))
250  {
251  RETARGET_TX(RETARGET_UART, '\r');
252  }
253  RETARGET_TX(RETARGET_UART, c);
254 
255  if (LFtoCRLF && (c == '\r'))
256  {
257  RETARGET_TX(RETARGET_UART, '\n');
258  }
259 
260  return c;
261 }
Clock management unit (CMU) API.
void CMU_ClockSelectSet(CMU_Clock_TypeDef clock, CMU_Select_TypeDef ref)
Select reference clock/oscillator used for a clock branch.
Definition: em_cmu.c:2521
#define _USART_ROUTELOC0_RXLOC_MASK
int RETARGET_ReadChar(void)
Receive a byte from USART/LEUART and put into global buffer.
#define CORE_DECLARE_IRQ_STATE
Definition: em_core.h:85
#define RXBUFSIZE
__IOM uint32_t ROUTELOC0
static bool initialized
__STATIC_INLINE void USART_IntClear(USART_TypeDef *usart, uint32_t flags)
Clear one or more pending USART interrupts.
Definition: em_usart.h:757
#define _USART_ROUTELOC0_RXLOC_SHIFT
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
Universal synchronous/asynchronous receiver/transmitter (USART/UART) peripheral API.
#define _USART_ROUTELOC0_TXLOC_MASK
__STATIC_INLINE void USART_IntEnable(USART_TypeDef *usart, uint32_t flags)
Enable one or more USART interrupts.
Definition: em_usart.h:796
USART_Enable_TypeDef enable
Definition: em_usart.h:295
Retarget stdout to a serial port.
__STATIC_INLINE void LEUART_IntClear(LEUART_TypeDef *leuart, uint32_t flags)
Clear one or more pending LEUART interrupts.
Definition: em_leuart.h:169
void LEUART_Init(LEUART_TypeDef *leuart, LEUART_Init_TypeDef const *init)
Init LEUART.
Definition: em_leuart.c:461
__STATIC_INLINE void LEUART_IntEnable(LEUART_TypeDef *leuart, uint32_t flags)
Enable one or more LEUART interrupts.
Definition: em_leuart.h:208
__IOM uint32_t ROUTEPEN
#define CORE_ENTER_ATOMIC()
Definition: em_core.h:138
void GPIO_PinModeSet(GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
Set the mode for a GPIO pin.
Definition: em_gpio.c:269
#define USART_IF_RXDATAV
General Purpose IO (GPIO) peripheral API.
int RETARGET_WriteChar(char c)
Transmit single byte to USART/LEUART.
#define _LEUART_ROUTELOC0_RXLOC_MASK
#define _LEUART_ROUTELOC0_TXLOC_SHIFT
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
Definition: em_cmu.c:1453
void LEUART_Enable(LEUART_TypeDef *leuart, LEUART_Enable_TypeDef enable)
Enable/disable LEUART receiver and/or transmitter.
Definition: em_leuart.c:357
__IOM uint32_t ROUTELOC0
__IOM uint32_t ROUTEPEN
#define LEUART_IF_RXDATAV
static volatile int rxCount
Low Energy Universal Asynchronous Receiver/Transmitter (LEUART) peripheral API.
static volatile int rxWriteIndex
static volatile int rxReadIndex
void RETARGET_SerialInit(void)
Intializes UART/LEUART.
#define CORE_EXIT_ATOMIC()
Definition: em_core.h:142
#define USART_STATUS_RXDATAV
#define _LEUART_ROUTELOC0_RXLOC_SHIFT
#define USART_ROUTEPEN_RXPEN
#define _USART_ROUTELOC0_TXLOC_SHIFT
static volatile uint8_t rxBuffer[RXBUFSIZE]
#define cmuClkDiv_1
Definition: em_cmu.h:149
#define _LEUART_ROUTELOC0_TXLOC_MASK
#define USART_INITASYNC_DEFAULT
Definition: em_usart.h:356
void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
Enable/disable USART/UART receiver and/or transmitter.
Definition: em_usart.c:527
void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
Init USART/UART for normal asynchronous mode.
Definition: em_usart.c:569
#define LEUART_INIT_DEFAULT
Definition: em_leuart.h:132
void RETARGET_SerialCrLf(int on)
UART/LEUART toggle LF to CRLF conversion.
static uint8_t LFtoCRLF
#define USART_ROUTEPEN_TXPEN
void CMU_ClockDivSet(CMU_Clock_TypeDef clock, CMU_ClkDiv_TypeDef div)
Set clock divisor/prescaler.
Definition: em_cmu.c:1244
LEUART_Enable_TypeDef enable
Definition: em_leuart.h:110