1 /**
2 * \file
3 *
4 * \brief SAM SERCOM I2C Slave Driver
5 *
6 * Copyright (c) 2013-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #ifndef I2C_SLAVE_H_INCLUDED
48 #define I2C_SLAVE_H_INCLUDED
49
50 #include "i2c_common.h"
51 #include <sercom.h>
52 #include <pinmux.h>
53
54 #if I2C_SLAVE_CALLBACK_MODE == true
55 # include <sercom_interrupt.h>
56 #endif
57
58 #ifndef PINMUX_DEFAULT
59 # define PINMUX_DEFAULT 0
60 #endif
61
62 #ifdef __cplusplus
63 extern "C" {
64 #endif
65
66 /**
67 * \addtogroup asfdoc_sam0_sercom_i2c_group
68 *
69 * @{
70 *
71 */
72
73 /**
74 * \name I2C Slave Status Flags
75 *
76 * I<SUP>2</SUP>C slave status flags, returned by \ref i2c_slave_get_status() and cleared
77 * by \ref i2c_slave_clear_status().
78 * @{
79 */
80
81 /** Address Match.
82 * \note Should only be cleared internally by driver.
83 */
84 #define I2C_SLAVE_STATUS_ADDRESS_MATCH (1UL << 0)
85 /** Data Ready. */
86 #define I2C_SLAVE_STATUS_DATA_READY (1UL << 1)
87 /** Stop Received. */
88 #define I2C_SLAVE_STATUS_STOP_RECEIVED (1UL << 2)
89 /** Clock Hold.
90 * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
91 * set.
92 */
93 #define I2C_SLAVE_STATUS_CLOCK_HOLD (1UL << 3)
94 /** SCL Low Timeout. */
95 #define I2C_SLAVE_STATUS_SCL_LOW_TIMEOUT (1UL << 4)
96 /** Repeated Start.
97 * \note Cannot be cleared, only valid when I2C_SLAVE_STATUS_ADDRESS_MATCH is
98 * set.
99 */
100 #define I2C_SLAVE_STATUS_REPEATED_START (1UL << 5)
101 /** Received not acknowledge.
102 * \note Cannot be cleared.
103 */
104 #define I2C_SLAVE_STATUS_RECEIVED_NACK (1UL << 6)
105 /** Transmit Collision. */
106 #define I2C_SLAVE_STATUS_COLLISION (1UL << 7)
107 /** Bus error. */
108 #define I2C_SLAVE_STATUS_BUS_ERROR (1UL << 8)
109
110 /** @} */
111
112 /**
113 * \brief I<SUP>2</SUP>C slave packet for read/write
114 *
115 * Structure to be used when transferring I<SUP>2</SUP>C slave packets.
116 */
117 struct i2c_slave_packet {
118 /** Length of data array */
119 uint16_t data_length;
120 /** Data array containing all data to be transferred */
121 uint8_t *data;
122 };
123
124 #if I2C_SLAVE_CALLBACK_MODE == true
125 /**
126 * \brief Callback types
127 *
128 * The available callback types for the I<SUP>2</SUP>C slave.
129 */
130 enum i2c_slave_callback {
131 /** Callback for packet write complete */
132 I2C_SLAVE_CALLBACK_WRITE_COMPLETE,
133 /** Callback for packet read complete */
134 I2C_SLAVE_CALLBACK_READ_COMPLETE,
135 /**
136 * Callback for read request from master - can be used to
137 * issue a write
138 */
139 I2C_SLAVE_CALLBACK_READ_REQUEST,
140 /**
141 * Callback for write request from master - can be used to issue a read
142 */
143 I2C_SLAVE_CALLBACK_WRITE_REQUEST,
144 /** Callback for error */
145 I2C_SLAVE_CALLBACK_ERROR,
146 /**
147 * Callback for error in last transfer. Discovered on a new address
148 * interrupt.
149 */
150 I2C_SLAVE_CALLBACK_ERROR_LAST_TRANSFER,
151 # if !defined(__DOXYGEN__)
152 /** Total number of callbacks */
153 _I2C_SLAVE_CALLBACK_N,
154 # endif
155 };
156
157 # if !defined(__DOXYGEN__)
158 /** Software module prototype */
159 struct i2c_slave_module;
160
161 /** Callback type */
162 typedef void (*i2c_slave_callback_t)(
163 struct i2c_slave_module *const module);
164 # endif
165 #endif
166
167 /**
168 * \brief Enum for the possible SDA hold times with respect to the negative
169 * edge of SCL
170 *
171 * Enum for the possible SDA hold times with respect to the negative edge
172 * of SCL.
173 */
174 enum i2c_slave_sda_hold_time {
175 /** SDA hold time disabled */
176 I2C_SLAVE_SDA_HOLD_TIME_DISABLED =
177 ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((0) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
178 /** SDA hold time 50ns - 100ns */
179 I2C_SLAVE_SDA_HOLD_TIME_50NS_100NS =
180 ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((1) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
181 /** SDA hold time 300ns - 600ns */
182 I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS =
183 ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((2) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
184 /** SDA hold time 400ns - 800ns */
185 I2C_SLAVE_SDA_HOLD_TIME_400NS_800NS =
186 ((SERCOM_I2CS_CTRLA_SDAHOLD_Msk & ((3) << SERCOM_I2CS_CTRLA_SDAHOLD_Pos))),
187 };
188
189 /**
190 * \brief Enum for the possible address modes
191 *
192 * Enum for the possible address modes.
193 */
194 enum i2c_slave_address_mode {
195 /** Address match on address_mask used as a mask to address */
196 I2C_SLAVE_ADDRESS_MODE_MASK = SERCOM_I2CS_CTRLB_AMODE(0),
197 /** Address math on both address and address_mask */
198 I2C_SLAVE_ADDRESS_MODE_TWO_ADDRESSES = SERCOM_I2CS_CTRLB_AMODE(1),
199 /**
200 * Address match on range of addresses between and including address and
201 * address_mask
202 */
203 I2C_SLAVE_ADDRESS_MODE_RANGE = SERCOM_I2CS_CTRLB_AMODE(2),
204 };
205
206 /**
207 * \brief Enum for the direction of a request
208 *
209 * Enum for the direction of a request.
210 */
211 enum i2c_slave_direction {
212 /** Read */
213 I2C_SLAVE_DIRECTION_READ,
214 /** Write */
215 I2C_SLAVE_DIRECTION_WRITE,
216 /** No direction */
217 I2C_SLAVE_DIRECTION_NONE,
218 };
219
220 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
221 /**
222 * \brief Enum for the transfer speed
223 *
224 * Enum for the transfer speed.
225 */
226 enum i2c_slave_transfer_speed {
227 /** Standard-mode (Sm) up to 100KHz and Fast-mode (Fm) up to 400KHz */
228 I2C_SLAVE_SPEED_STANDARD_AND_FAST = SERCOM_I2CS_CTRLA_SPEED(0),
229 /** Fast-mode Plus (Fm+) up to 1MHz */
230 I2C_SLAVE_SPEED_FAST_MODE_PLUS = SERCOM_I2CS_CTRLA_SPEED(1),
231 /** High-speed mode (Hs-mode) up to 3.4MHz */
232 I2C_SLAVE_SPEED_HIGH_SPEED = SERCOM_I2CS_CTRLA_SPEED(2),
233 };
234 #endif
235
236 /**
237 * \brief SERCOM I<SUP>2</SUP>C slave driver software device instance structure.
238 *
239 * SERCOM I<SUP>2</SUP>C slave driver software instance structure, used to
240 * retain software state information of an associated hardware module instance.
241 *
242 * \note The fields of this structure should not be altered by the user
243 * application; they are reserved for module-internal use only.
244 */
245 struct i2c_slave_module {
246 #if !defined(__DOXYGEN__)
247 /** Hardware instance initialized for the struct */
248 Sercom *hw;
249 /** Module lock */
250 volatile bool locked;
251 /** Timeout value for polled functions */
252 uint16_t buffer_timeout;
253 # ifdef FEATURE_I2C_10_BIT_ADDRESS
254 /** Using 10-bit addressing for the slave */
255 bool ten_bit_address;
256 # endif
257 # if I2C_SLAVE_CALLBACK_MODE == true
258 /** Nack on address match */
259 bool nack_on_address;
260 /** Pointers to callback functions */
261 volatile i2c_slave_callback_t callbacks[_I2C_SLAVE_CALLBACK_N];
262 /** Mask for registered callbacks */
263 volatile uint8_t registered_callback;
264 /** Mask for enabled callbacks */
265 volatile uint8_t enabled_callback;
266 /** The total number of bytes to transfer */
267 volatile uint16_t buffer_length;
268 /**
269 * Counter used for bytes left to send in write and to count number of
270 * obtained bytes in read
271 */
272 uint16_t buffer_remaining;
273 /** Data buffer for packet write and read */
274 volatile uint8_t *buffer;
275 /** Save direction of request from master. 1 = read, 0 = write. */
276 volatile enum i2c_transfer_direction transfer_direction;
277 /** Status for status read back in error callback */
278 volatile enum status_code status;
279 # endif
280 #endif
281 };
282
283 /**
284 * \brief Configuration structure for the I<SUP>2</SUP>C slave device
285 *
286 * This is the configuration structure for the I<SUP>2</SUP>C slave device. It is used
287 * as an argument for \ref i2c_slave_init to provide the desired
288 * configurations for the module. The structure should be initialized using the
289 * \ref i2c_slave_get_config_defaults.
290 */
291 struct i2c_slave_config {
292 /** Set to enable the SCL low timeout */
293 bool enable_scl_low_timeout;
294 /** SDA hold time with respect to the negative edge of SCL */
295 enum i2c_slave_sda_hold_time sda_hold_time;
296 /** Timeout to wait for master in polled functions */
297 uint16_t buffer_timeout;
298 /** Addressing mode */
299 enum i2c_slave_address_mode address_mode;
300 /** Address or upper limit of address range */
301 uint16_t address;
302 /** Address mask, second address, or lower limit of address range */
303 uint16_t address_mask;
304 #ifdef FEATURE_I2C_10_BIT_ADDRESS
305 /** Enable 10-bit addressing */
306 bool ten_bit_address;
307 #endif
308 /**
309 * Enable general call address recognition (general call address
310 * is defined as 0000000 with direction bit 0).
311 */
312 bool enable_general_call_address;
313
314 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
315 /** Transfer speed mode */
316 enum i2c_slave_transfer_speed transfer_speed;
317 #endif
318
319 #if I2C_SLAVE_CALLBACK_MODE == true
320 /**
321 * Enable NACK on address match (this can be changed after initialization
322 * via the \ref i2c_slave_enable_nack_on_address and
323 * \ref i2c_slave_disable_nack_on_address functions).
324 */
325 bool enable_nack_on_address;
326 #endif
327 /** GCLK generator to use as clock source */
328 enum gclk_generator generator_source;
329 /** Set to keep module active in sleep modes */
330 bool run_in_standby;
331 /** PAD0 (SDA) pinmux */
332 uint32_t pinmux_pad0;
333 /** PAD1 (SCL) pinmux */
334 uint32_t pinmux_pad1;
335 /** Set to enable SCL low time-out */
336 bool scl_low_timeout;
337 #ifdef FEATURE_I2C_SCL_STRETCH_MODE
338 /** Set to enable SCL stretch only after ACK bit (required for high speed) */
339 bool scl_stretch_only_after_ack_bit;
340 #endif
341 #ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
342 /** Set to enable slave SCL low extend time-out */
343 bool slave_scl_low_extend_timeout;
344 #endif
345 };
346
347
348 /**
349 * \name Lock/Unlock
350 * @{
351 */
352
353 /**
354 * \brief Attempt to get lock on driver instance
355 *
356 * This function checks the instance's lock, which indicates whether or not it
357 * is currently in use, and sets the lock if it was not already set.
358 *
359 * The purpose of this is to enable exclusive access to driver instances, so
360 * that, e.g., transactions by different services will not interfere with each
361 * other.
362 *
363 * \param[in,out] module Pointer to the driver instance to lock
364 *
365 * \retval STATUS_OK If the module was locked
366 * \retval STATUS_BUSY If the module was already locked
367 */
i2c_slave_lock(struct i2c_slave_module * const module)368 static inline enum status_code i2c_slave_lock(
369 struct i2c_slave_module *const module)
370 {
371 enum status_code status;
372
373 system_interrupt_enter_critical_section();
374
375 if (module->locked) {
376 status = STATUS_BUSY;
377 } else {
378 module->locked = true;
379 status = STATUS_OK;
380 }
381
382 system_interrupt_leave_critical_section();
383
384 return status;
385 }
386
387 /**
388 * \brief Unlock driver instance
389 *
390 * This function clears the instance lock, indicating that it is available for
391 * use.
392 *
393 * \param[in,out] module Pointer to the driver instance to lock
394 *
395 * \retval STATUS_OK If the module was locked
396 * \retval STATUS_BUSY If the module was already locked
397 */
i2c_slave_unlock(struct i2c_slave_module * const module)398 static inline void i2c_slave_unlock(struct i2c_slave_module *const module)
399 {
400 module->locked = false;
401 }
402
403 /** @} */
404
405 /**
406 * \name Configuration and Initialization
407 * @{
408 */
409
410 /**
411 * \brief Returns the synchronization status of the module
412 *
413 * Returns the synchronization status of the module.
414 *
415 * \param[out] module Pointer to software module structure
416 *
417 * \return Status of the synchronization.
418 * \retval true Module is busy synchronizing
419 * \retval false Module is not synchronizing
420 */
i2c_slave_is_syncing(const struct i2c_slave_module * const module)421 static inline bool i2c_slave_is_syncing(
422 const struct i2c_slave_module *const module)
423 {
424 /* Sanity check */
425 Assert(module);
426 Assert(module->hw);
427
428 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
429
430 /* Return sync status */
431 #if defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_1)
432 return (i2c_hw->STATUS.reg & SERCOM_I2CS_STATUS_SYNCBUSY);
433 #elif defined(FEATURE_SERCOM_SYNCBUSY_SCHEME_VERSION_2)
434 return (i2c_hw->SYNCBUSY.reg & SERCOM_I2CS_SYNCBUSY_MASK);
435 #else
436 # error Unknown SERCOM SYNCBUSY scheme!
437 #endif
438 }
439
440 #if !defined(__DOXYGEN__)
441 /**
442 * \internal Wait for hardware module to sync
443 *
444 * \param[in] module Pointer to software module structure
445 */
_i2c_slave_wait_for_sync(const struct i2c_slave_module * const module)446 static void _i2c_slave_wait_for_sync(
447 const struct i2c_slave_module *const module)
448 {
449 /* Sanity check */
450 Assert(module);
451
452 while (i2c_slave_is_syncing(module)) {
453 /* Wait for I<SUP>2</SUP>C module to sync */
454 }
455 }
456 #endif
457
458 ///@cond INTERNAL
459 /**
460 * \internal Workaround for errata 13574
461 * Instead set ACK/NACK of CTRLB
462 *
463 * This errata exist in part revisions of SAM D20/D21/D09
464 * D10/D11/L21/L22/DA1/C20/C21/R30/HA1, but workaround can be works in all
465 * revision of those device. As this function operation
466 * should be use less cpu time as possible, so caller
467 * function can ignore to check revision number, and use
468 * this workaround in all revision of those device.
469 *
470 * \param[in,out] module Pointer to software module structure
471 * \param[in] send_ack true send ACK, false send NACK
472 */
_i2c_slave_set_ctrlb_ackact(struct i2c_slave_module * const module,bool send_ack)473 static inline void _i2c_slave_set_ctrlb_ackact(
474 struct i2c_slave_module *const module,
475 bool send_ack)
476 {
477 Assert(module);
478 Assert(module->hw);
479
480 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
481
482 #if (SAMD20 || SAMD21 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAMDA1 || \
483 SAML22 || SAMC20 || SAMC21 || SAMHA1 || SAMR30)
484 /* Workaround, Following two write are atomic */
485 system_interrupt_enter_critical_section();
486 i2c_hw->STATUS.reg = 0;
487
488 if (send_ack == true) {
489 i2c_hw->CTRLB.reg = 0;
490 }
491 else {
492 i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_ACKACT;
493 }
494 system_interrupt_leave_critical_section();
495 #else
496 /* Normal operation */
497 if (send_ack == true) {
498 i2c_hw->CTRLB.reg &= ~SERCOM_I2CS_CTRLB_ACKACT;
499 }
500 else {
501 i2c_hw->CTRLB.reg |= SERCOM_I2CS_CTRLB_ACKACT;
502 }
503 #endif
504 return;
505 }
506
507 /**
508 * \internal Workaround for SAM0 errata 13574,
509 * instead Set CMD3 of CTRLB
510 *
511 * This errata exist in part revisions of SAM D20/D21/D09
512 * D10/D11/L21/DA1/C20/C21/R30/HA1, but workaround can be works in all
513 * revision of those device. As this function operation
514 * should be use less cpu time as possible, so caller
515 * function can ignore to check revision number, and use
516 * this workaround in all revision of those device.
517 *
518 * \param[in,out] module Pointer to software module structure
519 */
_i2c_slave_set_ctrlb_cmd3(struct i2c_slave_module * const module)520 static inline void _i2c_slave_set_ctrlb_cmd3(
521 struct i2c_slave_module *const module)
522 {
523 Assert(module);
524 Assert(module->hw);
525
526 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
527
528 #if (SAMD20 || SAMD21 || SAMD09 || SAMD10 || SAMD11 || SAML21 || SAML22 || \
529 SAMDA1 || SAMC20 || SAMC21 || SAMR30 || SAMHA1)
530 /* Workaround */
531 /*
532 * Below code instead i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
533 * CMD=0x3 clears all interrupts, so to keep the result similar
534 * PREC is cleared if it was set
535 */
536 if (i2c_hw->INTFLAG.bit.PREC) {
537 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC;
538 }
539 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_AMATCH;
540 #else
541 /* Normal operation */
542 i2c_hw->CTRLB.reg = SERCOM_I2CS_CTRLB_CMD(0x3);
543 #endif
544 return;
545 }
546 ///@endcond
547
548 /**
549 * \brief Gets the I<SUP>2</SUP>C slave default configurations
550 *
551 * This will initialize the configuration structure to known default values.
552 *
553 * The default configuration is as follows:
554 * - Disable SCL low timeout
555 * - 300ns - 600ns SDA hold time
556 * - Buffer timeout = 65535
557 * - Address with mask
558 * - Address = 0
559 * - Address mask = 0 (one single address)
560 * - General call address disabled
561 * - Address nack disabled if the interrupt driver is used
562 * - GCLK generator 0
563 * - Do not run in standby
564 * - PINMUX_DEFAULT for SERCOM pads
565 *
566 * Those default configuration only available if the device supports it:
567 * - Not using 10-bit addressing
568 * - Standard-mode and Fast-mode transfer speed
569 * - SCL stretch disabled
570 * - Slave SCL low extend time-out disabled
571 *
572 * \param[out] config Pointer to configuration structure to be initialized
573 */
i2c_slave_get_config_defaults(struct i2c_slave_config * const config)574 static inline void i2c_slave_get_config_defaults(
575 struct i2c_slave_config *const config)
576 {
577 /*Sanity check argument */
578 Assert(config);
579 config->enable_scl_low_timeout = false;
580 config->sda_hold_time = I2C_SLAVE_SDA_HOLD_TIME_300NS_600NS;
581 config->buffer_timeout = 65535;
582 config->address_mode = I2C_SLAVE_ADDRESS_MODE_MASK;
583 config->address = 0;
584 config->address_mask = 0;
585 #ifdef FEATURE_I2C_10_BIT_ADDRESS
586 config->ten_bit_address = false;
587 #endif
588 config->enable_general_call_address = false;
589 #ifdef FEATURE_I2C_FAST_MODE_PLUS_AND_HIGH_SPEED
590 config->transfer_speed = I2C_SLAVE_SPEED_STANDARD_AND_FAST;
591 #endif
592 #if I2C_SLAVE_CALLBACK_MODE == true
593 config->enable_nack_on_address = false;
594 #endif
595 config->generator_source = GCLK_GENERATOR_0;
596 config->run_in_standby = false;
597 config->pinmux_pad0 = PINMUX_DEFAULT;
598 config->pinmux_pad1 = PINMUX_DEFAULT;
599 config->scl_low_timeout = false;
600 #ifdef FEATURE_I2C_SCL_STRETCH_MODE
601 config->scl_stretch_only_after_ack_bit = false;
602 #endif
603 #ifdef FEATURE_I2C_SCL_EXTEND_TIMEOUT
604 config->slave_scl_low_extend_timeout = false;
605 #endif
606 }
607
608 enum status_code i2c_slave_init(struct i2c_slave_module *const module,
609 Sercom *const hw,
610 const struct i2c_slave_config *const config);
611
612 /**
613 * \brief Enables the I<SUP>2</SUP>C module
614 *
615 * This will enable the requested I<SUP>2</SUP>C module.
616 *
617 * \param[in] module Pointer to the software module struct
618 */
i2c_slave_enable(const struct i2c_slave_module * const module)619 static inline void i2c_slave_enable(
620 const struct i2c_slave_module *const module)
621 {
622 /* Sanity check of arguments */
623 Assert(module);
624 Assert(module->hw);
625
626 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
627
628 #if I2C_SLAVE_CALLBACK_MODE == true
629 /* Enable global interrupt for module */
630 system_interrupt_enable(_sercom_get_interrupt_vector(module->hw));
631 #endif
632
633 /* Wait for module to sync */
634 _i2c_slave_wait_for_sync(module);
635
636 /* Enable module */
637 i2c_hw->CTRLA.reg |= SERCOM_I2CS_CTRLA_ENABLE;
638 }
639
640
641 /**
642 * \brief Disables the I<SUP>2</SUP>C module
643 *
644 * This will disable the I<SUP>2</SUP>C module specified in the provided software module
645 * structure.
646 *
647 * \param[in] module Pointer to the software module struct
648 */
i2c_slave_disable(const struct i2c_slave_module * const module)649 static inline void i2c_slave_disable(
650 const struct i2c_slave_module *const module)
651 {
652 /* Sanity check of arguments */
653 Assert(module);
654 Assert(module->hw);
655
656 SercomI2cs *const i2c_hw = &(module->hw->I2CS);
657
658 #if I2C_SLAVE_CALLBACK_MODE == true
659 /* Disable interrupts */
660 i2c_hw->INTENCLR.reg = SERCOM_I2CS_INTENSET_PREC |
661 SERCOM_I2CS_INTENSET_AMATCH | SERCOM_I2CS_INTENSET_DRDY;
662
663 /* Clear interrupt flags */
664 i2c_hw->INTFLAG.reg = SERCOM_I2CS_INTFLAG_PREC | SERCOM_I2CS_INTFLAG_AMATCH |
665 SERCOM_I2CS_INTFLAG_DRDY;
666
667 /* Disable global interrupt for module */
668 system_interrupt_disable(_sercom_get_interrupt_vector(module->hw));
669 #endif
670
671 /* Wait for module to sync */
672 _i2c_slave_wait_for_sync(module);
673
674 /* Disable module */
675 i2c_hw->CTRLA.reg &= ~SERCOM_I2CS_CTRLA_ENABLE;
676 }
677
678 void i2c_slave_reset(
679 struct i2c_slave_module *const module);
680
681 /** @} */
682
683 /**
684 * \name Read and Write
685 * @{
686 */
687
688 enum status_code i2c_slave_write_packet_wait(
689 struct i2c_slave_module *const module,
690 struct i2c_slave_packet *const packet);
691 enum status_code i2c_slave_read_packet_wait(
692 struct i2c_slave_module *const module,
693 struct i2c_slave_packet *const packet);
694 enum i2c_slave_direction i2c_slave_get_direction_wait(
695 struct i2c_slave_module *const module);
696
697 /** @} */
698
699 /**
700 * \name Status Management
701 * @{
702 */
703 uint32_t i2c_slave_get_status(
704 struct i2c_slave_module *const module);
705 void i2c_slave_clear_status(
706 struct i2c_slave_module *const module,
707 uint32_t status_flags);
708 /** @} */
709
710 #ifdef FEATURE_I2C_DMA_SUPPORT
711 /**
712 * \name SERCOM I2C slave with DMA Interfaces
713 * @{
714 */
715
716 /**
717 * \brief Read SERCOM I<SUP>2</SUP>C interrupt status.
718 *
719 * Read I<SUP>2</SUP>C interrupt status for DMA transfer.
720 *
721 * \param[in,out] module Pointer to the driver instance to lock
722 *
723 */
i2c_slave_dma_read_interrupt_status(struct i2c_slave_module * const module)724 static inline uint8_t i2c_slave_dma_read_interrupt_status(struct i2c_slave_module *const module)
725 {
726 return (uint8_t)module->hw->I2CS.INTFLAG.reg;
727 }
728
729 /**
730 * \brief Write SERCOM I<SUP>2</SUP>C interrupt status.
731 *
732 * Write I<SUP>2</SUP>C interrupt status for DMA transfer.
733 *
734 * \param[in,out] module Pointer to the driver instance to lock
735 * \param[in] flag Interrupt flag status
736 *
737 */
i2c_slave_dma_write_interrupt_status(struct i2c_slave_module * const module,uint8_t flag)738 static inline void i2c_slave_dma_write_interrupt_status(struct i2c_slave_module *const module,
739 uint8_t flag)
740 {
741 module->hw->I2CS.INTFLAG.reg = flag;
742 }
743
744 /** @} */
745 #endif
746
747 /** @} */
748
749 #ifdef __cplusplus
750 }
751 #endif
752
753 #endif /* I2C_SLAVE_H_INCLUDED */
754