blob: 73739624ee908e900666a51310907b709d74077a [file] [log] [blame]
Kévin Redon4cd3f7d2019-01-24 17:57:13 +01001
2/**
3 * \file
4 *
5 * \brief SAM Serial Communication Interface
6 *
7 * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
8 *
9 * \asf_license_start
10 *
11 * \page License
12 *
13 * Subject to your compliance with these terms, you may use Microchip
14 * software and any derivatives exclusively with Microchip products.
15 * It is your responsibility to comply with third party license terms applicable
16 * to your use of third party software (including open source software) that
17 * may accompany Microchip software.
18 *
19 * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
20 * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
21 * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
22 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
23 * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
24 * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
25 * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
26 * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
27 * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
28 * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
29 * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
30 *
31 * \asf_license_stop
32 *
33 */
34#include <hpl_dma.h>
35#include <hpl_i2c_m_async.h>
36#include <hpl_i2c_m_sync.h>
37#include <hpl_i2c_s_async.h>
38#include <hpl_sercom_config.h>
39#include <hpl_spi_m_async.h>
40#include <hpl_spi_m_sync.h>
41#include <hpl_spi_s_async.h>
42#include <hpl_spi_s_sync.h>
43#include <hpl_usart_async.h>
44#include <hpl_usart_sync.h>
45#include <utils.h>
46#include <utils_assert.h>
47
48#ifndef CONF_SERCOM_0_USART_ENABLE
49#define CONF_SERCOM_0_USART_ENABLE 0
50#endif
51#ifndef CONF_SERCOM_1_USART_ENABLE
52#define CONF_SERCOM_1_USART_ENABLE 0
53#endif
54#ifndef CONF_SERCOM_2_USART_ENABLE
55#define CONF_SERCOM_2_USART_ENABLE 0
56#endif
57#ifndef CONF_SERCOM_3_USART_ENABLE
58#define CONF_SERCOM_3_USART_ENABLE 0
59#endif
60#ifndef CONF_SERCOM_4_USART_ENABLE
61#define CONF_SERCOM_4_USART_ENABLE 0
62#endif
63#ifndef CONF_SERCOM_5_USART_ENABLE
64#define CONF_SERCOM_5_USART_ENABLE 0
65#endif
66#ifndef CONF_SERCOM_6_USART_ENABLE
67#define CONF_SERCOM_6_USART_ENABLE 0
68#endif
69#ifndef CONF_SERCOM_7_USART_ENABLE
70#define CONF_SERCOM_7_USART_ENABLE 0
71#endif
72
73/** Amount of SERCOM that is used as USART. */
74#define SERCOM_USART_AMOUNT \
75 (CONF_SERCOM_0_USART_ENABLE + CONF_SERCOM_1_USART_ENABLE + CONF_SERCOM_2_USART_ENABLE + CONF_SERCOM_3_USART_ENABLE \
76 + CONF_SERCOM_4_USART_ENABLE + CONF_SERCOM_5_USART_ENABLE + CONF_SERCOM_6_USART_ENABLE \
77 + CONF_SERCOM_7_USART_ENABLE)
78
79/**
80 * \brief Macro is used to fill usart configuration structure based on
81 * its number
82 *
83 * \param[in] n The number of structures
84 */
85#define SERCOM_CONFIGURATION(n) \
86 { \
87 n, \
88 SERCOM_USART_CTRLA_MODE(CONF_SERCOM_##n##_USART_MODE) \
89 | (CONF_SERCOM_##n##_USART_RUNSTDBY << SERCOM_USART_CTRLA_RUNSTDBY_Pos) \
90 | (CONF_SERCOM_##n##_USART_IBON << SERCOM_USART_CTRLA_IBON_Pos) \
91 | (CONF_SERCOM_##n##_USART_TXINV << SERCOM_USART_CTRLA_TXINV_Pos) \
92 | (CONF_SERCOM_##n##_USART_RXINV << SERCOM_USART_CTRLA_RXINV_Pos) \
93 | SERCOM_USART_CTRLA_SAMPR(CONF_SERCOM_##n##_USART_SAMPR) \
94 | SERCOM_USART_CTRLA_TXPO(CONF_SERCOM_##n##_USART_TXPO) \
95 | SERCOM_USART_CTRLA_RXPO(CONF_SERCOM_##n##_USART_RXPO) \
96 | SERCOM_USART_CTRLA_SAMPA(CONF_SERCOM_##n##_USART_SAMPA) \
97 | SERCOM_USART_CTRLA_FORM(CONF_SERCOM_##n##_USART_FORM) \
98 | (CONF_SERCOM_##n##_USART_CMODE << SERCOM_USART_CTRLA_CMODE_Pos) \
99 | (CONF_SERCOM_##n##_USART_CPOL << SERCOM_USART_CTRLA_CPOL_Pos) \
100 | (CONF_SERCOM_##n##_USART_DORD << SERCOM_USART_CTRLA_DORD_Pos), \
101 SERCOM_USART_CTRLB_CHSIZE(CONF_SERCOM_##n##_USART_CHSIZE) \
102 | (CONF_SERCOM_##n##_USART_SBMODE << SERCOM_USART_CTRLB_SBMODE_Pos) \
103 | (CONF_SERCOM_##n##_USART_CLODEN << SERCOM_USART_CTRLB_COLDEN_Pos) \
104 | (CONF_SERCOM_##n##_USART_SFDE << SERCOM_USART_CTRLB_SFDE_Pos) \
105 | (CONF_SERCOM_##n##_USART_ENC << SERCOM_USART_CTRLB_ENC_Pos) \
106 | (CONF_SERCOM_##n##_USART_PMODE << SERCOM_USART_CTRLB_PMODE_Pos) \
107 | (CONF_SERCOM_##n##_USART_TXEN << SERCOM_USART_CTRLB_TXEN_Pos) \
108 | (CONF_SERCOM_##n##_USART_RXEN << SERCOM_USART_CTRLB_RXEN_Pos), \
109 SERCOM_USART_CTRLC_GTIME(CONF_SERCOM_##n##_USART_GTIME) \
110 | (CONF_SERCOM_##n##_USART_DSNACK << SERCOM_USART_CTRLC_DSNACK_Pos) \
111 | (CONF_SERCOM_##n##_USART_INACK << SERCOM_USART_CTRLC_INACK_Pos) \
112 | SERCOM_USART_CTRLC_MAXITER(CONF_SERCOM_##n##_USART_MAXITER), \
113 (uint16_t)(CONF_SERCOM_##n##_USART_BAUD_RATE), CONF_SERCOM_##n##_USART_FRACTIONAL, \
114 CONF_SERCOM_##n##_USART_RECEIVE_PULSE_LENGTH, CONF_SERCOM_##n##_USART_DEBUG_STOP_MODE, \
115 }
116
117/**
118 * \brief SERCOM USART configuration type
119 */
120struct usart_configuration {
121 uint8_t number;
122 hri_sercomusart_ctrla_reg_t ctrl_a;
123 hri_sercomusart_ctrlb_reg_t ctrl_b;
124 hri_sercomusart_ctrlc_reg_t ctrl_c;
125 hri_sercomusart_baud_reg_t baud;
126 uint8_t fractional;
127 hri_sercomusart_rxpl_reg_t rxpl;
128 hri_sercomusart_dbgctrl_reg_t debug_ctrl;
129};
130
131#if SERCOM_USART_AMOUNT < 1
132/** Dummy array to pass compiling. */
133static struct usart_configuration _usarts[1] = {{0}};
134#else
135/**
136 * \brief Array of SERCOM USART configurations
137 */
138static struct usart_configuration _usarts[] = {
139#if CONF_SERCOM_0_USART_ENABLE == 1
140 SERCOM_CONFIGURATION(0),
141#endif
142#if CONF_SERCOM_1_USART_ENABLE == 1
143 SERCOM_CONFIGURATION(1),
144#endif
145#if CONF_SERCOM_2_USART_ENABLE == 1
146 SERCOM_CONFIGURATION(2),
147#endif
148#if CONF_SERCOM_3_USART_ENABLE == 1
149 SERCOM_CONFIGURATION(3),
150#endif
151#if CONF_SERCOM_4_USART_ENABLE == 1
152 SERCOM_CONFIGURATION(4),
153#endif
154#if CONF_SERCOM_5_USART_ENABLE == 1
155 SERCOM_CONFIGURATION(5),
156#endif
157#if CONF_SERCOM_6_USART_ENABLE == 1
158 SERCOM_CONFIGURATION(6),
159#endif
160#if CONF_SERCOM_7_USART_ENABLE == 1
161 SERCOM_CONFIGURATION(7),
162#endif
163};
164#endif
165
Kévin Redon1f8ecef2019-01-31 13:36:12 +0100166static struct _usart_async_device *_sercom0_dev = NULL;
167
168static struct _usart_async_device *_sercom1_dev = NULL;
169
170static struct _usart_async_device *_sercom2_dev = NULL;
171
172static struct _usart_async_device *_sercom3_dev = NULL;
173
174static struct _usart_async_device *_sercom4_dev = NULL;
175
176static struct _usart_async_device *_sercom5_dev = NULL;
177
178static struct _usart_async_device *_sercom6_dev = NULL;
179
Kévin Redonba3a2fa2019-03-07 15:52:27 +0100180static struct _usart_async_device *_sercom7_dev = NULL;
181
Kévin Redon4cd3f7d2019-01-24 17:57:13 +0100182static uint8_t _get_sercom_index(const void *const hw);
183static uint8_t _sercom_get_irq_num(const void *const hw);
184static void _sercom_init_irq_param(const void *const hw, void *dev);
185static uint8_t _sercom_get_hardware_index(const void *const hw);
186
187static int32_t _usart_init(void *const hw);
188static inline void _usart_deinit(void *const hw);
189static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
190 const enum usart_baud_rate_mode mode, const uint8_t fraction);
191static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate);
192static void _usart_set_data_order(void *const hw, const enum usart_data_order order);
193static void _usart_set_mode(void *const hw, const enum usart_mode mode);
194static void _usart_set_parity(void *const hw, const enum usart_parity parity);
195static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits);
196static void _usart_set_character_size(void *const hw, const enum usart_character_size size);
197
198/**
199 * \brief Initialize synchronous SERCOM USART
200 */
201int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw)
202{
203 ASSERT(device);
204
205 device->hw = hw;
206
207 return _usart_init(hw);
208}
209
210/**
211 * \brief Initialize asynchronous SERCOM USART
212 */
213int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw)
214{
215 int32_t init_status;
216
217 ASSERT(device);
218
219 init_status = _usart_init(hw);
220 if (init_status) {
221 return init_status;
222 }
223 device->hw = hw;
224 _sercom_init_irq_param(hw, (void *)device);
225 uint8_t irq = _sercom_get_irq_num(hw);
226 for (uint32_t i = 0; i < 4; i++) {
227 NVIC_DisableIRQ((IRQn_Type)irq);
228 NVIC_ClearPendingIRQ((IRQn_Type)irq);
229 NVIC_EnableIRQ((IRQn_Type)irq);
230 irq++;
231 }
232 return ERR_NONE;
233}
234
235/**
236 * \brief De-initialize SERCOM USART
237 */
238void _usart_sync_deinit(struct _usart_sync_device *const device)
239{
240 _usart_deinit(device->hw);
241}
242
243/**
244 * \brief De-initialize SERCOM USART
245 */
246void _usart_async_deinit(struct _usart_async_device *const device)
247{
248 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
249 _usart_deinit(device->hw);
250}
251
252/**
253 * \brief Calculate baud rate register value
254 */
255uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
256 const enum usart_baud_rate_mode mode, const uint8_t fraction)
257{
258 return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
259}
260
261/**
262 * \brief Calculate baud rate register value
263 */
264uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
265 const enum usart_baud_rate_mode mode, const uint8_t fraction)
266{
267 return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction);
268}
269
270/**
271 * \brief Enable SERCOM module
272 */
273void _usart_sync_enable(struct _usart_sync_device *const device)
274{
275 hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
276}
277
278/**
279 * \brief Enable SERCOM module
280 */
281void _usart_async_enable(struct _usart_async_device *const device)
282{
283 hri_sercomusart_set_CTRLA_ENABLE_bit(device->hw);
284}
285
286/**
287 * \brief Disable SERCOM module
288 */
289void _usart_sync_disable(struct _usart_sync_device *const device)
290{
291 hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
292}
293
294/**
295 * \brief Disable SERCOM module
296 */
297void _usart_async_disable(struct _usart_async_device *const device)
298{
299 hri_sercomusart_clear_CTRLA_ENABLE_bit(device->hw);
300}
301
302/**
303 * \brief Set baud rate
304 */
305void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate)
306{
307 _usart_set_baud_rate(device->hw, baud_rate);
308}
309
310/**
311 * \brief Set baud rate
312 */
313void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate)
314{
315 _usart_set_baud_rate(device->hw, baud_rate);
316}
317
318/**
319 * \brief Set data order
320 */
321void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order)
322{
323 _usart_set_data_order(device->hw, order);
324}
325
326/**
327 * \brief Set data order
328 */
329void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order)
330{
331 _usart_set_data_order(device->hw, order);
332}
333
334/**
335 * \brief Set mode
336 */
337void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode)
338{
339 _usart_set_mode(device->hw, mode);
340}
341
342/**
343 * \brief Set mode
344 */
345void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode)
346{
347 _usart_set_mode(device->hw, mode);
348}
349
350/**
351 * \brief Set parity
352 */
353void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity)
354{
355 _usart_set_parity(device->hw, parity);
356}
357
358/**
359 * \brief Set parity
360 */
361void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity)
362{
363 _usart_set_parity(device->hw, parity);
364}
365
366/**
367 * \brief Set stop bits mode
368 */
369void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits)
370{
371 _usart_set_stop_bits(device->hw, stop_bits);
372}
373
374/**
375 * \brief Set stop bits mode
376 */
377void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits)
378{
379 _usart_set_stop_bits(device->hw, stop_bits);
380}
381
382/**
383 * \brief Set character size
384 */
385void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size)
386{
387 _usart_set_character_size(device->hw, size);
388}
389
390/**
391 * \brief Set character size
392 */
393void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size)
394{
395 _usart_set_character_size(device->hw, size);
396}
397
398/**
399 * \brief Retrieve SERCOM usart status
400 */
401uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device)
402{
403 return hri_sercomusart_read_STATUS_reg(device->hw);
404}
405
406/**
407 * \brief Retrieve SERCOM usart status
408 */
409uint32_t _usart_async_get_status(const struct _usart_async_device *const device)
410{
411 return hri_sercomusart_read_STATUS_reg(device->hw);
412}
413
414/**
415 * \brief Write a byte to the given SERCOM USART instance
416 */
417void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data)
418{
419 hri_sercomusart_write_DATA_reg(device->hw, data);
420}
421
422/**
423 * \brief Write a byte to the given SERCOM USART instance
424 */
425void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data)
426{
427 hri_sercomusart_write_DATA_reg(device->hw, data);
428}
429
430/**
431 * \brief Read a byte from the given SERCOM USART instance
432 */
433uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device)
434{
435 return hri_sercomusart_read_DATA_reg(device->hw);
436}
437
438/**
439 * \brief Check if USART is ready to send next byte
440 */
441bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device)
442{
443 return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
444}
445
446/**
447 * \brief Check if USART transmission complete
448 */
449bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device)
450{
451 return hri_sercomusart_get_interrupt_TXC_bit(device->hw);
452}
453
454/**
455 * \brief Check if USART is ready to send next byte
456 */
457bool _usart_async_is_byte_sent(const struct _usart_async_device *const device)
458{
459 return hri_sercomusart_get_interrupt_DRE_bit(device->hw);
460}
461
462/**
463 * \brief Check if there is data received by USART
464 */
465bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device)
466{
467 return hri_sercomusart_get_interrupt_RXC_bit(device->hw);
468}
469
470/**
471 * \brief Set the state of flow control pins
472 */
473void _usart_sync_set_flow_control_state(struct _usart_sync_device *const device,
474 const union usart_flow_control_state state)
475{
476 (void)device;
477 (void)state;
478}
479
480/**
481 * \brief Set the state of flow control pins
482 */
483void _usart_async_set_flow_control_state(struct _usart_async_device *const device,
484 const union usart_flow_control_state state)
485{
486 (void)device;
487 (void)state;
488}
489
490/**
491 * \brief Retrieve the state of flow control pins
492 */
493union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device)
494{
495 (void)device;
496 union usart_flow_control_state state;
497
498 state.value = 0;
499 state.bit.unavailable = 1;
500 return state;
501}
502
503/**
504 * \brief Retrieve the state of flow control pins
505 */
506union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device)
507{
508 (void)device;
509 union usart_flow_control_state state;
510
511 state.value = 0;
512 state.bit.unavailable = 1;
513 return state;
514}
515
516/**
517 * \brief Enable data register empty interrupt
518 */
519void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device)
520{
521 hri_sercomusart_set_INTEN_DRE_bit(device->hw);
522}
523
524/**
525 * \brief Enable transmission complete interrupt
526 */
527void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device)
528{
529 hri_sercomusart_set_INTEN_TXC_bit(device->hw);
530}
531
532/**
533 * \brief Retrieve ordinal number of the given sercom hardware instance
534 */
535static uint8_t _sercom_get_hardware_index(const void *const hw)
536{
537 Sercom *const sercom_modules[] = SERCOM_INSTS;
538 /* Find index for SERCOM instance. */
539 for (uint32_t i = 0; i < SERCOM_INST_NUM; i++) {
540 if ((uint32_t)hw == (uint32_t)sercom_modules[i]) {
541 return i;
542 }
543 }
544 return 0;
545}
546
547/**
548 * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
549 */
550uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device)
551{
552 return _sercom_get_hardware_index(device->hw);
553}
554
555/**
556 * \brief Retrieve ordinal number of the given SERCOM USART hardware instance
557 */
558uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device)
559{
560 return _sercom_get_hardware_index(device->hw);
561}
562
563/**
564 * \brief Enable/disable USART interrupt
565 */
566void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type,
567 const bool state)
568{
569 ASSERT(device);
570
571 if (USART_ASYNC_BYTE_SENT == type || USART_ASYNC_TX_DONE == type) {
572 hri_sercomusart_write_INTEN_DRE_bit(device->hw, state);
573 hri_sercomusart_write_INTEN_TXC_bit(device->hw, state);
574 } else if (USART_ASYNC_RX_DONE == type) {
575 hri_sercomusart_write_INTEN_RXC_bit(device->hw, state);
576 } else if (USART_ASYNC_ERROR == type) {
577 hri_sercomusart_write_INTEN_ERROR_bit(device->hw, state);
578 }
579}
Eric Wild9a2279c2019-11-27 18:30:18 +0100580#include <hal_gpio.h>
Kévin Redon4cd3f7d2019-01-24 17:57:13 +0100581/**
Kévin Redonccbed0b2019-01-24 18:30:26 +0100582 * \internal Sercom interrupt handler
583 *
584 * \param[in] p The pointer to interrupt parameter
585 */
586static void _sercom_usart_interrupt_handler(struct _usart_async_device *device)
587{
588 void *hw = device->hw;
589
590 if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) {
591 hri_sercomusart_clear_INTEN_DRE_bit(hw);
Eric Wild474cf592019-11-22 18:39:30 +0100592 hri_sercomusart_read_DATA_reg(hw);
593 hri_sercomusart_clear_INTFLAG_RXC_bit(hw);
Kévin Redonccbed0b2019-01-24 18:30:26 +0100594 device->usart_cb.tx_byte_sent(device);
595 } else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) {
Eric Wild9a2279c2019-11-27 18:30:18 +0100596#if 0
597// tx byte last edge <-> txc irq delay
598 gpio_set_pin_level(PIN_PB12, true);
599 delay_us(1);
600 gpio_set_pin_level(PIN_PB12, false);
601#endif
Kévin Redonccbed0b2019-01-24 18:30:26 +0100602 hri_sercomusart_clear_INTEN_TXC_bit(hw);
Eric Wild474cf592019-11-22 18:39:30 +0100603 hri_sercomusart_read_DATA_reg(hw);
604 hri_sercomusart_clear_INTFLAG_RXC_bit(hw);
Kévin Redonccbed0b2019-01-24 18:30:26 +0100605 device->usart_cb.tx_done_cb(device);
606 } else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) {
607 if (hri_sercomusart_read_STATUS_reg(hw)
608 & (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF
609 | SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) {
610 hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK);
611 return;
612 }
Eric Wild9a2279c2019-11-27 18:30:18 +0100613#if 0
614// rx byte last edge <-> rxc irq delay
615 gpio_set_pin_level(PIN_PB12, true);
616 delay_us(1);
617 gpio_set_pin_level(PIN_PB12, false);
618#endif
Kévin Redonccbed0b2019-01-24 18:30:26 +0100619
620 device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw));
Eric Wild9a2279c2019-11-27 18:30:18 +0100621#if 0
622// rx byte last edge <-> rxc irq end delay
623 gpio_set_pin_level(PIN_PB12, true);
624 delay_us(1);
625 gpio_set_pin_level(PIN_PB12, false);
626#endif
Kévin Redonccbed0b2019-01-24 18:30:26 +0100627 } else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) {
628 uint32_t status;
629
630 hri_sercomusart_clear_interrupt_ERROR_bit(hw);
631 device->usart_cb.error_cb(device);
632 status = hri_sercomusart_read_STATUS_reg(hw);
633 hri_sercomusart_clear_STATUS_reg(hw, status);
634 }
635}
636
637/**
Kévin Redon4cd3f7d2019-01-24 17:57:13 +0100638 * \internal Retrieve ordinal number of the given sercom hardware instance
639 *
640 * \param[in] hw The pointer to hardware instance
641
642 * \return The ordinal number of the given sercom hardware instance
643 */
644static uint8_t _get_sercom_index(const void *const hw)
645{
646 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
647 uint8_t i;
648
649 for (i = 0; i < ARRAY_SIZE(_usarts); i++) {
650 if (_usarts[i].number == sercom_offset) {
651 return i;
652 }
653 }
654
655 ASSERT(false);
656 return 0;
657}
658
659/**
660 * \brief Init irq param with the given sercom hardware instance
661 */
662static void _sercom_init_irq_param(const void *const hw, void *dev)
663{
Kévin Redonccbed0b2019-01-24 18:30:26 +0100664
Kévin Redon1f8ecef2019-01-31 13:36:12 +0100665 if (hw == SERCOM0) {
666 _sercom0_dev = (struct _usart_async_device *)dev;
667 }
668
669 if (hw == SERCOM1) {
670 _sercom1_dev = (struct _usart_async_device *)dev;
671 }
672
673 if (hw == SERCOM2) {
674 _sercom2_dev = (struct _usart_async_device *)dev;
675 }
676
677 if (hw == SERCOM3) {
678 _sercom3_dev = (struct _usart_async_device *)dev;
679 }
680
681 if (hw == SERCOM4) {
682 _sercom4_dev = (struct _usart_async_device *)dev;
683 }
684
685 if (hw == SERCOM5) {
686 _sercom5_dev = (struct _usart_async_device *)dev;
687 }
688
689 if (hw == SERCOM6) {
690 _sercom6_dev = (struct _usart_async_device *)dev;
691 }
Kévin Redonba3a2fa2019-03-07 15:52:27 +0100692
693 if (hw == SERCOM7) {
694 _sercom7_dev = (struct _usart_async_device *)dev;
695 }
Kévin Redon4cd3f7d2019-01-24 17:57:13 +0100696}
697
698/**
699 * \internal Initialize SERCOM USART
700 *
701 * \param[in] hw The pointer to hardware instance
702 *
703 * \return The status of initialization
704 */
705static int32_t _usart_init(void *const hw)
706{
707 uint8_t i = _get_sercom_index(hw);
708
709 if (!hri_sercomusart_is_syncing(hw, SERCOM_USART_SYNCBUSY_SWRST)) {
710 uint32_t mode = _usarts[i].ctrl_a & SERCOM_USART_CTRLA_MODE_Msk;
711 if (hri_sercomusart_get_CTRLA_reg(hw, SERCOM_USART_CTRLA_ENABLE)) {
712 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
713 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
714 }
715 hri_sercomusart_write_CTRLA_reg(hw, SERCOM_USART_CTRLA_SWRST | mode);
716 }
717 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_SWRST);
718
719 hri_sercomusart_write_CTRLA_reg(hw, _usarts[i].ctrl_a);
720 hri_sercomusart_write_CTRLB_reg(hw, _usarts[i].ctrl_b);
721 hri_sercomusart_write_CTRLC_reg(hw, _usarts[i].ctrl_c);
722 if ((_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x1)) || (_usarts[i].ctrl_a & SERCOM_USART_CTRLA_SAMPR(0x3))) {
723 ((Sercom *)hw)->USART.BAUD.FRAC.BAUD = _usarts[i].baud;
724 ((Sercom *)hw)->USART.BAUD.FRAC.FP = _usarts[i].fractional;
725 } else {
726 hri_sercomusart_write_BAUD_reg(hw, _usarts[i].baud);
727 }
728
729 hri_sercomusart_write_RXPL_reg(hw, _usarts[i].rxpl);
730 hri_sercomusart_write_DBGCTRL_reg(hw, _usarts[i].debug_ctrl);
731
732 return ERR_NONE;
733}
734
735/**
736 * \internal De-initialize SERCOM USART
737 *
738 * \param[in] hw The pointer to hardware instance
739 */
740static inline void _usart_deinit(void *const hw)
741{
742 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
743 hri_sercomusart_set_CTRLA_SWRST_bit(hw);
744}
745
746/**
747 * \internal Calculate baud rate register value
748 *
749 * \param[in] baud Required baud rate
750 * \param[in] clock_rate SERCOM clock frequency
751 * \param[in] samples The number of samples
752 * \param[in] mode USART mode
753 * \param[in] fraction A fraction value
754 *
755 * \return Calculated baud rate register value
756 */
757static uint16_t _usart_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples,
758 const enum usart_baud_rate_mode mode, const uint8_t fraction)
759{
760 if (USART_BAUDRATE_ASYNCH_ARITHMETIC == mode) {
761 return 65536 - ((uint64_t)65536 * samples * baud) / clock_rate;
762 }
763
764 if (USART_BAUDRATE_ASYNCH_FRACTIONAL == mode) {
765 return clock_rate / baud / samples + SERCOM_USART_BAUD_FRACFP_FP(fraction);
766 }
767
768 if (USART_BAUDRATE_SYNCH == mode) {
769 return clock_rate / baud / 2 - 1;
770 }
771
772 return 0;
773}
774
775/**
776 * \internal Set baud rate
777 *
778 * \param[in] device The pointer to USART device instance
779 * \param[in] baud_rate A baud rate to set
780 */
781static void _usart_set_baud_rate(void *const hw, const uint32_t baud_rate)
782{
783 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
784
785 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
786
787 CRITICAL_SECTION_ENTER()
788 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
789 hri_sercomusart_write_BAUD_reg(hw, baud_rate);
790 CRITICAL_SECTION_LEAVE()
791
792 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
793}
794
795/**
796 * \internal Set data order
797 *
798 * \param[in] device The pointer to USART device instance
799 * \param[in] order A data order to set
800 */
801static void _usart_set_data_order(void *const hw, const enum usart_data_order order)
802{
803 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
804
805 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
806
807 CRITICAL_SECTION_ENTER()
808 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
809 hri_sercomusart_write_CTRLA_DORD_bit(hw, order);
810 CRITICAL_SECTION_LEAVE()
811
812 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
813}
814
815/**
816 * \internal Set mode
817 *
818 * \param[in] device The pointer to USART device instance
819 * \param[in] mode A mode to set
820 */
821static void _usart_set_mode(void *const hw, const enum usart_mode mode)
822{
823 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
824
825 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
826
827 CRITICAL_SECTION_ENTER()
828 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
829 hri_sercomusart_write_CTRLA_CMODE_bit(hw, mode);
830 CRITICAL_SECTION_LEAVE()
831
832 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
833}
834
835/**
836 * \internal Set parity
837 *
838 * \param[in] device The pointer to USART device instance
839 * \param[in] parity A parity to set
840 */
841static void _usart_set_parity(void *const hw, const enum usart_parity parity)
842{
843 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
844
845 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
846
847 CRITICAL_SECTION_ENTER()
848 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
849
850 if (USART_PARITY_NONE != parity) {
851 hri_sercomusart_set_CTRLA_FORM_bf(hw, 1);
852 } else {
853 hri_sercomusart_clear_CTRLA_FORM_bf(hw, 1);
854 }
855
856 hri_sercomusart_write_CTRLB_PMODE_bit(hw, parity);
857 CRITICAL_SECTION_LEAVE()
858
859 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
860}
861
862/**
863 * \internal Set stop bits mode
864 *
865 * \param[in] device The pointer to USART device instance
866 * \param[in] stop_bits A stop bits mode to set
867 */
868static void _usart_set_stop_bits(void *const hw, const enum usart_stop_bits stop_bits)
869{
870 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
871
872 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
873
874 CRITICAL_SECTION_ENTER()
875 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
876 hri_sercomusart_write_CTRLB_SBMODE_bit(hw, stop_bits);
877 CRITICAL_SECTION_LEAVE()
878
879 hri_sercomusart_write_CTRLA_ENABLE_bit(hw, enabled);
880}
881
882/**
883 * \internal Set character size
884 *
885 * \param[in] device The pointer to USART device instance
886 * \param[in] size A character size to set
887 */
888static void _usart_set_character_size(void *const hw, const enum usart_character_size size)
889{
890 bool enabled = hri_sercomusart_get_CTRLA_ENABLE_bit(hw);
891
892 hri_sercomusart_clear_CTRLA_ENABLE_bit(hw);
893
894 CRITICAL_SECTION_ENTER()
895 hri_sercomusart_wait_for_sync(hw, SERCOM_USART_SYNCBUSY_ENABLE);
896 hri_sercomusart_write_CTRLB_CHSIZE_bf(hw, size);
897 CRITICAL_SECTION_LEAVE()
898
899 if (enabled) {
900 hri_sercomusart_set_CTRLA_ENABLE_bit(hw);
901 }
902}
903
904 /* Sercom I2C implementation */
905
906#ifndef CONF_SERCOM_0_I2CM_ENABLE
907#define CONF_SERCOM_0_I2CM_ENABLE 0
908#endif
909#ifndef CONF_SERCOM_1_I2CM_ENABLE
910#define CONF_SERCOM_1_I2CM_ENABLE 0
911#endif
912#ifndef CONF_SERCOM_2_I2CM_ENABLE
913#define CONF_SERCOM_2_I2CM_ENABLE 0
914#endif
915#ifndef CONF_SERCOM_3_I2CM_ENABLE
916#define CONF_SERCOM_3_I2CM_ENABLE 0
917#endif
918#ifndef CONF_SERCOM_4_I2CM_ENABLE
919#define CONF_SERCOM_4_I2CM_ENABLE 0
920#endif
921#ifndef CONF_SERCOM_5_I2CM_ENABLE
922#define CONF_SERCOM_5_I2CM_ENABLE 0
923#endif
924#ifndef CONF_SERCOM_6_I2CM_ENABLE
925#define CONF_SERCOM_6_I2CM_ENABLE 0
926#endif
927#ifndef CONF_SERCOM_7_I2CM_ENABLE
928#define CONF_SERCOM_7_I2CM_ENABLE 0
929#endif
930
931/** Amount of SERCOM that is used as I2C Master. */
932#define SERCOM_I2CM_AMOUNT \
933 (CONF_SERCOM_0_I2CM_ENABLE + CONF_SERCOM_1_I2CM_ENABLE + CONF_SERCOM_2_I2CM_ENABLE + CONF_SERCOM_3_I2CM_ENABLE \
934 + CONF_SERCOM_4_I2CM_ENABLE + CONF_SERCOM_5_I2CM_ENABLE + CONF_SERCOM_6_I2CM_ENABLE + CONF_SERCOM_7_I2CM_ENABLE)
935
936/**
937 * \brief Macro is used to fill i2cm configuration structure based on
938 * its number
939 *
940 * \param[in] n The number of structures
941 */
942#define I2CM_CONFIGURATION(n) \
943 { \
944 (n), \
945 (SERCOM_I2CM_CTRLA_MODE_I2C_MASTER) | (CONF_SERCOM_##n##_I2CM_RUNSTDBY << SERCOM_I2CM_CTRLA_RUNSTDBY_Pos) \
946 | (CONF_SERCOM_##n##_I2CM_SPEED << SERCOM_I2CM_CTRLA_SPEED_Pos) \
947 | (CONF_SERCOM_##n##_I2CM_MEXTTOEN << SERCOM_I2CM_CTRLA_MEXTTOEN_Pos) \
948 | (CONF_SERCOM_##n##_I2CM_SEXTTOEN << SERCOM_I2CM_CTRLA_SEXTTOEN_Pos) \
949 | (CONF_SERCOM_##n##_I2CM_INACTOUT << SERCOM_I2CM_CTRLA_INACTOUT_Pos) \
950 | (CONF_SERCOM_##n##_I2CM_LOWTOUT << SERCOM_I2CM_CTRLA_LOWTOUTEN_Pos) \
951 | (CONF_SERCOM_##n##_I2CM_SDAHOLD << SERCOM_I2CM_CTRLA_SDAHOLD_Pos), \
952 SERCOM_I2CM_CTRLB_SMEN, (uint32_t)(CONF_SERCOM_##n##_I2CM_BAUD_RATE), \
953 CONF_SERCOM_##n##_I2CM_DEBUG_STOP_MODE, CONF_SERCOM_##n##_I2CM_TRISE, CONF_GCLK_SERCOM##n##_CORE_FREQUENCY \
954 }
955
956#define ERROR_FLAG (1 << 7)
957#define SB_FLAG (1 << 1)
958#define MB_FLAG (1 << 0)
959
960#define CMD_STOP 0x3
961#define I2C_IDLE 0x1
962#define I2C_SM 0x0
963#define I2C_FM 0x1
964#define I2C_HS 0x2
965#define TEN_ADDR_FRAME 0x78
966#define TEN_ADDR_MASK 0x3ff
967#define SEVEN_ADDR_MASK 0x7f
968
969/**
970 * \brief SERCOM I2CM configuration type
971 */
972struct i2cm_configuration {
973 uint8_t number;
974 hri_sercomi2cm_ctrla_reg_t ctrl_a;
975 hri_sercomi2cm_ctrlb_reg_t ctrl_b;
976 hri_sercomi2cm_baud_reg_t baud;
977 hri_sercomi2cm_dbgctrl_reg_t dbgctrl;
978 uint16_t trise;
979 uint32_t clk; /* SERCOM peripheral clock frequency */
980};
981
982static inline void _i2c_m_enable_implementation(void *hw);
983static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw);
984
985#if SERCOM_I2CM_AMOUNT < 1
986/** Dummy array to pass compiling. */
987static struct i2cm_configuration _i2cms[1] = {{0}};
988#else
989/**
990 * \brief Array of SERCOM I2CM configurations
991 */
992static struct i2cm_configuration _i2cms[] = {
993#if CONF_SERCOM_0_I2CM_ENABLE == 1
994 I2CM_CONFIGURATION(0),
995#endif
996#if CONF_SERCOM_1_I2CM_ENABLE == 1
997 I2CM_CONFIGURATION(1),
998#endif
999#if CONF_SERCOM_2_I2CM_ENABLE == 1
1000 I2CM_CONFIGURATION(2),
1001#endif
1002#if CONF_SERCOM_3_I2CM_ENABLE == 1
1003 I2CM_CONFIGURATION(3),
1004#endif
1005#if CONF_SERCOM_4_I2CM_ENABLE == 1
1006 I2CM_CONFIGURATION(4),
1007#endif
1008#if CONF_SERCOM_5_I2CM_ENABLE == 1
1009 I2CM_CONFIGURATION(5),
1010#endif
1011#if CONF_SERCOM_6_I2CM_ENABLE == 1
1012 I2CM_CONFIGURATION(6),
1013#endif
1014#if CONF_SERCOM_7_I2CM_ENABLE == 1
1015 I2CM_CONFIGURATION(7),
1016#endif
1017};
1018#endif
1019
1020/**
1021 * \internal Retrieve ordinal number of the given sercom hardware instance
1022 *
1023 * \param[in] hw The pointer to hardware instance
1024
1025 * \return The ordinal number of the given sercom hardware instance
1026 */
1027static int8_t _get_i2cm_index(const void *const hw)
1028{
1029 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
1030 uint8_t i;
1031
1032 for (i = 0; i < ARRAY_SIZE(_i2cms); i++) {
1033 if (_i2cms[i].number == sercom_offset) {
1034 return i;
1035 }
1036 }
1037
1038 ASSERT(false);
1039 return -1;
1040}
1041
1042static inline void _sercom_i2c_send_stop(void *const hw)
1043{
1044 hri_sercomi2cm_set_CTRLB_CMD_bf(hw, CMD_STOP);
1045}
1046
1047/**
1048 * \brief SERCOM I2CM analyze hardware status and transfer next byte
1049 */
1050static inline int32_t _sercom_i2c_sync_analyse_flags(void *const hw, uint32_t flags, struct _i2c_m_msg *const msg)
1051{
1052 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
1053 uint16_t status = hri_sercomi2cm_read_STATUS_reg(hw);
1054
1055 if (flags & MB_FLAG) {
1056 /* tx error */
1057 if (status & SERCOM_I2CM_STATUS_ARBLOST) {
1058 hri_sercomi2cm_clear_interrupt_MB_bit(hw);
1059 msg->flags |= I2C_M_FAIL;
1060 msg->flags &= ~I2C_M_BUSY;
1061
1062 if (status & SERCOM_I2CM_STATUS_BUSERR) {
1063 return I2C_ERR_BUS;
1064 }
1065
1066 return I2C_ERR_BAD_ADDRESS;
1067 } else {
1068 if (status & SERCOM_I2CM_STATUS_RXNACK) {
1069
1070 /* Slave rejects to receive more data */
1071 if (msg->len > 0) {
1072 msg->flags |= I2C_M_FAIL;
1073 }
1074
1075 if (msg->flags & I2C_M_STOP) {
1076 _sercom_i2c_send_stop(hw);
1077 }
1078
1079 msg->flags &= ~I2C_M_BUSY;
1080
1081 return I2C_NACK;
1082 }
1083
1084 if (msg->flags & I2C_M_TEN) {
1085 hri_sercomi2cm_write_ADDR_reg(hw,
1086 ((((msg->addr & TEN_ADDR_MASK) >> 8) | TEN_ADDR_FRAME) << 1) | I2C_M_RD
1087 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1088 msg->flags &= ~I2C_M_TEN;
1089
1090 return I2C_OK;
1091 }
1092
1093 if (msg->len == 0) {
1094 if (msg->flags & I2C_M_STOP) {
1095 _sercom_i2c_send_stop(hw);
1096 }
1097
1098 msg->flags &= ~I2C_M_BUSY;
1099 } else {
1100 hri_sercomi2cm_write_DATA_reg(hw, *msg->buffer);
1101 msg->buffer++;
1102 msg->len--;
1103 }
1104
1105 return I2C_OK;
1106 }
1107 } else if (flags & SB_FLAG) {
1108 if ((msg->len) && !(status & SERCOM_I2CM_STATUS_RXNACK)) {
1109 msg->len--;
1110
1111 /* last byte, send nack */
1112 if ((msg->len == 0 && !sclsm) || (msg->len == 1 && sclsm)) {
1113 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1114 }
1115
1116 if (msg->len == 0) {
1117 if (msg->flags & I2C_M_STOP) {
1118 hri_sercomi2cm_clear_CTRLB_SMEN_bit(hw);
1119 _sercom_i2c_send_stop(hw);
1120 }
1121
1122 msg->flags &= ~I2C_M_BUSY;
1123 }
1124
1125 /* Accessing DATA.DATA auto-triggers I2C bus operations.
1126 * The operation performed depends on the state of
1127 * CTRLB.ACKACT, CTRLB.SMEN
1128 **/
1129 *msg->buffer++ = hri_sercomi2cm_read_DATA_reg(hw);
1130 } else {
1131 hri_sercomi2cm_clear_interrupt_SB_bit(hw);
1132 return I2C_NACK;
1133 }
1134
1135 hri_sercomi2cm_clear_interrupt_SB_bit(hw);
1136 }
1137
1138 return I2C_OK;
1139}
1140
1141/**
1142 * \brief Enable the i2c master module
1143 *
1144 * \param[in] i2c_dev The pointer to i2c device
1145 */
1146int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev)
1147{
1148 ASSERT(i2c_dev);
1149
1150 _i2c_m_enable_implementation(i2c_dev->hw);
1151
1152 return ERR_NONE;
1153}
1154
1155/**
1156 * \brief Disable the i2c master module
1157 *
1158 * \param[in] i2c_dev The pointer to i2c device
1159 */
1160int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev)
1161{
1162 void *hw = i2c_dev->hw;
1163
1164 ASSERT(i2c_dev);
1165 ASSERT(i2c_dev->hw);
1166
1167 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(hw));
1168 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1169
1170 return ERR_NONE;
1171}
1172
1173/**
1174 * \brief Set baudrate of master
1175 *
1176 * \param[in] i2c_dev The pointer to i2c device
1177 * \param[in] clkrate The clock rate of i2c master, in KHz
1178 * \param[in] baudrate The baud rate desired for i2c master, in KHz
1179 */
1180int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
1181{
1182 uint32_t tmp;
1183 void * hw = i2c_dev->hw;
1184
1185 if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
1186 return ERR_DENIED;
1187 }
1188
1189 tmp = _get_i2cm_index(hw);
1190 clkrate = _i2cms[tmp].clk / 1000;
1191
1192 if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
1193 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1194 / (2 * baudrate));
1195 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1196 } else if (i2c_dev->service.mode == I2C_FASTMODE) {
1197 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1198 / (2 * baudrate));
1199 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1200 } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
1201 tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
1202 hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
1203 } else {
1204 /* error baudrate */
1205 return ERR_INVALID_ARG;
1206 }
1207
1208 return ERR_NONE;
1209}
1210
1211/**
1212 * \brief Retrieve IRQ number for the given hardware instance
1213 */
1214static uint8_t _sercom_get_irq_num(const void *const hw)
1215{
1216 return SERCOM0_0_IRQn + (_sercom_get_hardware_index(hw) << 2);
1217}
1218
1219/**
1220 * \brief Initialize sercom i2c module to use in async mode
1221 *
1222 * \param[in] i2c_dev The pointer to i2c device
1223 */
1224int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw)
1225{
1226 int32_t init_status;
1227
1228 ASSERT(i2c_dev);
1229
1230 i2c_dev->hw = hw;
1231
1232 init_status = _i2c_m_sync_init_impl(&i2c_dev->service, hw);
1233 if (init_status) {
1234 return init_status;
1235 }
1236
1237 _sercom_init_irq_param(hw, (void *)i2c_dev);
1238 uint8_t irq = _sercom_get_irq_num(hw);
1239 for (uint32_t i = 0; i < 4; i++) {
1240 NVIC_DisableIRQ((IRQn_Type)irq);
1241 NVIC_ClearPendingIRQ((IRQn_Type)irq);
1242 NVIC_EnableIRQ((IRQn_Type)irq);
1243 irq++;
1244 }
1245 return ERR_NONE;
1246}
1247
1248/**
1249 * \brief Deinitialize sercom i2c module
1250 *
1251 * \param[in] i2c_dev The pointer to i2c device
1252 */
1253int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev)
1254{
1255 ASSERT(i2c_dev);
1256
1257 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
1258 hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
1259
1260 return ERR_NONE;
1261}
1262
1263/**
1264 * \brief Transfer the slave address to bus, which will start the transfer
1265 *
1266 * \param[in] i2c_dev The pointer to i2c device
1267 */
1268static int32_t _sercom_i2c_send_address(struct _i2c_m_async_device *const i2c_dev)
1269{
1270 void * hw = i2c_dev->hw;
1271 struct _i2c_m_msg *msg = &i2c_dev->service.msg;
1272 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
1273
1274 ASSERT(i2c_dev);
1275
1276 if (msg->len == 1 && sclsm) {
1277 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1278 } else {
1279 hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
1280 }
1281
1282 /* ten bit address */
1283 if (msg->addr & I2C_M_TEN) {
1284 if (msg->flags & I2C_M_RD) {
1285 msg->flags |= I2C_M_TEN;
1286 }
1287
1288 hri_sercomi2cm_write_ADDR_reg(hw,
1289 ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
1290 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1291 } else {
1292 hri_sercomi2cm_write_ADDR_reg(hw,
1293 ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
1294 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1295 }
1296
1297 return ERR_NONE;
1298}
1299
1300/**
1301 * \brief Transfer data specified by msg
1302 *
1303 * \param[in] i2c_dev The pointer to i2c device
1304 * \param[in] msg The pointer to i2c message
1305 *
1306 * \return Transfer status.
1307 * \retval 0 Transfer success
1308 * \retval <0 Transfer fail, return the error code
1309 */
1310int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *i2c_dev, struct _i2c_m_msg *msg)
1311{
1312 int ret;
1313
1314 ASSERT(i2c_dev);
1315 ASSERT(i2c_dev->hw);
1316 ASSERT(msg);
1317
1318 if (msg->len == 0) {
1319 return ERR_NONE;
1320 }
1321
1322 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1323 return ERR_BUSY;
1324 }
1325
1326 msg->flags |= I2C_M_BUSY;
1327 i2c_dev->service.msg = *msg;
1328 hri_sercomi2cm_set_CTRLB_SMEN_bit(i2c_dev->hw);
1329
1330 ret = _sercom_i2c_send_address(i2c_dev);
1331
1332 if (ret) {
1333 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1334
1335 return ret;
1336 }
1337
1338 return ERR_NONE;
1339}
1340
1341/**
1342 * \brief Set callback to be called in interrupt handler
1343 *
1344 * \param[in] i2c_dev The pointer to master i2c device
1345 * \param[in] type The callback type
1346 * \param[in] func The callback function pointer
1347 */
1348int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *const i2c_dev, enum _i2c_m_async_callback_type type,
1349 FUNC_PTR func)
1350{
1351 switch (type) {
1352 case I2C_M_ASYNC_DEVICE_ERROR:
1353 i2c_dev->cb.error = (_i2c_error_cb_t)func;
1354 break;
1355 case I2C_M_ASYNC_DEVICE_TX_COMPLETE:
1356 i2c_dev->cb.tx_complete = (_i2c_complete_cb_t)func;
1357 break;
1358 case I2C_M_ASYNC_DEVICE_RX_COMPLETE:
1359 i2c_dev->cb.rx_complete = (_i2c_complete_cb_t)func;
1360 break;
1361 default:
1362 /* error */
1363 break;
1364 }
1365
1366 return ERR_NONE;
1367}
1368
1369/**
1370 * \brief Set stop condition on I2C
1371 *
1372 * \param i2c_dev Pointer to master i2c device
1373 *
1374 * \return Operation status
1375 * \retval I2C_OK Operation was successfull
1376 */
1377int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev)
1378{
1379 void *hw = i2c_dev->hw;
1380
1381 _sercom_i2c_send_stop(hw);
1382
1383 return I2C_OK;
1384}
1385
1386/**
1387 * \brief Get number of bytes left in transfer buffer
1388 *
1389 * \param i2c_dev Pointer to i2c master device
1390 *
1391 * \return Bytes left in buffer
1392 * \retval =>0 Bytes left in buffer
1393 */
1394int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev)
1395{
1396 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1397 return i2c_dev->service.msg.len;
1398 }
1399
1400 return 0;
1401}
1402
1403/**
1404 * \brief Initialize sercom i2c module to use in sync mode
1405 *
1406 * \param[in] i2c_dev The pointer to i2c device
1407 */
1408int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw)
1409{
1410 ASSERT(i2c_dev);
1411
1412 i2c_dev->hw = hw;
1413
1414 return _i2c_m_sync_init_impl(&i2c_dev->service, hw);
1415}
1416
1417/**
1418 * \brief Deinitialize sercom i2c module
1419 *
1420 * \param[in] i2c_dev The pointer to i2c device
1421 */
1422int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev)
1423{
1424 ASSERT(i2c_dev);
1425
1426 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(i2c_dev->hw);
1427 hri_sercomi2cm_set_CTRLA_SWRST_bit(i2c_dev->hw);
1428
1429 return ERR_NONE;
1430}
1431
1432/**
1433 * \brief Enable the i2c master module
1434 *
1435 * \param[in] i2c_dev The pointer to i2c device
1436 */
1437int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev)
1438{
1439 ASSERT(i2c_dev);
1440
1441 _i2c_m_enable_implementation(i2c_dev->hw);
1442
1443 return ERR_NONE;
1444}
1445
1446/**
1447 * \brief Disable the i2c master module
1448 *
1449 * \param[in] i2c_dev The pointer to i2c device
1450 */
1451int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev)
1452{
1453 void *hw = i2c_dev->hw;
1454
1455 ASSERT(i2c_dev);
1456 ASSERT(i2c_dev->hw);
1457
1458 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1459
1460 return ERR_NONE;
1461}
1462
1463/**
1464 * \brief Set baudrate of master
1465 *
1466 * \param[in] i2c_dev The pointer to i2c device
1467 * \param[in] clkrate The clock rate of i2c master, in KHz
1468 * \param[in] baudrate The baud rate desired for i2c master, in KHz
1469 */
1470int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate)
1471{
1472 uint32_t tmp;
1473 void * hw = i2c_dev->hw;
1474
1475 if (hri_sercomi2cm_get_CTRLA_ENABLE_bit(hw)) {
1476 return ERR_DENIED;
1477 }
1478
1479 tmp = _get_i2cm_index(hw);
1480 clkrate = _i2cms[tmp].clk / 1000;
1481
1482 if (i2c_dev->service.mode == I2C_STANDARD_MODE) {
1483 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1484 / (2 * baudrate));
1485 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1486 } else if (i2c_dev->service.mode == I2C_FASTMODE) {
1487 tmp = (uint32_t)((clkrate - 10 * baudrate - baudrate * clkrate * (i2c_dev->service.trise * 0.000000001))
1488 / (2 * baudrate));
1489 hri_sercomi2cm_write_BAUD_BAUD_bf(hw, tmp);
1490 } else if (i2c_dev->service.mode == I2C_HIGHSPEED_MODE) {
1491 tmp = (clkrate - 2 * baudrate) / (2 * baudrate);
1492 hri_sercomi2cm_write_BAUD_HSBAUD_bf(hw, tmp);
1493 } else {
1494 /* error baudrate */
1495 return ERR_INVALID_ARG;
1496 }
1497
1498 return ERR_NONE;
1499}
1500
1501/**
1502 * \brief Enable/disable I2C master interrupt
1503 */
1504void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type,
1505 const bool state)
1506{
1507 if (I2C_M_ASYNC_DEVICE_TX_COMPLETE == type || I2C_M_ASYNC_DEVICE_RX_COMPLETE == type) {
1508 hri_sercomi2cm_write_INTEN_SB_bit(device->hw, state);
1509 hri_sercomi2cm_write_INTEN_MB_bit(device->hw, state);
1510 } else if (I2C_M_ASYNC_DEVICE_ERROR == type) {
1511 hri_sercomi2cm_write_INTEN_ERROR_bit(device->hw, state);
1512 }
1513}
1514
1515/**
1516 * \brief Wait for bus response
1517 *
1518 * \param[in] i2c_dev The pointer to i2c device
1519 * \param[in] flags Store the hardware response
1520 *
1521 * \return Bus response status.
1522 * \retval 0 Bus response status OK
1523 * \retval <0 Bus response fail
1524 */
1525inline static int32_t _sercom_i2c_sync_wait_bus(struct _i2c_m_sync_device *const i2c_dev, uint32_t *flags)
1526{
1527 uint32_t timeout = 65535;
1528 void * hw = i2c_dev->hw;
1529
1530 do {
1531 *flags = hri_sercomi2cm_read_INTFLAG_reg(hw);
1532
1533 if (timeout-- == 0) {
1534 return I2C_ERR_BUS;
1535 }
1536 } while (!(*flags & MB_FLAG) && !(*flags & SB_FLAG));
1537
1538 return I2C_OK;
1539}
1540
1541/**
1542 * \brief Send the slave address to bus, which will start the transfer
1543 *
1544 * \param[in] i2c_dev The pointer to i2c device
1545 */
1546static int32_t _sercom_i2c_sync_send_address(struct _i2c_m_sync_device *const i2c_dev)
1547{
1548 void * hw = i2c_dev->hw;
1549 struct _i2c_m_msg *msg = &i2c_dev->service.msg;
1550 int sclsm = hri_sercomi2cm_get_CTRLA_SCLSM_bit(hw);
1551 uint32_t flags;
1552
1553 ASSERT(i2c_dev);
1554
1555 if (msg->len == 1 && sclsm) {
1556 hri_sercomi2cm_set_CTRLB_ACKACT_bit(hw);
1557 } else {
1558 hri_sercomi2cm_clear_CTRLB_ACKACT_bit(hw);
1559 }
1560
1561 /* ten bit address */
1562 if (msg->addr & I2C_M_TEN) {
1563 if (msg->flags & I2C_M_RD) {
1564 msg->flags |= I2C_M_TEN;
1565 }
1566
1567 hri_sercomi2cm_write_ADDR_reg(hw,
1568 ((msg->addr & TEN_ADDR_MASK) << 1) | SERCOM_I2CM_ADDR_TENBITEN
1569 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1570 } else {
1571 hri_sercomi2cm_write_ADDR_reg(hw,
1572 ((msg->addr & SEVEN_ADDR_MASK) << 1) | (msg->flags & I2C_M_RD ? I2C_M_RD : 0x0)
1573 | (hri_sercomi2cm_read_ADDR_reg(hw) & SERCOM_I2CM_ADDR_HS));
1574 }
1575
1576 _sercom_i2c_sync_wait_bus(i2c_dev, &flags);
1577 return _sercom_i2c_sync_analyse_flags(hw, flags, msg);
1578}
1579
1580/**
1581 * \brief Transfer data specified by msg
1582 *
1583 * \param[in] i2c_dev The pointer to i2c device
1584 * \param[in] msg The pointer to i2c message
1585 *
1586 * \return Transfer status.
1587 * \retval 0 Transfer success
1588 * \retval <0 Transfer fail or partial fail, return the error code
1589 */
1590int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg)
1591{
1592 uint32_t flags;
1593 int ret;
1594 void * hw = i2c_dev->hw;
1595
1596 ASSERT(i2c_dev);
1597 ASSERT(i2c_dev->hw);
1598 ASSERT(msg);
1599
1600 if (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1601 return I2C_ERR_BUSY;
1602 }
1603
1604 msg->flags |= I2C_M_BUSY;
1605 i2c_dev->service.msg = *msg;
1606 hri_sercomi2cm_set_CTRLB_SMEN_bit(hw);
1607
1608 ret = _sercom_i2c_sync_send_address(i2c_dev);
1609
1610 if (ret) {
1611 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1612
1613 return ret;
1614 }
1615
1616 while (i2c_dev->service.msg.flags & I2C_M_BUSY) {
1617 ret = _sercom_i2c_sync_wait_bus(i2c_dev, &flags);
1618
1619 if (ret) {
1620 if (msg->flags & I2C_M_STOP) {
1621 _sercom_i2c_send_stop(hw);
1622 }
1623
1624 i2c_dev->service.msg.flags &= ~I2C_M_BUSY;
1625
1626 return ret;
1627 }
1628
1629 ret = _sercom_i2c_sync_analyse_flags(hw, flags, &i2c_dev->service.msg);
1630 }
1631
1632 return ret;
1633}
1634
1635int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev)
1636{
1637 void *hw = i2c_dev->hw;
1638
1639 _sercom_i2c_send_stop(hw);
1640
1641 return I2C_OK;
1642}
1643
1644static inline void _i2c_m_enable_implementation(void *const hw)
1645{
1646 int timeout = 65535;
1647
1648 ASSERT(hw);
1649
1650 /* Enable interrupts */
1651 hri_sercomi2cm_set_CTRLA_ENABLE_bit(hw);
1652
1653 while (hri_sercomi2cm_read_STATUS_BUSSTATE_bf(hw) != I2C_IDLE) {
1654 timeout--;
1655
1656 if (timeout <= 0) {
1657 hri_sercomi2cm_clear_STATUS_reg(hw, SERCOM_I2CM_STATUS_BUSSTATE(I2C_IDLE));
1658 }
1659 }
1660}
1661
1662static int32_t _i2c_m_sync_init_impl(struct _i2c_m_service *const service, void *const hw)
1663{
1664 uint8_t i = _get_i2cm_index(hw);
1665
1666 if (!hri_sercomi2cm_is_syncing(hw, SERCOM_I2CM_SYNCBUSY_SWRST)) {
1667 uint32_t mode = _i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_MODE_Msk;
1668 if (hri_sercomi2cm_get_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_ENABLE)) {
1669 hri_sercomi2cm_clear_CTRLA_ENABLE_bit(hw);
1670 hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_ENABLE);
1671 }
1672 hri_sercomi2cm_write_CTRLA_reg(hw, SERCOM_I2CM_CTRLA_SWRST | mode);
1673 }
1674 hri_sercomi2cm_wait_for_sync(hw, SERCOM_I2CM_SYNCBUSY_SWRST);
1675
1676 hri_sercomi2cm_write_CTRLA_reg(hw, _i2cms[i].ctrl_a);
1677 hri_sercomi2cm_write_CTRLB_reg(hw, _i2cms[i].ctrl_b);
1678 hri_sercomi2cm_write_BAUD_reg(hw, _i2cms[i].baud);
1679
1680 service->mode = (_i2cms[i].ctrl_a & SERCOM_I2CM_CTRLA_SPEED_Msk) >> SERCOM_I2CM_CTRLA_SPEED_Pos;
1681 hri_sercomi2cm_write_ADDR_HS_bit(hw, service->mode < I2C_HS ? 0 : 1);
1682
1683 service->trise = _i2cms[i].trise;
1684
1685 return ERR_NONE;
1686}
1687
1688 /* SERCOM I2C slave */
1689
1690#ifndef CONF_SERCOM_0_I2CS_ENABLE
1691#define CONF_SERCOM_0_I2CS_ENABLE 0
1692#endif
1693#ifndef CONF_SERCOM_1_I2CS_ENABLE
1694#define CONF_SERCOM_1_I2CS_ENABLE 0
1695#endif
1696#ifndef CONF_SERCOM_2_I2CS_ENABLE
1697#define CONF_SERCOM_2_I2CS_ENABLE 0
1698#endif
1699#ifndef CONF_SERCOM_3_I2CS_ENABLE
1700#define CONF_SERCOM_3_I2CS_ENABLE 0
1701#endif
1702#ifndef CONF_SERCOM_4_I2CS_ENABLE
1703#define CONF_SERCOM_4_I2CS_ENABLE 0
1704#endif
1705#ifndef CONF_SERCOM_5_I2CS_ENABLE
1706#define CONF_SERCOM_5_I2CS_ENABLE 0
1707#endif
1708#ifndef CONF_SERCOM_6_I2CS_ENABLE
1709#define CONF_SERCOM_6_I2CS_ENABLE 0
1710#endif
1711#ifndef CONF_SERCOM_7_I2CS_ENABLE
1712#define CONF_SERCOM_7_I2CS_ENABLE 0
1713#endif
1714
1715/** Amount of SERCOM that is used as I2C Slave. */
1716#define SERCOM_I2CS_AMOUNT \
1717 (CONF_SERCOM_0_I2CS_ENABLE + CONF_SERCOM_1_I2CS_ENABLE + CONF_SERCOM_2_I2CS_ENABLE + CONF_SERCOM_3_I2CS_ENABLE \
1718 + CONF_SERCOM_4_I2CS_ENABLE + CONF_SERCOM_5_I2CS_ENABLE + CONF_SERCOM_6_I2CS_ENABLE + CONF_SERCOM_7_I2CS_ENABLE)
1719
1720/**
1721 * \brief Macro is used to fill I2C slave configuration structure based on
1722 * its number
1723 *
1724 * \param[in] n The number of structures
1725 */
1726#define I2CS_CONFIGURATION(n) \
1727 { \
1728 n, \
1729 SERCOM_I2CM_CTRLA_MODE_I2C_SLAVE | (CONF_SERCOM_##n##_I2CS_RUNSTDBY << SERCOM_I2CS_CTRLA_RUNSTDBY_Pos) \
1730 | SERCOM_I2CS_CTRLA_SDAHOLD(CONF_SERCOM_##n##_I2CS_SDAHOLD) \
1731 | (CONF_SERCOM_##n##_I2CS_SEXTTOEN << SERCOM_I2CS_CTRLA_SEXTTOEN_Pos) \
1732 | (CONF_SERCOM_##n##_I2CS_SPEED << SERCOM_I2CS_CTRLA_SPEED_Pos) \
1733 | (CONF_SERCOM_##n##_I2CS_SCLSM << SERCOM_I2CS_CTRLA_SCLSM_Pos) \
1734 | (CONF_SERCOM_##n##_I2CS_LOWTOUT << SERCOM_I2CS_CTRLA_LOWTOUTEN_Pos), \
1735 SERCOM_I2CS_CTRLB_SMEN | SERCOM_I2CS_CTRLB_AACKEN | SERCOM_I2CS_CTRLB_AMODE(CONF_SERCOM_##n##_I2CS_AMODE), \
1736 (CONF_SERCOM_##n##_I2CS_GENCEN << SERCOM_I2CS_ADDR_GENCEN_Pos) \
1737 | SERCOM_I2CS_ADDR_ADDR(CONF_SERCOM_##n##_I2CS_ADDRESS) \
1738 | (CONF_SERCOM_##n##_I2CS_TENBITEN << SERCOM_I2CS_ADDR_TENBITEN_Pos) \
1739 | SERCOM_I2CS_ADDR_ADDRMASK(CONF_SERCOM_##n##_I2CS_ADDRESS_MASK) \
1740 }
1741
1742/**
1743 * \brief Macro to check 10-bit addressing
1744 */
1745#define I2CS_7BIT_ADDRESSING_MASK 0x7F
1746
1747static int32_t _i2c_s_init(void *const hw);
1748static int8_t _get_i2c_s_index(const void *const hw);
1749static inline void _i2c_s_deinit(void *const hw);
1750static int32_t _i2c_s_set_address(void *const hw, const uint16_t address);
1751
1752/**
1753 * \brief SERCOM I2C slave configuration type
1754 */
1755struct i2cs_configuration {
1756 uint8_t number;
1757 hri_sercomi2cs_ctrla_reg_t ctrl_a;
1758 hri_sercomi2cs_ctrlb_reg_t ctrl_b;
1759 hri_sercomi2cs_addr_reg_t address;
1760};
1761
1762#if SERCOM_I2CS_AMOUNT < 1
1763/** Dummy array for compiling. */
1764static struct i2cs_configuration _i2css[1] = {{0}};
1765#else
1766/**
1767 * \brief Array of SERCOM I2C slave configurations
1768 */
1769static struct i2cs_configuration _i2css[] = {
1770#if CONF_SERCOM_0_I2CS_ENABLE == 1
1771 I2CS_CONFIGURATION(0),
1772#endif
1773#if CONF_SERCOM_1_I2CS_ENABLE == 1
1774 I2CS_CONFIGURATION(1),
1775#endif
1776#if CONF_SERCOM_2_I2CS_ENABLE == 1
1777 I2CS_CONFIGURATION(2),
1778#endif
1779#if CONF_SERCOM_3_I2CS_ENABLE == 1
1780 I2CS_CONFIGURATION(3),
1781#endif
1782#if CONF_SERCOM_4_I2CS_ENABLE == 1
1783 I2CS_CONFIGURATION(4),
1784#endif
1785#if CONF_SERCOM_5_I2CS_ENABLE == 1
1786 I2CS_CONFIGURATION(5),
1787#endif
1788};
1789#endif
1790
1791/**
1792 * \brief Initialize synchronous I2C slave
1793 */
1794int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw)
1795{
1796 int32_t status;
1797
1798 ASSERT(device);
1799
1800 status = _i2c_s_init(hw);
1801 if (status) {
1802 return status;
1803 }
1804 device->hw = hw;
1805
1806 return ERR_NONE;
1807}
1808
1809/**
1810 * \brief Initialize asynchronous I2C slave
1811 */
1812int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw)
1813{
1814 int32_t init_status;
1815
1816 ASSERT(device);
1817
1818 init_status = _i2c_s_init(hw);
1819 if (init_status) {
1820 return init_status;
1821 }
1822
1823 device->hw = hw;
1824 _sercom_init_irq_param(hw, (void *)device);
1825 uint8_t irq = _sercom_get_irq_num(hw);
1826 for (uint32_t i = 0; i < 4; i++) {
1827 NVIC_DisableIRQ((IRQn_Type)irq);
1828 NVIC_ClearPendingIRQ((IRQn_Type)irq);
1829 NVIC_EnableIRQ((IRQn_Type)irq);
1830 irq++;
1831 }
1832
1833 return ERR_NONE;
1834}
1835
1836/**
1837 * \brief Deinitialize synchronous I2C
1838 */
1839int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device)
1840{
1841 _i2c_s_deinit(device->hw);
1842
1843 return ERR_NONE;
1844}
1845
1846/**
1847 * \brief Deinitialize asynchronous I2C
1848 */
1849int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device)
1850{
1851 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(device->hw));
1852 _i2c_s_deinit(device->hw);
1853
1854 return ERR_NONE;
1855}
1856
1857/**
1858 * \brief Enable I2C module
1859 */
1860int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device)
1861{
1862 hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
1863
1864 return ERR_NONE;
1865}
1866
1867/**
1868 * \brief Enable I2C module
1869 */
1870int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device)
1871{
1872 hri_sercomi2cs_set_CTRLA_ENABLE_bit(device->hw);
1873
1874 return ERR_NONE;
1875}
1876
1877/**
1878 * \brief Disable I2C module
1879 */
1880int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device)
1881{
1882 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
1883
1884 return ERR_NONE;
1885}
1886
1887/**
1888 * \brief Disable I2C module
1889 */
1890int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device)
1891{
1892 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(device->hw);
1893
1894 return ERR_NONE;
1895}
1896
1897/**
1898 * \brief Check if 10-bit addressing mode is on
1899 */
1900int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device)
1901{
1902 return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
1903}
1904
1905/**
1906 * \brief Check if 10-bit addressing mode is on
1907 */
1908int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device)
1909{
1910 return hri_sercomi2cs_get_ADDR_TENBITEN_bit(device->hw);
1911}
1912
1913/**
1914 * \brief Set I2C slave address
1915 */
1916int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address)
1917{
1918 return _i2c_s_set_address(device->hw, address);
1919}
1920
1921/**
1922 * \brief Set I2C slave address
1923 */
1924int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address)
1925{
1926 return _i2c_s_set_address(device->hw, address);
1927}
1928
1929/**
1930 * \brief Write a byte to the given I2C instance
1931 */
1932void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data)
1933{
1934 hri_sercomi2cs_write_DATA_reg(device->hw, data);
1935}
1936
1937/**
1938 * \brief Write a byte to the given I2C instance
1939 */
1940void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data)
1941{
1942 hri_sercomi2cs_write_DATA_reg(device->hw, data);
1943}
1944
1945/**
1946 * \brief Read a byte from the given I2C instance
1947 */
1948uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device)
1949{
1950 return hri_sercomi2cs_read_DATA_reg(device->hw);
1951}
1952
1953/**
1954 * \brief Check if I2C is ready to send next byt
1955 */
1956bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device)
1957{
1958 return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
1959}
1960
1961/**
1962 * \brief Check if there is data received by I2C
1963 */
1964bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device)
1965{
1966 return hri_sercomi2cs_get_interrupt_DRDY_bit(device->hw);
1967}
1968
1969/**
1970 * \brief Retrieve I2C slave status
1971 */
1972i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device)
1973{
1974 return hri_sercomi2cs_read_STATUS_reg(device->hw);
1975}
1976
1977/**
1978 * \brief Clear the Data Ready interrupt flag
1979 */
1980int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device)
1981{
1982 hri_sercomi2cs_clear_INTFLAG_DRDY_bit(device->hw);
1983
1984 return ERR_NONE;
1985}
1986
1987/**
1988 * \brief Retrieve I2C slave status
1989 */
1990i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device)
1991{
1992 return hri_sercomi2cs_read_STATUS_reg(device->hw);
1993}
1994
1995/**
1996 * \brief Abort data transmission
1997 */
1998int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device)
1999{
2000 hri_sercomi2cs_clear_INTEN_DRDY_bit(device->hw);
2001
2002 return ERR_NONE;
2003}
2004
2005/**
2006 * \brief Enable/disable I2C slave interrupt
2007 */
2008int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type,
2009 const bool state)
2010{
2011 ASSERT(device);
2012
2013 if (I2C_S_DEVICE_TX == type || I2C_S_DEVICE_RX_COMPLETE == type) {
2014 hri_sercomi2cs_write_INTEN_DRDY_bit(device->hw, state);
2015 } else if (I2C_S_DEVICE_ERROR == type) {
2016 hri_sercomi2cs_write_INTEN_ERROR_bit(device->hw, state);
2017 }
2018
2019 return ERR_NONE;
2020}
2021
2022/**
2023 * \internal Initalize i2c slave hardware
2024 *
2025 * \param[in] p The pointer to hardware instance
2026 *
2027 *\ return status of initialization
2028 */
2029static int32_t _i2c_s_init(void *const hw)
2030{
2031 int8_t i = _get_i2c_s_index(hw);
2032 if (i == -1) {
2033 return ERR_INVALID_ARG;
2034 }
2035
2036 if (!hri_sercomi2cs_is_syncing(hw, SERCOM_I2CS_CTRLA_SWRST)) {
2037 uint32_t mode = _i2css[i].ctrl_a & SERCOM_I2CS_CTRLA_MODE_Msk;
2038 if (hri_sercomi2cs_get_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_ENABLE)) {
2039 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
2040 hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_ENABLE);
2041 }
2042 hri_sercomi2cs_write_CTRLA_reg(hw, SERCOM_I2CS_CTRLA_SWRST | mode);
2043 }
2044 hri_sercomi2cs_wait_for_sync(hw, SERCOM_I2CS_SYNCBUSY_SWRST);
2045
2046 hri_sercomi2cs_write_CTRLA_reg(hw, _i2css[i].ctrl_a);
2047 hri_sercomi2cs_write_CTRLB_reg(hw, _i2css[i].ctrl_b);
2048 hri_sercomi2cs_write_ADDR_reg(hw, _i2css[i].address);
2049
2050 return ERR_NONE;
2051}
2052
2053/**
2054 * \internal Retrieve ordinal number of the given sercom hardware instance
2055 *
2056 * \param[in] hw The pointer to hardware instance
2057 *
2058 * \return The ordinal number of the given sercom hardware instance
2059 */
2060static int8_t _get_i2c_s_index(const void *const hw)
2061{
2062 uint8_t sercom_offset = _sercom_get_hardware_index(hw);
2063 uint8_t i;
2064
2065 for (i = 0; i < ARRAY_SIZE(_i2css); i++) {
2066 if (_i2css[i].number == sercom_offset) {
2067 return i;
2068 }
2069 }
2070
2071 ASSERT(false);
2072 return -1;
2073}
2074
2075/**
2076 * \internal De-initialize i2c slave
2077 *
2078 * \param[in] hw The pointer to hardware instance
2079 */
2080static inline void _i2c_s_deinit(void *const hw)
2081{
2082 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
2083 hri_sercomi2cs_set_CTRLA_SWRST_bit(hw);
2084}
2085
2086/**
2087 * \internal De-initialize i2c slave
2088 *
2089 * \param[in] hw The pointer to hardware instance
2090 * \param[in] address Address to set
2091 */
2092static int32_t _i2c_s_set_address(void *const hw, const uint16_t address)
2093{
2094 bool enabled;
2095
2096 enabled = hri_sercomi2cs_get_CTRLA_ENABLE_bit(hw);
2097
2098 CRITICAL_SECTION_ENTER()
2099 hri_sercomi2cs_clear_CTRLA_ENABLE_bit(hw);
2100 hri_sercomi2cs_write_ADDR_ADDR_bf(hw, address);
2101 CRITICAL_SECTION_LEAVE()
2102
2103 if (enabled) {
2104 hri_sercomi2cs_set_CTRLA_ENABLE_bit(hw);
2105 }
2106
2107 return ERR_NONE;
2108}
2109
2110 /* Sercom SPI implementation */
2111
2112#ifndef SERCOM_USART_CTRLA_MODE_SPI_SLAVE
2113#define SERCOM_USART_CTRLA_MODE_SPI_SLAVE (2 << 2)
2114#endif
2115
2116#define SPI_DEV_IRQ_MODE 0x8000
2117
2118#define _SPI_CS_PORT_EXTRACT(cs) (((cs) >> 0) & 0xFF)
2119#define _SPI_CS_PIN_EXTRACT(cs) (((cs) >> 8) & 0xFF)
2120
2121COMPILER_PACK_SET(1)
2122/** Initialization configuration of registers. */
2123struct sercomspi_regs_cfg {
2124 uint32_t ctrla;
2125 uint32_t ctrlb;
2126 uint32_t addr;
2127 uint8_t baud;
2128 uint8_t dbgctrl;
2129 uint16_t dummy_byte;
2130 uint8_t n;
2131};
2132COMPILER_PACK_RESET()
2133
2134/** Build configuration from header macros. */
2135#define SERCOMSPI_REGS(n) \
2136 { \
2137 (((CONF_SERCOM_##n##_SPI_DORD) << SERCOM_SPI_CTRLA_DORD_Pos) \
2138 | (CONF_SERCOM_##n##_SPI_CPOL << SERCOM_SPI_CTRLA_CPOL_Pos) \
2139 | (CONF_SERCOM_##n##_SPI_CPHA << SERCOM_SPI_CTRLA_CPHA_Pos) \
2140 | (CONF_SERCOM_##n##_SPI_AMODE_EN ? SERCOM_SPI_CTRLA_FORM(2) : SERCOM_SPI_CTRLA_FORM(0)) \
2141 | SERCOM_SPI_CTRLA_DOPO(CONF_SERCOM_##n##_SPI_TXPO) | SERCOM_SPI_CTRLA_DIPO(CONF_SERCOM_##n##_SPI_RXPO) \
2142 | (CONF_SERCOM_##n##_SPI_IBON << SERCOM_SPI_CTRLA_IBON_Pos) \
2143 | (CONF_SERCOM_##n##_SPI_RUNSTDBY << SERCOM_SPI_CTRLA_RUNSTDBY_Pos) \
2144 | SERCOM_SPI_CTRLA_MODE(CONF_SERCOM_##n##_SPI_MODE)), /* ctrla */ \
2145 ((CONF_SERCOM_##n##_SPI_RXEN << SERCOM_SPI_CTRLB_RXEN_Pos) \
2146 | (CONF_SERCOM_##n##_SPI_MSSEN << SERCOM_SPI_CTRLB_MSSEN_Pos) \
2147 | (CONF_SERCOM_##n##_SPI_SSDE << SERCOM_SPI_CTRLB_SSDE_Pos) \
2148 | (CONF_SERCOM_##n##_SPI_PLOADEN << SERCOM_SPI_CTRLB_PLOADEN_Pos) \
2149 | SERCOM_SPI_CTRLB_AMODE(CONF_SERCOM_##n##_SPI_AMODE) \
2150 | SERCOM_SPI_CTRLB_CHSIZE(CONF_SERCOM_##n##_SPI_CHSIZE)), /* ctrlb */ \
2151 (SERCOM_SPI_ADDR_ADDR(CONF_SERCOM_##n##_SPI_ADDR) \
2152 | SERCOM_SPI_ADDR_ADDRMASK(CONF_SERCOM_##n##_SPI_ADDRMASK)), /* addr */ \
2153 ((uint8_t)CONF_SERCOM_##n##_SPI_BAUD_RATE), /* baud */ \
2154 (CONF_SERCOM_##n##_SPI_DBGSTOP << SERCOM_SPI_DBGCTRL_DBGSTOP_Pos), /* dbgctrl */ \
2155 CONF_SERCOM_##n##_SPI_DUMMYBYTE, /* Dummy byte for SPI master mode */ \
2156 n /* sercom number */ \
2157 }
2158
2159#ifndef CONF_SERCOM_0_SPI_ENABLE
2160#define CONF_SERCOM_0_SPI_ENABLE 0
2161#endif
2162#ifndef CONF_SERCOM_1_SPI_ENABLE
2163#define CONF_SERCOM_1_SPI_ENABLE 0
2164#endif
2165#ifndef CONF_SERCOM_2_SPI_ENABLE
2166#define CONF_SERCOM_2_SPI_ENABLE 0
2167#endif
2168#ifndef CONF_SERCOM_3_SPI_ENABLE
2169#define CONF_SERCOM_3_SPI_ENABLE 0
2170#endif
2171#ifndef CONF_SERCOM_4_SPI_ENABLE
2172#define CONF_SERCOM_4_SPI_ENABLE 0
2173#endif
2174#ifndef CONF_SERCOM_5_SPI_ENABLE
2175#define CONF_SERCOM_5_SPI_ENABLE 0
2176#endif
2177#ifndef CONF_SERCOM_6_SPI_ENABLE
2178#define CONF_SERCOM_6_SPI_ENABLE 0
2179#endif
2180#ifndef CONF_SERCOM_7_SPI_ENABLE
2181#define CONF_SERCOM_7_SPI_ENABLE 0
2182#endif
2183
2184/** Amount of SERCOM that is used as SPI */
2185#define SERCOM_SPI_AMOUNT \
2186 (CONF_SERCOM_0_SPI_ENABLE + CONF_SERCOM_1_SPI_ENABLE + CONF_SERCOM_2_SPI_ENABLE + CONF_SERCOM_3_SPI_ENABLE \
2187 + CONF_SERCOM_4_SPI_ENABLE + CONF_SERCOM_5_SPI_ENABLE + CONF_SERCOM_6_SPI_ENABLE + CONF_SERCOM_7_SPI_ENABLE)
2188
2189#if SERCOM_SPI_AMOUNT < 1
2190/** Dummy array for compiling. */
2191static const struct sercomspi_regs_cfg sercomspi_regs[1] = {{0}};
2192#else
2193/** The SERCOM SPI configurations of SERCOM that is used as SPI. */
2194static const struct sercomspi_regs_cfg sercomspi_regs[] = {
2195#if CONF_SERCOM_0_SPI_ENABLE
2196 SERCOMSPI_REGS(0),
2197#endif
2198#if CONF_SERCOM_1_SPI_ENABLE
2199 SERCOMSPI_REGS(1),
2200#endif
2201#if CONF_SERCOM_2_SPI_ENABLE
2202 SERCOMSPI_REGS(2),
2203#endif
2204#if CONF_SERCOM_3_SPI_ENABLE
2205 SERCOMSPI_REGS(3),
2206#endif
2207#if CONF_SERCOM_4_SPI_ENABLE
2208 SERCOMSPI_REGS(4),
2209#endif
2210#if CONF_SERCOM_5_SPI_ENABLE
2211 SERCOMSPI_REGS(5),
2212#endif
2213#if CONF_SERCOM_6_SPI_ENABLE
2214 SERCOMSPI_REGS(6),
2215#endif
2216#if CONF_SERCOM_7_SPI_ENABLE
2217 SERCOMSPI_REGS(7),
2218#endif
2219};
2220#endif
2221
2222/** \internal De-initialize SERCOM SPI
2223 *
2224 * \param[in] hw Pointer to the hardware register base.
2225 *
2226 * \return De-initialization status
2227 */
2228static int32_t _spi_deinit(void *const hw)
2229{
2230 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2231 hri_sercomspi_set_CTRLA_SWRST_bit(hw);
2232
2233 return ERR_NONE;
2234}
2235
2236/** \internal Enable SERCOM SPI
2237 *
2238 * \param[in] hw Pointer to the hardware register base.
2239 *
2240 * \return Enabling status
2241 */
2242static int32_t _spi_sync_enable(void *const hw)
2243{
2244 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2245 return ERR_BUSY;
2246 }
2247
2248 hri_sercomspi_set_CTRLA_ENABLE_bit(hw);
2249
2250 return ERR_NONE;
2251}
2252
2253/** \internal Enable SERCOM SPI
2254 *
2255 * \param[in] hw Pointer to the hardware register base.
2256 *
2257 * \return Enabling status
2258 */
2259static int32_t _spi_async_enable(void *const hw)
2260{
2261 _spi_sync_enable(hw);
2262 uint8_t irq = _sercom_get_irq_num(hw);
2263 for (uint32_t i = 0; i < 4; i++) {
2264 NVIC_EnableIRQ((IRQn_Type)irq++);
2265 }
2266
2267 return ERR_NONE;
2268}
2269
2270/** \internal Disable SERCOM SPI
2271 *
2272 * \param[in] hw Pointer to the hardware register base.
2273 *
2274 * \return Disabling status
2275 */
2276static int32_t _spi_sync_disable(void *const hw)
2277{
2278 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2279 return ERR_BUSY;
2280 }
2281 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2282
2283 return ERR_NONE;
2284}
2285
2286/** \internal Disable SERCOM SPI
2287 *
2288 * \param[in] hw Pointer to the hardware register base.
2289 *
2290 * \return Disabling status
2291 */
2292static int32_t _spi_async_disable(void *const hw)
2293{
2294 _spi_sync_disable(hw);
2295 hri_sercomspi_clear_INTEN_reg(
2296 hw, SERCOM_SPI_INTFLAG_ERROR | SERCOM_SPI_INTFLAG_RXC | SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
2297 uint8_t irq = _sercom_get_irq_num(hw);
2298 for (uint32_t i = 0; i < 4; i++) {
2299 NVIC_DisableIRQ((IRQn_Type)irq++);
2300 }
2301
2302 return ERR_NONE;
2303}
2304
2305/** \internal Set SERCOM SPI mode
2306 *
2307 * \param[in] hw Pointer to the hardware register base.
2308 * \param[in] mode The mode to set
2309 *
2310 * \return Setting mode status
2311 */
2312static int32_t _spi_set_mode(void *const hw, const enum spi_transfer_mode mode)
2313{
2314 uint32_t ctrla;
2315
2316 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE)) {
2317 return ERR_BUSY;
2318 }
2319
2320 ctrla = hri_sercomspi_read_CTRLA_reg(hw);
2321 ctrla &= ~(SERCOM_SPI_CTRLA_CPOL | SERCOM_SPI_CTRLA_CPHA);
2322 ctrla |= (mode & 0x3u) << SERCOM_SPI_CTRLA_CPHA_Pos;
2323 hri_sercomspi_write_CTRLA_reg(hw, ctrla);
2324
2325 return ERR_NONE;
2326}
2327
2328/** \internal Set SERCOM SPI baudrate
2329 *
2330 * \param[in] hw Pointer to the hardware register base.
2331 * \param[in] baud_val The baudrate to set
2332 *
2333 * \return Setting baudrate status
2334 */
2335static int32_t _spi_set_baudrate(void *const hw, const uint32_t baud_val)
2336{
2337 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2338 return ERR_BUSY;
2339 }
2340
2341 hri_sercomspi_write_BAUD_reg(hw, baud_val);
2342
2343 return ERR_NONE;
2344}
2345
2346/** \internal Set SERCOM SPI char size
2347 *
2348 * \param[in] hw Pointer to the hardware register base.
2349 * \param[in] baud_val The baudrate to set
2350 * \param[out] size Stored char size
2351 *
2352 * \return Setting char size status
2353 */
2354static int32_t _spi_set_char_size(void *const hw, const enum spi_char_size char_size, uint8_t *const size)
2355{
2356 /* Only 8-bit or 9-bit accepted */
2357 if (!(char_size == SPI_CHAR_SIZE_8 || char_size == SPI_CHAR_SIZE_9)) {
2358 return ERR_INVALID_ARG;
2359 }
2360
2361 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_CTRLB)) {
2362 return ERR_BUSY;
2363 }
2364
2365 hri_sercomspi_write_CTRLB_CHSIZE_bf(hw, char_size);
2366 *size = (char_size == SPI_CHAR_SIZE_8) ? 1 : 2;
2367
2368 return ERR_NONE;
2369}
2370
2371/** \internal Set SERCOM SPI data order
2372 *
2373 * \param[in] hw Pointer to the hardware register base.
2374 * \param[in] baud_val The baudrate to set
2375 *
2376 * \return Setting data order status
2377 */
2378static int32_t _spi_set_data_order(void *const hw, const enum spi_data_order dord)
2379{
2380 uint32_t ctrla;
2381
2382 if (hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2383 return ERR_BUSY;
2384 }
2385
2386 ctrla = hri_sercomspi_read_CTRLA_reg(hw);
2387
2388 if (dord == SPI_DATA_ORDER_LSB_1ST) {
2389 ctrla |= SERCOM_SPI_CTRLA_DORD;
2390 } else {
2391 ctrla &= ~SERCOM_SPI_CTRLA_DORD;
2392 }
2393 hri_sercomspi_write_CTRLA_reg(hw, ctrla);
2394
2395 return ERR_NONE;
2396}
2397
2398/** \brief Load SERCOM registers to init for SPI master mode
2399 * The settings will be applied with default master mode, unsupported things
2400 * are ignored.
2401 * \param[in, out] hw Pointer to the hardware register base.
2402 * \param[in] regs Pointer to register configuration values.
2403 */
2404static inline void _spi_load_regs_master(void *const hw, const struct sercomspi_regs_cfg *regs)
2405{
2406 ASSERT(hw && regs);
2407 hri_sercomspi_write_CTRLA_reg(
2408 hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
2409 hri_sercomspi_write_CTRLB_reg(
2410 hw,
2411 (regs->ctrlb
2412 & ~(SERCOM_SPI_CTRLB_MSSEN | SERCOM_SPI_CTRLB_AMODE_Msk | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN))
2413 | (SERCOM_SPI_CTRLB_RXEN));
2414 hri_sercomspi_write_BAUD_reg(hw, regs->baud);
2415 hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
2416}
2417
2418/** \brief Load SERCOM registers to init for SPI slave mode
2419 * The settings will be applied with default slave mode, unsupported things
2420 * are ignored.
2421 * \param[in, out] hw Pointer to the hardware register base.
2422 * \param[in] regs Pointer to register configuration values.
2423 */
2424static inline void _spi_load_regs_slave(void *const hw, const struct sercomspi_regs_cfg *regs)
2425{
2426 ASSERT(hw && regs);
2427 hri_sercomspi_write_CTRLA_reg(
2428 hw, regs->ctrla & ~(SERCOM_SPI_CTRLA_IBON | SERCOM_SPI_CTRLA_ENABLE | SERCOM_SPI_CTRLA_SWRST));
2429 hri_sercomspi_write_CTRLB_reg(hw,
2430 (regs->ctrlb & ~(SERCOM_SPI_CTRLB_MSSEN))
2431 | (SERCOM_SPI_CTRLB_RXEN | SERCOM_SPI_CTRLB_SSDE | SERCOM_SPI_CTRLB_PLOADEN));
2432 hri_sercomspi_write_ADDR_reg(hw, regs->addr);
2433 hri_sercomspi_write_DBGCTRL_reg(hw, regs->dbgctrl);
2434 while (hri_sercomspi_is_syncing(hw, 0xFFFFFFFF))
2435 ;
2436}
2437
2438/** \brief Return the pointer to register settings of specific SERCOM
2439 * \param[in] hw_addr The hardware register base address.
2440 * \return Pointer to register settings of specific SERCOM.
2441 */
2442static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_addr)
2443{
2444 uint8_t n = _sercom_get_hardware_index((const void *)hw_addr);
2445 uint8_t i;
2446
2447 for (i = 0; i < sizeof(sercomspi_regs) / sizeof(struct sercomspi_regs_cfg); i++) {
2448 if (sercomspi_regs[i].n == n) {
2449 return &sercomspi_regs[i];
2450 }
2451 }
2452
2453 return NULL;
2454}
2455
Kévin Redonccbed0b2019-01-24 18:30:26 +01002456/**
2457 * \internal Sercom interrupt handler
2458 */
Kévin Redon1f8ecef2019-01-31 13:36:12 +01002459void SERCOM0_0_Handler(void)
2460{
2461 _sercom_usart_interrupt_handler(_sercom0_dev);
2462}
2463/**
2464 * \internal Sercom interrupt handler
2465 */
2466void SERCOM0_1_Handler(void)
2467{
2468 _sercom_usart_interrupt_handler(_sercom0_dev);
2469}
2470/**
2471 * \internal Sercom interrupt handler
2472 */
2473void SERCOM0_2_Handler(void)
2474{
2475 _sercom_usart_interrupt_handler(_sercom0_dev);
2476}
2477/**
2478 * \internal Sercom interrupt handler
2479 */
2480void SERCOM0_3_Handler(void)
2481{
2482 _sercom_usart_interrupt_handler(_sercom0_dev);
2483}
2484
2485/**
2486 * \internal Sercom interrupt handler
2487 */
2488void SERCOM1_0_Handler(void)
2489{
2490 _sercom_usart_interrupt_handler(_sercom1_dev);
2491}
2492/**
2493 * \internal Sercom interrupt handler
2494 */
2495void SERCOM1_1_Handler(void)
2496{
2497 _sercom_usart_interrupt_handler(_sercom1_dev);
2498}
2499/**
2500 * \internal Sercom interrupt handler
2501 */
2502void SERCOM1_2_Handler(void)
2503{
2504 _sercom_usart_interrupt_handler(_sercom1_dev);
2505}
2506/**
2507 * \internal Sercom interrupt handler
2508 */
2509void SERCOM1_3_Handler(void)
2510{
2511 _sercom_usart_interrupt_handler(_sercom1_dev);
2512}
2513
2514/**
2515 * \internal Sercom interrupt handler
2516 */
2517void SERCOM2_0_Handler(void)
2518{
2519 _sercom_usart_interrupt_handler(_sercom2_dev);
2520}
2521/**
2522 * \internal Sercom interrupt handler
2523 */
2524void SERCOM2_1_Handler(void)
2525{
2526 _sercom_usart_interrupt_handler(_sercom2_dev);
2527}
2528/**
2529 * \internal Sercom interrupt handler
2530 */
2531void SERCOM2_2_Handler(void)
2532{
2533 _sercom_usart_interrupt_handler(_sercom2_dev);
2534}
2535/**
2536 * \internal Sercom interrupt handler
2537 */
2538void SERCOM2_3_Handler(void)
2539{
2540 _sercom_usart_interrupt_handler(_sercom2_dev);
2541}
2542
2543/**
2544 * \internal Sercom interrupt handler
2545 */
2546void SERCOM3_0_Handler(void)
2547{
2548 _sercom_usart_interrupt_handler(_sercom3_dev);
2549}
2550/**
2551 * \internal Sercom interrupt handler
2552 */
2553void SERCOM3_1_Handler(void)
2554{
2555 _sercom_usart_interrupt_handler(_sercom3_dev);
2556}
2557/**
2558 * \internal Sercom interrupt handler
2559 */
2560void SERCOM3_2_Handler(void)
2561{
2562 _sercom_usart_interrupt_handler(_sercom3_dev);
2563}
2564/**
2565 * \internal Sercom interrupt handler
2566 */
2567void SERCOM3_3_Handler(void)
2568{
2569 _sercom_usart_interrupt_handler(_sercom3_dev);
2570}
2571
2572/**
2573 * \internal Sercom interrupt handler
2574 */
2575void SERCOM4_0_Handler(void)
2576{
2577 _sercom_usart_interrupt_handler(_sercom4_dev);
2578}
2579/**
2580 * \internal Sercom interrupt handler
2581 */
2582void SERCOM4_1_Handler(void)
2583{
2584 _sercom_usart_interrupt_handler(_sercom4_dev);
2585}
2586/**
2587 * \internal Sercom interrupt handler
2588 */
2589void SERCOM4_2_Handler(void)
2590{
2591 _sercom_usart_interrupt_handler(_sercom4_dev);
2592}
2593/**
2594 * \internal Sercom interrupt handler
2595 */
2596void SERCOM4_3_Handler(void)
2597{
2598 _sercom_usart_interrupt_handler(_sercom4_dev);
2599}
2600
2601/**
2602 * \internal Sercom interrupt handler
2603 */
2604void SERCOM5_0_Handler(void)
2605{
2606 _sercom_usart_interrupt_handler(_sercom5_dev);
2607}
2608/**
2609 * \internal Sercom interrupt handler
2610 */
2611void SERCOM5_1_Handler(void)
2612{
2613 _sercom_usart_interrupt_handler(_sercom5_dev);
2614}
2615/**
2616 * \internal Sercom interrupt handler
2617 */
2618void SERCOM5_2_Handler(void)
2619{
2620 _sercom_usart_interrupt_handler(_sercom5_dev);
2621}
2622/**
2623 * \internal Sercom interrupt handler
2624 */
2625void SERCOM5_3_Handler(void)
2626{
2627 _sercom_usart_interrupt_handler(_sercom5_dev);
2628}
2629
2630/**
2631 * \internal Sercom interrupt handler
2632 */
2633void SERCOM6_0_Handler(void)
2634{
2635 _sercom_usart_interrupt_handler(_sercom6_dev);
2636}
2637/**
2638 * \internal Sercom interrupt handler
2639 */
2640void SERCOM6_1_Handler(void)
2641{
2642 _sercom_usart_interrupt_handler(_sercom6_dev);
2643}
2644/**
2645 * \internal Sercom interrupt handler
2646 */
2647void SERCOM6_2_Handler(void)
2648{
2649 _sercom_usart_interrupt_handler(_sercom6_dev);
2650}
2651/**
2652 * \internal Sercom interrupt handler
2653 */
2654void SERCOM6_3_Handler(void)
2655{
2656 _sercom_usart_interrupt_handler(_sercom6_dev);
2657}
2658
Kévin Redonba3a2fa2019-03-07 15:52:27 +01002659/**
2660 * \internal Sercom interrupt handler
2661 */
2662void SERCOM7_0_Handler(void)
2663{
2664 _sercom_usart_interrupt_handler(_sercom7_dev);
2665}
2666/**
2667 * \internal Sercom interrupt handler
2668 */
2669void SERCOM7_1_Handler(void)
2670{
2671 _sercom_usart_interrupt_handler(_sercom7_dev);
2672}
2673/**
2674 * \internal Sercom interrupt handler
2675 */
2676void SERCOM7_2_Handler(void)
2677{
2678 _sercom_usart_interrupt_handler(_sercom7_dev);
2679}
2680/**
2681 * \internal Sercom interrupt handler
2682 */
2683void SERCOM7_3_Handler(void)
2684{
2685 _sercom_usart_interrupt_handler(_sercom7_dev);
2686}
2687
Kévin Redon4cd3f7d2019-01-24 17:57:13 +01002688int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw)
2689{
2690 const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw);
2691
2692 ASSERT(dev && hw);
2693
2694 if (regs == NULL) {
2695 return ERR_INVALID_ARG;
2696 }
2697
2698 if (!hri_sercomspi_is_syncing(hw, SERCOM_SPI_SYNCBUSY_SWRST)) {
2699 uint32_t mode = regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk;
2700 if (hri_sercomspi_get_CTRLA_reg(hw, SERCOM_SPI_CTRLA_ENABLE)) {
2701 hri_sercomspi_clear_CTRLA_ENABLE_bit(hw);
2702 hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_ENABLE);
2703 }
2704 hri_sercomspi_write_CTRLA_reg(hw, SERCOM_SPI_CTRLA_SWRST | mode);
2705 }
2706 hri_sercomspi_wait_for_sync(hw, SERCOM_SPI_SYNCBUSY_SWRST);
2707
2708 dev->prvt = hw;
2709
2710 if ((regs->ctrla & SERCOM_SPI_CTRLA_MODE_Msk) == SERCOM_USART_CTRLA_MODE_SPI_SLAVE) {
2711 _spi_load_regs_slave(hw, regs);
2712 } else {
2713 _spi_load_regs_master(hw, regs);
2714 }
2715
2716 /* Load character size from default hardware configuration */
2717 dev->char_size = ((regs->ctrlb & SERCOM_SPI_CTRLB_CHSIZE_Msk) == 0) ? 1 : 2;
2718
2719 dev->dummy_byte = regs->dummy_byte;
2720
2721 return ERR_NONE;
2722}
2723
2724int32_t _spi_s_sync_init(struct _spi_s_sync_dev *dev, void *const hw)
2725{
2726 return _spi_m_sync_init(dev, hw);
2727}
2728
2729int32_t _spi_m_async_init(struct _spi_async_dev *dev, void *const hw)
2730{
2731 struct _spi_async_dev *spid = dev;
2732 /* Do hardware initialize. */
2733 int32_t rc = _spi_m_sync_init((struct _spi_m_sync_dev *)dev, hw);
2734
2735 if (rc < 0) {
2736 return rc;
2737 }
2738
2739 _sercom_init_irq_param(hw, (void *)dev);
2740 /* Initialize callbacks: must use them */
2741 spid->callbacks.complete = NULL;
2742 spid->callbacks.rx = NULL;
2743 spid->callbacks.tx = NULL;
2744 uint8_t irq = _sercom_get_irq_num(hw);
2745 for (uint32_t i = 0; i < 4; i++) {
2746 NVIC_DisableIRQ((IRQn_Type)irq);
2747 NVIC_ClearPendingIRQ((IRQn_Type)irq);
2748 irq++;
2749 }
2750
2751 return ERR_NONE;
2752}
2753
2754int32_t _spi_s_async_init(struct _spi_s_async_dev *dev, void *const hw)
2755{
2756 return _spi_m_async_init(dev, hw);
2757}
2758
2759int32_t _spi_m_async_deinit(struct _spi_async_dev *dev)
2760{
2761 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2762 NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2763
2764 return _spi_deinit(dev->prvt);
2765}
2766
2767int32_t _spi_s_async_deinit(struct _spi_s_async_dev *dev)
2768{
2769 NVIC_DisableIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2770 NVIC_ClearPendingIRQ((IRQn_Type)_sercom_get_irq_num(dev->prvt));
2771
2772 return _spi_deinit(dev->prvt);
2773}
2774
2775int32_t _spi_m_sync_deinit(struct _spi_m_sync_dev *dev)
2776{
2777 return _spi_deinit(dev->prvt);
2778}
2779
2780int32_t _spi_s_sync_deinit(struct _spi_s_sync_dev *dev)
2781{
2782 return _spi_deinit(dev->prvt);
2783}
2784
2785int32_t _spi_m_sync_enable(struct _spi_m_sync_dev *dev)
2786{
2787 ASSERT(dev && dev->prvt);
2788
2789 return _spi_sync_enable(dev->prvt);
2790}
2791
2792int32_t _spi_s_sync_enable(struct _spi_s_sync_dev *dev)
2793{
2794 ASSERT(dev && dev->prvt);
2795
2796 return _spi_sync_enable(dev->prvt);
2797}
2798
2799int32_t _spi_m_async_enable(struct _spi_async_dev *dev)
2800{
2801 ASSERT(dev && dev->prvt);
2802
2803 return _spi_async_enable(dev->prvt);
2804}
2805
2806int32_t _spi_s_async_enable(struct _spi_s_async_dev *dev)
2807{
2808 ASSERT(dev && dev->prvt);
2809
2810 return _spi_async_enable(dev->prvt);
2811}
2812
2813int32_t _spi_m_sync_disable(struct _spi_m_sync_dev *dev)
2814{
2815 ASSERT(dev && dev->prvt);
2816
2817 return _spi_sync_disable(dev->prvt);
2818}
2819
2820int32_t _spi_s_sync_disable(struct _spi_s_sync_dev *dev)
2821{
2822 ASSERT(dev && dev->prvt);
2823
2824 return _spi_sync_disable(dev->prvt);
2825}
2826
2827int32_t _spi_m_async_disable(struct _spi_async_dev *dev)
2828{
2829 ASSERT(dev && dev->prvt);
2830
2831 return _spi_async_disable(dev->prvt);
2832}
2833
2834int32_t _spi_s_async_disable(struct _spi_s_async_dev *dev)
2835{
2836 ASSERT(dev && dev->prvt);
2837
2838 return _spi_async_disable(dev->prvt);
2839}
2840
2841int32_t _spi_m_sync_set_mode(struct _spi_m_sync_dev *dev, const enum spi_transfer_mode mode)
2842{
2843 ASSERT(dev && dev->prvt);
2844
2845 return _spi_set_mode(dev->prvt, mode);
2846}
2847
2848int32_t _spi_m_async_set_mode(struct _spi_async_dev *dev, const enum spi_transfer_mode mode)
2849{
2850 ASSERT(dev && dev->prvt);
2851
2852 return _spi_set_mode(dev->prvt, mode);
2853}
2854
2855int32_t _spi_s_async_set_mode(struct _spi_s_async_dev *dev, const enum spi_transfer_mode mode)
2856{
2857 ASSERT(dev && dev->prvt);
2858
2859 return _spi_set_mode(dev->prvt, mode);
2860}
2861
2862int32_t _spi_s_sync_set_mode(struct _spi_s_sync_dev *dev, const enum spi_transfer_mode mode)
2863{
2864 ASSERT(dev && dev->prvt);
2865
2866 return _spi_set_mode(dev->prvt, mode);
2867}
2868
2869int32_t _spi_calc_baud_val(struct spi_dev *dev, const uint32_t clk, const uint32_t baud)
2870{
2871 int32_t rc;
2872 ASSERT(dev);
2873
2874 /* Not accept 0es */
2875 if (clk == 0 || baud == 0) {
2876 return ERR_INVALID_ARG;
2877 }
2878
2879 /* Check baudrate range of current assigned clock */
2880 if (!(baud <= (clk >> 1) && baud >= (clk >> 8))) {
2881 return ERR_INVALID_ARG;
2882 }
2883
2884 rc = ((clk >> 1) / baud) - 1;
2885 return rc;
2886}
2887
2888int32_t _spi_m_sync_set_baudrate(struct _spi_m_sync_dev *dev, const uint32_t baud_val)
2889{
2890 ASSERT(dev && dev->prvt);
2891
2892 return _spi_set_baudrate(dev->prvt, baud_val);
2893}
2894
2895int32_t _spi_m_async_set_baudrate(struct _spi_async_dev *dev, const uint32_t baud_val)
2896{
2897 ASSERT(dev && dev->prvt);
2898
2899 return _spi_set_baudrate(dev->prvt, baud_val);
2900}
2901
2902int32_t _spi_m_sync_set_char_size(struct _spi_m_sync_dev *dev, const enum spi_char_size char_size)
2903{
2904 ASSERT(dev && dev->prvt);
2905
2906 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2907}
2908
2909int32_t _spi_m_async_set_char_size(struct _spi_async_dev *dev, const enum spi_char_size char_size)
2910{
2911 ASSERT(dev && dev->prvt);
2912
2913 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2914}
2915
2916int32_t _spi_s_async_set_char_size(struct _spi_s_async_dev *dev, const enum spi_char_size char_size)
2917{
2918 ASSERT(dev && dev->prvt);
2919
2920 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2921}
2922
2923int32_t _spi_s_sync_set_char_size(struct _spi_s_sync_dev *dev, const enum spi_char_size char_size)
2924{
2925 ASSERT(dev && dev->prvt);
2926
2927 return _spi_set_char_size(dev->prvt, char_size, &dev->char_size);
2928}
2929
2930int32_t _spi_m_sync_set_data_order(struct _spi_m_sync_dev *dev, const enum spi_data_order dord)
2931{
2932 ASSERT(dev && dev->prvt);
2933
2934 return _spi_set_data_order(dev->prvt, dord);
2935}
2936
2937int32_t _spi_m_async_set_data_order(struct _spi_async_dev *dev, const enum spi_data_order dord)
2938{
2939 ASSERT(dev && dev->prvt);
2940
2941 return _spi_set_data_order(dev->prvt, dord);
2942}
2943
2944int32_t _spi_s_async_set_data_order(struct _spi_s_async_dev *dev, const enum spi_data_order dord)
2945{
2946 ASSERT(dev && dev->prvt);
2947
2948 return _spi_set_data_order(dev->prvt, dord);
2949}
2950
2951int32_t _spi_s_sync_set_data_order(struct _spi_s_sync_dev *dev, const enum spi_data_order dord)
2952{
2953 ASSERT(dev && dev->prvt);
2954
2955 return _spi_set_data_order(dev->prvt, dord);
2956}
2957
2958/** Wait until SPI bus idle. */
2959static inline void _spi_wait_bus_idle(void *const hw)
2960{
2961 while (!(hri_sercomspi_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE))) {
2962 ;
2963 }
2964 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC | SERCOM_SPI_INTFLAG_DRE);
2965}
2966
2967/** Holds run time information for message sync transaction. */
2968struct _spi_trans_ctrl {
2969 /** Pointer to transmitting data buffer. */
2970 uint8_t *txbuf;
2971 /** Pointer to receiving data buffer. */
2972 uint8_t *rxbuf;
2973 /** Count number of data transmitted. */
2974 uint32_t txcnt;
2975 /** Count number of data received. */
2976 uint32_t rxcnt;
2977 /** Data character size. */
2978 uint8_t char_size;
2979};
2980
2981/** Check interrupt flag of RXC and update transaction runtime information. */
2982static inline bool _spi_rx_check_and_receive(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl)
2983{
2984 uint32_t data;
2985
2986 if (!(iflag & SERCOM_SPI_INTFLAG_RXC)) {
2987 return false;
2988 }
2989
2990 data = hri_sercomspi_read_DATA_reg(hw);
2991
2992 if (ctrl->rxbuf) {
2993 *ctrl->rxbuf++ = (uint8_t)data;
2994
2995 if (ctrl->char_size > 1) {
2996 *ctrl->rxbuf++ = (uint8_t)(data >> 8);
2997 }
2998 }
2999
3000 ctrl->rxcnt++;
3001
3002 return true;
3003}
3004
3005/** Check interrupt flag of DRE and update transaction runtime information. */
3006static inline void _spi_tx_check_and_send(void *const hw, const uint32_t iflag, struct _spi_trans_ctrl *ctrl,
3007 uint16_t dummy)
3008{
3009 uint32_t data;
3010
3011 if (!(SERCOM_SPI_INTFLAG_DRE & iflag)) {
3012 return;
3013 }
3014
3015 if (ctrl->txbuf) {
3016 data = *ctrl->txbuf++;
3017
3018 if (ctrl->char_size > 1) {
3019 data |= (*ctrl->txbuf) << 8;
3020 ctrl->txbuf++;
3021 }
3022 } else {
3023 data = dummy;
3024 }
3025
3026 ctrl->txcnt++;
3027 hri_sercomspi_write_DATA_reg(hw, data);
3028}
3029
3030/** Check interrupt flag of ERROR and update transaction runtime information. */
3031static inline int32_t _spi_err_check(const uint32_t iflag, void *const hw)
3032{
3033 if (SERCOM_SPI_INTFLAG_ERROR & iflag) {
3034 hri_sercomspi_clear_STATUS_reg(hw, ~0);
3035 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
3036 return ERR_OVERFLOW;
3037 }
3038
3039 return ERR_NONE;
3040}
3041
3042int32_t _spi_m_sync_trans(struct _spi_m_sync_dev *dev, const struct spi_msg *msg)
3043{
3044 void * hw = dev->prvt;
3045 int32_t rc = 0;
3046 struct _spi_trans_ctrl ctrl = {msg->txbuf, msg->rxbuf, 0, 0, dev->char_size};
3047
3048 ASSERT(dev && hw);
3049
3050 /* If settings are not applied (pending), we can not go on */
3051 if (hri_sercomspi_is_syncing(
3052 hw, (SERCOM_SPI_SYNCBUSY_SWRST | SERCOM_SPI_SYNCBUSY_ENABLE | SERCOM_SPI_SYNCBUSY_CTRLB))) {
3053 return ERR_BUSY;
3054 }
3055
3056 /* SPI must be enabled to start synchronous transfer */
3057 if (!hri_sercomspi_get_CTRLA_ENABLE_bit(hw)) {
3058 return ERR_NOT_INITIALIZED;
3059 }
3060
3061 for (;;) {
3062 uint32_t iflag = hri_sercomspi_read_INTFLAG_reg(hw);
3063
3064 if (!_spi_rx_check_and_receive(hw, iflag, &ctrl)) {
3065 /* In master mode, do not start next byte before previous byte received
3066 * to make better output waveform */
3067 if (ctrl.rxcnt >= ctrl.txcnt) {
3068 _spi_tx_check_and_send(hw, iflag, &ctrl, dev->dummy_byte);
3069 }
3070 }
3071
3072 rc = _spi_err_check(iflag, hw);
3073
3074 if (rc < 0) {
3075 break;
3076 }
3077 if (ctrl.txcnt >= msg->size && ctrl.rxcnt >= msg->size) {
3078 rc = ctrl.txcnt;
3079 break;
3080 }
3081 }
3082 /* Wait until SPI bus idle */
3083 _spi_wait_bus_idle(hw);
3084
3085 return rc;
3086}
3087
3088int32_t _spi_m_async_enable_tx(struct _spi_async_dev *dev, bool state)
3089{
3090 void *hw = dev->prvt;
3091
3092 ASSERT(dev && hw);
3093
3094 if (state) {
3095 hri_sercomspi_set_INTEN_DRE_bit(hw);
3096 } else {
3097 hri_sercomspi_clear_INTEN_DRE_bit(hw);
3098 }
3099
3100 return ERR_NONE;
3101}
3102
3103int32_t _spi_s_async_enable_tx(struct _spi_s_async_dev *dev, bool state)
3104{
3105 return _spi_m_async_enable_tx(dev, state);
3106}
3107
3108int32_t _spi_m_async_enable_rx(struct _spi_async_dev *dev, bool state)
3109{
3110 void *hw = dev->prvt;
3111
3112 ASSERT(dev);
3113 ASSERT(hw);
3114
3115 if (state) {
3116 hri_sercomspi_set_INTEN_RXC_bit(hw);
3117 } else {
3118 hri_sercomspi_clear_INTEN_RXC_bit(hw);
3119 }
3120
3121 return ERR_NONE;
3122}
3123
3124int32_t _spi_s_async_enable_rx(struct _spi_s_async_dev *dev, bool state)
3125{
3126 return _spi_m_async_enable_rx(dev, state);
3127}
3128
3129int32_t _spi_m_async_enable_tx_complete(struct _spi_async_dev *dev, bool state)
3130{
3131 ASSERT(dev && dev->prvt);
3132
3133 if (state) {
3134 hri_sercomspi_set_INTEN_TXC_bit(dev->prvt);
3135 } else {
3136 hri_sercomspi_clear_INTEN_TXC_bit(dev->prvt);
3137 }
3138
3139 return ERR_NONE;
3140}
3141
3142int32_t _spi_s_async_enable_ss_detect(struct _spi_s_async_dev *dev, bool state)
3143{
3144 return _spi_m_async_enable_tx_complete(dev, state);
3145}
3146
3147int32_t _spi_m_async_write_one(struct _spi_async_dev *dev, uint16_t data)
3148{
3149 ASSERT(dev && dev->prvt);
3150
3151 hri_sercomspi_write_DATA_reg(dev->prvt, data);
3152
3153 return ERR_NONE;
3154}
3155
3156int32_t _spi_s_async_write_one(struct _spi_s_async_dev *dev, uint16_t data)
3157{
3158 ASSERT(dev && dev->prvt);
3159
3160 hri_sercomspi_write_DATA_reg(dev->prvt, data);
3161
3162 return ERR_NONE;
3163}
3164
3165int32_t _spi_s_sync_write_one(struct _spi_s_sync_dev *dev, uint16_t data)
3166{
3167 ASSERT(dev && dev->prvt);
3168
3169 hri_sercomspi_write_DATA_reg(dev->prvt, data);
3170
3171 return ERR_NONE;
3172}
3173
3174uint16_t _spi_m_async_read_one(struct _spi_async_dev *dev)
3175{
3176 ASSERT(dev && dev->prvt);
3177
3178 return hri_sercomspi_read_DATA_reg(dev->prvt);
3179}
3180
3181uint16_t _spi_s_async_read_one(struct _spi_s_async_dev *dev)
3182{
3183 ASSERT(dev && dev->prvt);
3184
3185 return hri_sercomspi_read_DATA_reg(dev->prvt);
3186}
3187
3188uint16_t _spi_s_sync_read_one(struct _spi_s_sync_dev *dev)
3189{
3190 ASSERT(dev && dev->prvt);
3191
3192 return hri_sercomspi_read_DATA_reg(dev->prvt);
3193}
3194
3195int32_t _spi_m_async_register_callback(struct _spi_async_dev *dev, const enum _spi_async_dev_cb_type cb_type,
3196 const FUNC_PTR func)
3197{
3198 typedef void (*func_t)(void);
3199 struct _spi_async_dev *spid = dev;
3200
3201 ASSERT(dev && (cb_type < SPI_DEV_CB_N));
3202
3203 func_t *p_ls = (func_t *)&spid->callbacks;
3204 p_ls[cb_type] = (func_t)func;
3205
3206 return ERR_NONE;
3207}
3208
3209int32_t _spi_s_async_register_callback(struct _spi_s_async_dev *dev, const enum _spi_s_async_dev_cb_type cb_type,
3210 const FUNC_PTR func)
3211{
3212 return _spi_m_async_register_callback(dev, cb_type, func);
3213}
3214
3215bool _spi_s_sync_is_tx_ready(struct _spi_s_sync_dev *dev)
3216{
3217 ASSERT(dev && dev->prvt);
3218
3219 return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_DRE);
3220}
3221
3222bool _spi_s_sync_is_rx_ready(struct _spi_s_sync_dev *dev)
3223{
3224 ASSERT(dev && dev->prvt);
3225
3226 return hri_sercomi2cm_get_INTFLAG_reg(dev->prvt, SERCOM_SPI_INTFLAG_RXC);
3227}
3228
3229bool _spi_s_sync_is_ss_deactivated(struct _spi_s_sync_dev *dev)
3230{
3231 void *hw = dev->prvt;
3232
3233 ASSERT(dev && hw);
3234
3235 if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC)) {
3236 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_TXC);
3237 return true;
3238 }
3239 return false;
3240}
3241
3242bool _spi_s_sync_is_error(struct _spi_s_sync_dev *dev)
3243{
3244 void *hw = dev->prvt;
3245
3246 ASSERT(dev && hw);
3247
3248 if (hri_sercomi2cm_get_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR)) {
3249 hri_sercomspi_clear_STATUS_reg(hw, SERCOM_SPI_STATUS_BUFOVF);
3250 hri_sercomspi_clear_INTFLAG_reg(hw, SERCOM_SPI_INTFLAG_ERROR);
3251 return true;
3252 }
3253 return false;
3254}
3255
3256/**
3257 * \brief Enable/disable SPI master interrupt
3258 *
3259 * param[in] device The pointer to SPI master device instance
3260 * param[in] type The type of interrupt to disable/enable if applicable
3261 * param[in] state Enable or disable
3262 */
3263void _spi_m_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
3264 const bool state)
3265{
3266 ASSERT(device);
3267
3268 if (SPI_DEV_CB_ERROR == type) {
3269 hri_sercomspi_write_INTEN_ERROR_bit(device->prvt, state);
3270 }
3271}
3272
3273/**
3274 * \brief Enable/disable SPI slave interrupt
3275 *
3276 * param[in] device The pointer to SPI slave device instance
3277 * param[in] type The type of interrupt to disable/enable if applicable
3278 * param[in] state Enable or disable
3279 */
3280void _spi_s_async_set_irq_state(struct _spi_async_dev *const device, const enum _spi_async_dev_cb_type type,
3281 const bool state)
3282{
3283 _spi_m_async_set_irq_state(device, type, state);
3284}