Contiki 3.x
uart1.c
Go to the documentation of this file.
1 /**
2  * \addtogroup stm32w-cpu
3  *
4  * @{
5  */
6 
7 /*
8  * Copyright (c) 2010, STMicroelectronics.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * 3. The name of the author may not be used to endorse or promote
21  * products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  *
36  *
37  */
38 
39 /**
40 * \file
41 * Machine dependent STM32W UART1 code.
42 * \author
43 * Salvatore Pitrulli
44 * \version
45 * 0.1
46 * \since
47 * 03.04.2010
48 */
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include "sys/energest.h"
53 #include "dev/uart1.h"
54 #include "dev/watchdog.h"
55 #include "lib/ringbuf.h"
56 #include "dev/leds.h"
57 
58 static int (*uart1_input_handler) (unsigned char c);
59 
60 void uart1_rx_interrupt(void);
61 
62 void uart1_tx_interrupt(void);
63 
64 static volatile uint8_t transmitting;
65 
66 #ifdef UART1_CONF_TX_WITH_INTERRUPT
67 #define TX_WITH_INTERRUPT UART1_CONF_TX_WITH_INTERRUPT
68 #else /* UART1_CONF_TX_WITH_INTERRUPT */
69 #define TX_WITH_INTERRUPT 1
70 #endif /* UART1_CONF_TX_WITH_INTERRUPT */
71 
72 
73 #if TX_WITH_INTERRUPT
74 #ifdef UART1_CONF_TX_BUFSIZE
75 #define UART1_TX_BUFSIZE UART1_CONF_TX_BUFSIZE
76 #else /* UART1_CONF_TX_BUFSIZE */
77 #define UART1_TX_BUFSIZE 64
78 #endif /* UART1_CONF_TX_BUFSIZE */
79 static struct ringbuf txbuf;
80 static uint8_t txbuf_data[UART1_TX_BUFSIZE];
81 #endif /* TX_WITH_INTERRUPT */
82 /*---------------------------------------------------------------------------*/
83 void
84 uart1_set_input(int (*input) (unsigned char c))
85 {
86  uart1_input_handler = input;
87 }
88 /*---------------------------------------------------------------------------*/
89 void
90 uart1_writeb(unsigned char c)
91 {
93 #if TX_WITH_INTERRUPT
94  /*
95  * Put the outgoing byte on the transmission buffer. If the buffer
96  * is full, we just keep on trying to put the byte into the buffer
97  * until it is possible to put it there.
98  */
99  while(ringbuf_put(&txbuf, c) == 0);
100 
101  /*
102  * If there is no transmission going, we need to start it by putting
103  * the first byte into the UART.
104  */
105  if(transmitting == 0) {
106  transmitting = 1;
107  SC1_DATA = ringbuf_get(&txbuf);
108  INT_SC1FLAG = INT_SCTXFREE;
109  INT_SC1CFG |= INT_SCTXFREE;
110  }
111 #else /* TX_WITH_INTERRUPT */
112 
113  /* Loop until the transmission buffer is available. */
114  while((INT_SC1FLAG & INT_SCTXFREE) == 0);
115 
116  /* Transmit the data. */
117  SC1_DATA = c;
118 
119  INT_SC1FLAG = INT_SCTXFREE;
120 #endif /* TX_WITH_INTERRUPT */
121 }
122 /*---------------------------------------------------------------------------*/
123 #if ! WITH_UIP
124 /* If WITH_UIP is defined, putchar() is defined by the SLIP driver */
125 #endif /* ! WITH_UIP */
126 /*---------------------------------------------------------------------------*/
127 /*
128  * Initalize the RS232 port.
129  */
130 void
131 uart1_init(unsigned long ubr)
132 {
133  uint16_t uartper;
134 
135  uint32_t rest;
136 
137  GPIO_PBCFGL &= 0xF00F;
138  GPIO_PBCFGL |= 0x0490;
139 
140  uartper = (uint32_t) 24e6 / (2 * ubr);
141  rest = (uint32_t) 24e6 % (2 * ubr);
142 
143  SC1_UARTFRAC = 0;
144  if(rest > (2 * ubr) / 4 && rest < (3 * 2 * ubr) / 4) {
145  SC1_UARTFRAC = 1; /* + 0.5 */
146  } else if(rest >= (3 * 2 * ubr) / 4) {
147  uartper++; /* + 1 */
148  }
149 
150  SC1_UARTPER = uartper;
151  SC1_UARTCFG = SC_UART8BIT;
152  SC1_MODE = SC1_MODE_UART;
153  /*
154  * Receive buffer has data interrupt mode and Transmit buffer free interrupt
155  * mode: Level triggered.
156  */
157  SC1_INTMODE = SC_RXVALLEVEL | SC_TXFREELEVEL;
158  INT_SC1CFG = INT_SCRXVAL; /* Receive buffer has data interrupt enable */
159  transmitting = 0;
160 
161 #if TX_WITH_INTERRUPT
162  ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data));
163 #endif /* TX_WITH_INTERRUPT */
164 
165  INT_SC1FLAG = 0xFFFF;
166  INT_CFGSET = INT_SC1;
167 }
168 /*---------------------------------------------------------------------------*/
169 void
170 halSc1Isr(void)
171 {
172  ENERGEST_ON(ENERGEST_TYPE_IRQ);
173 
174  if(INT_SC1FLAG & INT_SCRXVAL) {
175  uart1_rx_interrupt();
176  INT_SC1FLAG = INT_SCRXVAL;
177  }
178 #if TX_WITH_INTERRUPT
179  else if(INT_SC1FLAG & INT_SCTXFREE) {
180  uart1_tx_interrupt();
181  INT_SC1FLAG = INT_SCTXFREE;
182  }
183 #endif /* TX_WITH_INTERRUPT */
184 
185  ENERGEST_OFF(ENERGEST_TYPE_IRQ);
186 }
187 /*--------------------------------------------------------------------------*/
188 void
189 uart1_rx_interrupt(void)
190 {
191  uint8_t c;
192 
193  c = SC1_DATA;
194  if(uart1_input_handler != NULL) {
195  uart1_input_handler(c);
196  }
197 }
198 /*---------------------------------------------------------------------------*/
199 #if TX_WITH_INTERRUPT
200 void
201 uart1_tx_interrupt(void)
202 {
203  if(ringbuf_elements(&txbuf) == 0) {
204  transmitting = 0;
205  INT_SC1CFG &= ~INT_SCTXFREE;
206  } else {
207  SC1_DATA = ringbuf_get(&txbuf);
208  }
209 }
210 #endif /* TX_WITH_INTERRUPT */
211 /** @} */
void uart1_init(unsigned long ubr)
Initalize the RS232 port.
Definition: uart1.c:143
Header file for the ring buffer library
Structure that holds the state of a ring buffer.
Definition: ringbuf.h:68
#define NULL
The null pointer.
int ringbuf_get(struct ringbuf *r)
Get a byte from the ring buffer.
Definition: ringbuf.c:72
void ringbuf_init(struct ringbuf *r, uint8_t *dataptr, uint8_t size)
Initialize a ring buffer.
Definition: ringbuf.c:43
Header file for the energy estimation mechanism
int ringbuf_elements(struct ringbuf *r)
Get the number of elements currently in the ring buffer.
Definition: ringbuf.c:102
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
int ringbuf_put(struct ringbuf *r, uint8_t c)
Insert a byte into the ring buffer.
Definition: ringbuf.c:52