1 /**
2 * \file
3 *
4 * \brief SAM USART in SPI mode driver functions.
5 *
6 * Copyright (c) 2011-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #include "usart_spi.h"
48 #include "sysclk.h"
49 #if SAMG55
50 #include "flexcom.h"
51 #include "conf_board.h"
52 #endif
53
54 /// @cond 0
55 /**INDENT-OFF**/
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 /**INDENT-ON**/
60 /// @endcond
61
62 /*! \brief Enable the USART system clock in SPI master mode.
63 *
64 * \param p_usart Pointer to Base address of the USART instance.
65 *
66 */
usart_spi_init(Usart * p_usart)67 void usart_spi_init(Usart *p_usart)
68 {
69 #if (!SAMG55)
70
71 uint8_t uc_id;
72
73 #ifdef USART0
74 if (p_usart == USART0) {
75 uc_id = ID_USART0;
76 }
77 #endif
78
79 #ifdef USART1
80 else if(p_usart == USART1) {
81 uc_id = ID_USART1;
82 }
83 #endif
84
85 #ifdef USART2
86 else if(p_usart == USART2) {
87 uc_id = ID_USART2;
88 }
89 #endif
90
91 #ifdef USART3
92 else if(p_usart == USART3) {
93 uc_id = ID_USART3;
94 }
95 #endif
96
97 #endif
98
99 #if SAM4L
100 sysclk_enable_peripheral_clock(p_usart);
101 #elif SAMG55
102 flexcom_enable(BOARD_FLEXCOM_USART);
103 flexcom_set_opmode(BOARD_FLEXCOM_USART, FLEXCOM_USART);
104 #else
105 sysclk_enable_peripheral_clock(uc_id);
106 #endif
107 }
108
109 /**
110 * \brief Set up a USART in SPI master mode device.
111 *
112 * The returned device descriptor structure must be passed to the driver
113 * whenever that device should be used as current slave device.
114 *
115 * \param p_usart Base address of the USART instance.
116 * \param device Pointer to usart device struct that should be initialized.
117 * \param flags USART configuration flags. Common flags for all
118 * implementations are the usart modes, which should be SPI_MODE_0,
119 * SPI_MODE_1, SPI_MODE_2, SPI_MODE_3.
120 * \param baud_rate Baud rate for communication with slave device in Hz.
121 * \param sel_id Board specific select id.
122 */
usart_spi_setup_device(Usart * p_usart,struct usart_spi_device * device,spi_flags_t flags,unsigned long baud_rate,board_spi_select_id_t sel_id)123 void usart_spi_setup_device(Usart *p_usart, struct usart_spi_device *device,
124 spi_flags_t flags, unsigned long baud_rate,
125 board_spi_select_id_t sel_id)
126 {
127 usart_spi_opt_t opt;
128
129 /* avoid Cppcheck Warning */
130 UNUSED(device);
131 UNUSED(sel_id);
132
133 /* Basic usart SPI configuration. */
134 opt.baudrate = baud_rate;
135 opt.char_length = US_MR_CHRL_8_BIT;
136 opt.spi_mode = flags;
137 opt.channel_mode = US_MR_CHMODE_NORMAL;
138
139 /* Initialize the USART module as SPI master. */
140 #if (SAM4L)
141 usart_init_spi_master(p_usart, &opt, sysclk_get_pba_hz());
142 #else
143 usart_init_spi_master(p_usart, &opt, sysclk_get_peripheral_hz());
144 #endif
145
146 usart_enable_rx(p_usart);
147 usart_enable_tx(p_usart);
148 }
149
150 /*! \brief Write one byte to an SPI device using USART in SPI mode.
151 *
152 * \param p_usart Base address of the USART instance.
153 * \param data The data to be sent out.
154 *
155 */
usart_spi_write_single(Usart * p_usart,uint8_t data)156 void usart_spi_write_single(Usart *p_usart, uint8_t data)
157 {
158 usart_putchar(p_usart, data);
159 }
160
161 /**
162 * \brief Send a sequence of bytes to an SPI device using USART in SPI mode.
163 *
164 * Received bytes on the USART in SPI mode are discarded.
165 *
166 * \param p_usart Base address of the USART instance.
167 * \param data Data buffer to write.
168 * \param len Length of data.
169 *
170 * \return 0 if the USART in SPI master mode sends packet successfully.
171 *
172 * \pre USART device must be selected with usart_spi_select_device() first.
173 */
usart_spi_write_packet(Usart * p_usart,const uint8_t * data,size_t len)174 uint32_t usart_spi_write_packet(Usart *p_usart, const uint8_t *data, size_t len)
175 {
176 uint32_t dummy_data;
177 size_t i=0;
178 while(len) {
179 usart_putchar(p_usart, *(data+i));
180 usart_getchar(p_usart, &dummy_data);
181 len--;
182 i++;
183 }
184 return 0;
185 }
186
187 /*! \brief Receive one byte from an SPI device using USART in SPI mode.
188 *
189 * \param p_usart Base address of the USART instance.
190 * \param data Pointer to the data byte where to store the received data.
191 *
192 * \pre USART device must be selected with usart_spi_select_device() first.
193 */
usart_spi_read_single(Usart * p_usart,uint8_t * data)194 void usart_spi_read_single(Usart *p_usart, uint8_t *data)
195 {
196 uint32_t temp_data = 0;
197 /* Dummy write one data to slave in order to read data. */
198 usart_putchar(p_usart, CONFIG_USART_SPI_DUMMY);
199
200 usart_getchar(p_usart, &temp_data);
201 *data = (uint8_t)temp_data;
202 }
203
204 /**
205 * \brief Receive a sequence of bytes from a USART in SPI mode device.
206 *
207 * All bytes sent out on usart bus are sent as value 0.
208 *
209 * \param p_usart Base address of the usart instance.
210 * \param data Data buffer to put read data.
211 * \param len Length of data.
212 *
213 * \return 0 if the USART in SPI master mode reads packet successfully.
214 *
215 * \pre USART device must be selected with usart_spi_select_device() first.
216 */
usart_spi_read_packet(Usart * p_usart,uint8_t * data,size_t len)217 uint32_t usart_spi_read_packet(Usart *p_usart, uint8_t *data, size_t len)
218 {
219 uint32_t val;
220 uint32_t i = 0;
221
222 while(len) {
223 /* Dummy write one data to slave in order to read data. */
224 usart_putchar(p_usart, CONFIG_USART_SPI_DUMMY);
225 usart_getchar(p_usart, &val);
226
227 data[i] = (uint8_t)(val & 0xFF);
228 i++;
229 len--;
230 }
231
232 return 0;
233 }
234
235 /**
236 * \brief Select the given device on the SPI bus.
237 *
238 * \param p_usart Base address of the USART instance.
239 * \param device SPI device.
240 *
241 */
usart_spi_select_device(Usart * p_usart,struct usart_spi_device * device)242 void usart_spi_select_device(Usart *p_usart, struct usart_spi_device *device)
243 {
244 /* avoid Cppcheck Warning */
245 UNUSED(device);
246
247 usart_spi_force_chip_select(p_usart);
248 }
249
250 /**
251 * \brief De-select the given device on the SPI bus.
252 *
253 * \param p_usart Base address of the USART instance.
254 * \param device SPI device.
255 */
usart_spi_deselect_device(Usart * p_usart,struct usart_spi_device * device)256 void usart_spi_deselect_device(Usart *p_usart, struct usart_spi_device *device)
257 {
258 /* avoid Cppcheck Warning */
259 UNUSED(device);
260
261 usart_spi_release_chip_select(p_usart);
262 }
263
264 /*! \brief Check whether there are data in Transmit Holding Register or
265 * Transmit Shift Register in SPI master mode.
266 *
267 * \param p_usart Base address of the USART instance.
268 *
269 * \retval 1 The two registers are empty.
270 * \retval 0 One of the two registers contains data.
271 */
usart_spi_is_tx_empty(Usart * p_usart)272 uint32_t usart_spi_is_tx_empty(Usart *p_usart)
273 {
274 return usart_is_tx_empty(p_usart);
275 }
276
277 /*! \brief Check whether the USART in SPI master mode contains a received character.
278 *
279 * \param p_usart Base address of the USART instance.
280 *
281 * \retval 1 Some data have been received.
282 * \retval 0 No data has been received.
283 */
usart_spi_is_rx_ready(Usart * p_usart)284 uint32_t usart_spi_is_rx_ready(Usart *p_usart)
285 {
286 return usart_is_rx_ready(p_usart);
287 }
288
289 /*! \brief Check if the USART Transmit Holding Register is empty or not in SPI mode.
290 *
291 * \param p_usart Base address of the USART instance.
292 *
293 * \retval 1 There is no data in the Transmit Holding Register.
294 * \retval 0 There are data in the Transmit Holding Register.
295 */
usart_spi_is_tx_ready(Usart * p_usart)296 uint32_t usart_spi_is_tx_ready(Usart *p_usart)
297 {
298 return usart_is_tx_ready(p_usart);
299 }
300
301 /*! \brief Check if both receive buffers are full.
302 *
303 * \param p_usart Base address of the USART instance.
304 *
305 * \retval 1 Receive buffers are full.
306 * \retval 0 Receive buffers are not full.
307 */
usart_spi_is_rx_full(Usart * p_usart)308 uint32_t usart_spi_is_rx_full(Usart *p_usart)
309 {
310 #if (!SAMV71 && !SAMV70 && !SAME70 && !SAMS70)
311 return usart_is_rx_buf_full(p_usart);
312 #endif
313 }
314
315 /*! \brief Enable the USART for the specified USART in SPI mode.
316 *
317 * \param p_usart Base address of the USART instance.
318 */
usart_spi_enable(Usart * p_usart)319 void usart_spi_enable(Usart *p_usart)
320 {
321 usart_enable_tx(p_usart);
322 usart_enable_rx(p_usart);
323 }
324
325 /*! \brief Disable the USART for the specified USART in SPI mode.
326 *
327 * Ensure that nothing is transferred while setting up buffers.
328 *
329 * \param p_usart Base address of the USART instance.
330 *
331 */
usart_spi_disable(Usart * p_usart)332 void usart_spi_disable(Usart *p_usart)
333 {
334 usart_disable_tx(p_usart);
335 usart_disable_rx(p_usart);
336 }
337
338 /// @cond 0
339 /**INDENT-OFF**/
340 #ifdef __cplusplus
341 }
342 #endif
343 /**INDENT-ON**/
344 /// @endcond
345