usart.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /**
  2. * \file
  3. *
  4. * \brief SAM SERCOM USART Driver
  5. *
  6. * Copyright (C) 2012-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. #include "usart.h"
  47. #include <pinmux.h>
  48. #if USART_CALLBACK_MODE == true
  49. # include "usart_interrupt.h"
  50. #endif
  51. /**
  52. * \internal
  53. * Set Configuration of the USART module
  54. */
  55. static enum status_code _usart_set_config(
  56. struct usart_module *const module,
  57. const struct usart_config *const config)
  58. {
  59. /* Sanity check arguments */
  60. Assert(module);
  61. Assert(module->hw);
  62. /* Get a pointer to the hardware module instance */
  63. SercomUsart *const usart_hw = &(module->hw->USART);
  64. /* Index for generic clock */
  65. uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
  66. uint32_t gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
  67. /* Cache new register values to minimize the number of register writes */
  68. uint32_t ctrla = 0;
  69. uint32_t ctrlb = 0;
  70. #ifdef FEATURE_USART_ISO7816
  71. uint32_t ctrlc = 0;
  72. #endif
  73. uint16_t baud = 0;
  74. uint32_t transfer_mode;
  75. enum sercom_asynchronous_operation_mode mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
  76. enum sercom_asynchronous_sample_num sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
  77. #ifdef FEATURE_USART_OVER_SAMPLE
  78. switch (config->sample_rate) {
  79. case USART_SAMPLE_RATE_16X_ARITHMETIC:
  80. mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
  81. sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
  82. break;
  83. case USART_SAMPLE_RATE_8X_ARITHMETIC:
  84. mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
  85. sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
  86. break;
  87. case USART_SAMPLE_RATE_3X_ARITHMETIC:
  88. mode = SERCOM_ASYNC_OPERATION_MODE_ARITHMETIC;
  89. sample_num = SERCOM_ASYNC_SAMPLE_NUM_3;
  90. break;
  91. case USART_SAMPLE_RATE_16X_FRACTIONAL:
  92. mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
  93. sample_num = SERCOM_ASYNC_SAMPLE_NUM_16;
  94. break;
  95. case USART_SAMPLE_RATE_8X_FRACTIONAL:
  96. mode = SERCOM_ASYNC_OPERATION_MODE_FRACTIONAL;
  97. sample_num = SERCOM_ASYNC_SAMPLE_NUM_8;
  98. break;
  99. }
  100. #endif
  101. /* Set data order, internal muxing, and clock polarity */
  102. ctrla = (uint32_t)config->data_order |
  103. (uint32_t)config->mux_setting |
  104. #ifdef FEATURE_USART_OVER_SAMPLE
  105. config->sample_adjustment |
  106. config->sample_rate |
  107. #endif
  108. #ifdef FEATURE_USART_IMMEDIATE_BUFFER_OVERFLOW_NOTIFICATION
  109. (config->immediate_buffer_overflow_notification << SERCOM_USART_CTRLA_IBON_Pos) |
  110. #endif
  111. (config->clock_polarity_inverted << SERCOM_USART_CTRLA_CPOL_Pos);
  112. enum status_code status_code = STATUS_OK;
  113. transfer_mode = (uint32_t)config->transfer_mode;
  114. #ifdef FEATURE_USART_ISO7816
  115. if(config->iso7816_config.enabled) {
  116. transfer_mode = config->iso7816_config.protocol_t;
  117. }
  118. #endif
  119. /* Get baud value from mode and clock */
  120. #ifdef FEATURE_USART_ISO7816
  121. if(config->iso7816_config.enabled) {
  122. baud = config->baudrate;
  123. } else {
  124. #endif
  125. switch (transfer_mode)
  126. {
  127. case USART_TRANSFER_SYNCHRONOUSLY:
  128. if (!config->use_external_clock) {
  129. status_code = _sercom_get_sync_baud_val(config->baudrate,
  130. system_gclk_chan_get_hz(gclk_index), &baud);
  131. }
  132. break;
  133. case USART_TRANSFER_ASYNCHRONOUSLY:
  134. if (config->use_external_clock) {
  135. status_code =
  136. _sercom_get_async_baud_val(config->baudrate,
  137. config->ext_clock_freq, &baud, mode, sample_num);
  138. } else {
  139. status_code =
  140. _sercom_get_async_baud_val(config->baudrate,
  141. system_gclk_chan_get_hz(gclk_index), &baud, mode, sample_num);
  142. }
  143. break;
  144. }
  145. /* Check if calculating the baudrate failed */
  146. if (status_code != STATUS_OK) {
  147. /* Abort */
  148. return status_code;
  149. }
  150. #ifdef FEATURE_USART_ISO7816
  151. }
  152. #endif
  153. #ifdef FEATURE_USART_IRDA
  154. if(config->encoding_format_enable) {
  155. usart_hw->RXPL.reg = config->receive_pulse_length;
  156. }
  157. #endif
  158. /* Wait until synchronization is complete */
  159. _usart_wait_for_sync(module);
  160. /*Set baud val */
  161. usart_hw->BAUD.reg = baud;
  162. /* Set sample mode */
  163. ctrla |= transfer_mode;
  164. if (config->use_external_clock == false) {
  165. ctrla |= SERCOM_USART_CTRLA_MODE(0x1);
  166. }
  167. else {
  168. ctrla |= SERCOM_USART_CTRLA_MODE(0x0);
  169. }
  170. /* Set stopbits and enable transceivers */
  171. ctrlb =
  172. #ifdef FEATURE_USART_IRDA
  173. (config->encoding_format_enable << SERCOM_USART_CTRLB_ENC_Pos) |
  174. #endif
  175. #ifdef FEATURE_USART_START_FRAME_DECTION
  176. (config->start_frame_detection_enable << SERCOM_USART_CTRLB_SFDE_Pos) |
  177. #endif
  178. #ifdef FEATURE_USART_COLLISION_DECTION
  179. (config->collision_detection_enable << SERCOM_USART_CTRLB_COLDEN_Pos) |
  180. #endif
  181. (config->receiver_enable << SERCOM_USART_CTRLB_RXEN_Pos) |
  182. (config->transmitter_enable << SERCOM_USART_CTRLB_TXEN_Pos);
  183. #ifdef FEATURE_USART_ISO7816
  184. if(config->iso7816_config.enabled) {
  185. ctrla |= SERCOM_USART_CTRLA_FORM(0x07);
  186. if (config->iso7816_config.enable_inverse) {
  187. ctrla |= SERCOM_USART_CTRLA_TXINV | SERCOM_USART_CTRLA_RXINV;
  188. }
  189. ctrlb |= USART_CHARACTER_SIZE_8BIT;
  190. switch(config->iso7816_config.protocol_t) {
  191. case ISO7816_PROTOCOL_T_0:
  192. ctrlb |= (uint32_t)config->stopbits;
  193. ctrlc |= SERCOM_USART_CTRLC_GTIME(config->iso7816_config.guard_time) | \
  194. (config->iso7816_config.inhibit_nack) | \
  195. (config->iso7816_config.successive_recv_nack) | \
  196. SERCOM_USART_CTRLC_MAXITER(config->iso7816_config.max_iterations);
  197. break;
  198. case ISO7816_PROTOCOL_T_1:
  199. ctrlb |= USART_STOPBITS_1;
  200. break;
  201. }
  202. } else {
  203. #endif
  204. ctrlb |= (uint32_t)config->stopbits;
  205. ctrlb |= (uint32_t)config->character_size;
  206. /* Check parity mode bits */
  207. if (config->parity != USART_PARITY_NONE) {
  208. ctrla |= SERCOM_USART_CTRLA_FORM(1);
  209. ctrlb |= config->parity;
  210. } else {
  211. #ifdef FEATURE_USART_LIN_SLAVE
  212. if(config->lin_slave_enable) {
  213. ctrla |= SERCOM_USART_CTRLA_FORM(0x4);
  214. } else {
  215. ctrla |= SERCOM_USART_CTRLA_FORM(0);
  216. }
  217. #else
  218. ctrla |= SERCOM_USART_CTRLA_FORM(0);
  219. #endif
  220. }
  221. #ifdef FEATURE_USART_ISO7816
  222. }
  223. #endif
  224. #ifdef FEATURE_USART_LIN_MASTER
  225. usart_hw->CTRLC.reg = ((usart_hw->CTRLC.reg) & SERCOM_USART_CTRLC_GTIME_Msk)
  226. | config->lin_header_delay
  227. | config->lin_break_length;
  228. if (config->lin_node != LIN_INVALID_MODE) {
  229. ctrla &= ~(SERCOM_USART_CTRLA_FORM(0xf));
  230. ctrla |= config->lin_node;
  231. }
  232. #endif
  233. /* Set whether module should run in standby. */
  234. if (config->run_in_standby || system_is_debugger_present()) {
  235. ctrla |= SERCOM_USART_CTRLA_RUNSTDBY;
  236. }
  237. /* Wait until synchronization is complete */
  238. _usart_wait_for_sync(module);
  239. /* Write configuration to CTRLB */
  240. usart_hw->CTRLB.reg = ctrlb;
  241. /* Wait until synchronization is complete */
  242. _usart_wait_for_sync(module);
  243. /* Write configuration to CTRLA */
  244. usart_hw->CTRLA.reg = ctrla;
  245. #ifdef FEATURE_USART_RS485
  246. if ((usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_FORM_Msk) != \
  247. SERCOM_USART_CTRLA_FORM(0x07)) {
  248. usart_hw->CTRLC.reg &= ~(SERCOM_USART_CTRLC_GTIME(0x7));
  249. usart_hw->CTRLC.reg |= SERCOM_USART_CTRLC_GTIME(config->rs485_guard_time);
  250. }
  251. #endif
  252. #ifdef FEATURE_USART_ISO7816
  253. if(config->iso7816_config.enabled) {
  254. _usart_wait_for_sync(module);
  255. usart_hw->CTRLC.reg = ctrlc;
  256. }
  257. #endif
  258. return STATUS_OK;
  259. }
  260. /**
  261. * \brief Initializes the device
  262. *
  263. * Initializes the USART device based on the setting specified in the
  264. * configuration struct.
  265. *
  266. * \param[out] module Pointer to USART device
  267. * \param[in] hw Pointer to USART hardware instance
  268. * \param[in] config Pointer to configuration struct
  269. *
  270. * \return Status of the initialization.
  271. *
  272. * \retval STATUS_OK The initialization was successful
  273. * \retval STATUS_BUSY The USART module is busy
  274. * resetting
  275. * \retval STATUS_ERR_DENIED The USART has not been disabled in
  276. * advance of initialization
  277. * \retval STATUS_ERR_INVALID_ARG The configuration struct contains
  278. * invalid configuration
  279. * \retval STATUS_ERR_ALREADY_INITIALIZED The SERCOM instance has already been
  280. * initialized with different clock
  281. * configuration
  282. * \retval STATUS_ERR_BAUD_UNAVAILABLE The BAUD rate given by the
  283. * configuration
  284. * struct cannot be reached with
  285. * the current clock configuration
  286. */
  287. enum status_code usart_init(
  288. struct usart_module *const module,
  289. Sercom *const hw,
  290. const struct usart_config *const config)
  291. {
  292. /* Sanity check arguments */
  293. Assert(module);
  294. Assert(hw);
  295. Assert(config);
  296. enum status_code status_code = STATUS_OK;
  297. /* Assign module pointer to software instance struct */
  298. module->hw = hw;
  299. /* Get a pointer to the hardware module instance */
  300. SercomUsart *const usart_hw = &(module->hw->USART);
  301. uint32_t sercom_index = _sercom_get_sercom_inst_index(module->hw);
  302. uint32_t pm_index, gclk_index;
  303. #if (SAML22) || (SAMC20)
  304. pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
  305. gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
  306. #elif (SAML21) || (SAMR30)
  307. if (sercom_index == 5) {
  308. pm_index = MCLK_APBDMASK_SERCOM5_Pos;
  309. gclk_index = SERCOM5_GCLK_ID_CORE;
  310. } else {
  311. pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
  312. gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
  313. }
  314. #elif (SAMC21)
  315. pm_index = sercom_index + MCLK_APBCMASK_SERCOM0_Pos;
  316. if (sercom_index == 5){
  317. gclk_index = SERCOM5_GCLK_ID_CORE;
  318. } else {
  319. gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
  320. }
  321. #else
  322. pm_index = sercom_index + PM_APBCMASK_SERCOM0_Pos;
  323. gclk_index = sercom_index + SERCOM0_GCLK_ID_CORE;
  324. #endif
  325. if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_SWRST) {
  326. /* The module is busy resetting itself */
  327. return STATUS_BUSY;
  328. }
  329. if (usart_hw->CTRLA.reg & SERCOM_USART_CTRLA_ENABLE) {
  330. /* Check the module is enabled */
  331. return STATUS_ERR_DENIED;
  332. }
  333. /* Turn on module in PM */
  334. #if (SAML21) || (SAMR30)
  335. if (sercom_index == 5) {
  336. system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBD, 1 << pm_index);
  337. } else {
  338. system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
  339. }
  340. #else
  341. system_apb_clock_set_mask(SYSTEM_CLOCK_APB_APBC, 1 << pm_index);
  342. #endif
  343. /* Set up the GCLK for the module */
  344. struct system_gclk_chan_config gclk_chan_conf;
  345. system_gclk_chan_get_config_defaults(&gclk_chan_conf);
  346. gclk_chan_conf.source_generator = config->generator_source;
  347. system_gclk_chan_set_config(gclk_index, &gclk_chan_conf);
  348. system_gclk_chan_enable(gclk_index);
  349. sercom_set_gclk_generator(config->generator_source, false);
  350. /* Set character size */
  351. module->character_size = config->character_size;
  352. /* Set transmitter and receiver status */
  353. module->receiver_enabled = config->receiver_enable;
  354. module->transmitter_enabled = config->transmitter_enable;
  355. #ifdef FEATURE_USART_LIN_SLAVE
  356. module->lin_slave_enabled = config->lin_slave_enable;
  357. #endif
  358. #ifdef FEATURE_USART_START_FRAME_DECTION
  359. module->start_frame_detection_enabled = config->start_frame_detection_enable;
  360. #endif
  361. #ifdef FEATURE_USART_ISO7816
  362. module->iso7816_mode_enabled = config->iso7816_config.enabled;
  363. #endif
  364. /* Set configuration according to the config struct */
  365. status_code = _usart_set_config(module, config);
  366. if(status_code != STATUS_OK) {
  367. return status_code;
  368. }
  369. struct system_pinmux_config pin_conf;
  370. system_pinmux_get_config_defaults(&pin_conf);
  371. pin_conf.direction = SYSTEM_PINMUX_PIN_DIR_INPUT;
  372. pin_conf.input_pull = SYSTEM_PINMUX_PIN_PULL_NONE;
  373. uint32_t pad_pinmuxes[] = {
  374. config->pinmux_pad0, config->pinmux_pad1,
  375. config->pinmux_pad2, config->pinmux_pad3
  376. };
  377. /* Configure the SERCOM pins according to the user configuration */
  378. for (uint8_t pad = 0; pad < 4; pad++) {
  379. uint32_t current_pinmux = pad_pinmuxes[pad];
  380. if (current_pinmux == PINMUX_DEFAULT) {
  381. current_pinmux = _sercom_get_default_pad(hw, pad);
  382. }
  383. if (current_pinmux != PINMUX_UNUSED) {
  384. pin_conf.mux_position = current_pinmux & 0xFFFF;
  385. system_pinmux_pin_set_config(current_pinmux >> 16, &pin_conf);
  386. }
  387. }
  388. #if USART_CALLBACK_MODE == true
  389. /* Initialize parameters */
  390. for (uint32_t i = 0; i < USART_CALLBACK_N; i++) {
  391. module->callback[i] = NULL;
  392. }
  393. module->tx_buffer_ptr = NULL;
  394. module->rx_buffer_ptr = NULL;
  395. module->remaining_tx_buffer_length = 0x0000;
  396. module->remaining_rx_buffer_length = 0x0000;
  397. module->callback_reg_mask = 0x00;
  398. module->callback_enable_mask = 0x00;
  399. module->rx_status = STATUS_OK;
  400. module->tx_status = STATUS_OK;
  401. /* Set interrupt handler and register USART software module struct in
  402. * look-up table */
  403. uint8_t instance_index = _sercom_get_sercom_inst_index(module->hw);
  404. _sercom_set_handler(instance_index, _usart_interrupt_handler);
  405. _sercom_instances[instance_index] = module;
  406. #endif
  407. return status_code;
  408. }
  409. /**
  410. * \brief Transmit a character via the USART
  411. *
  412. * This blocking function will transmit a single character via the
  413. * USART.
  414. *
  415. * \param[in] module Pointer to the software instance struct
  416. * \param[in] tx_data Data to transfer
  417. *
  418. * \return Status of the operation.
  419. * \retval STATUS_OK If the operation was completed
  420. * \retval STATUS_BUSY If the operation was not completed, due to the USART
  421. * module being busy
  422. * \retval STATUS_ERR_DENIED If the transmitter is not enabled
  423. */
  424. enum status_code usart_write_wait(
  425. struct usart_module *const module,
  426. const uint16_t tx_data)
  427. {
  428. /* Sanity check arguments */
  429. Assert(module);
  430. Assert(module->hw);
  431. /* Get a pointer to the hardware module instance */
  432. SercomUsart *const usart_hw = &(module->hw->USART);
  433. /* Check that the transmitter is enabled */
  434. if (!(module->transmitter_enabled)) {
  435. return STATUS_ERR_DENIED;
  436. }
  437. #if USART_CALLBACK_MODE == true
  438. /* Check if the USART is busy doing asynchronous operation. */
  439. if (module->remaining_tx_buffer_length > 0) {
  440. return STATUS_BUSY;
  441. }
  442. #else
  443. /* Check if USART is ready for new data */
  444. if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
  445. /* Return error code */
  446. return STATUS_BUSY;
  447. }
  448. #endif
  449. /* Wait until synchronization is complete */
  450. _usart_wait_for_sync(module);
  451. /* Write data to USART module */
  452. usart_hw->DATA.reg = tx_data;
  453. while (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)) {
  454. /* Wait until data is sent */
  455. }
  456. return STATUS_OK;
  457. }
  458. /**
  459. * \brief Receive a character via the USART
  460. *
  461. * This blocking function will receive a character via the USART.
  462. *
  463. * \param[in] module Pointer to the software instance struct
  464. * \param[out] rx_data Pointer to received data
  465. *
  466. * \return Status of the operation.
  467. * \retval STATUS_OK If the operation was completed
  468. * \retval STATUS_BUSY If the operation was not completed,
  469. * due to the USART module being busy
  470. * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
  471. * due to configuration mismatch between USART
  472. * and the sender
  473. * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
  474. * due to the baudrate being too low or the
  475. * system frequency being too high
  476. * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due to
  477. * data being corrupted
  478. * \retval STATUS_ERR_DENIED If the receiver is not enabled
  479. */
  480. enum status_code usart_read_wait(
  481. struct usart_module *const module,
  482. uint16_t *const rx_data)
  483. {
  484. /* Sanity check arguments */
  485. Assert(module);
  486. Assert(module->hw);
  487. /* Error variable */
  488. uint8_t error_code;
  489. /* Get a pointer to the hardware module instance */
  490. SercomUsart *const usart_hw = &(module->hw->USART);
  491. /* Check that the receiver is enabled */
  492. if (!(module->receiver_enabled)) {
  493. return STATUS_ERR_DENIED;
  494. }
  495. #if USART_CALLBACK_MODE == true
  496. /* Check if the USART is busy doing asynchronous operation. */
  497. if (module->remaining_rx_buffer_length > 0) {
  498. return STATUS_BUSY;
  499. }
  500. #endif
  501. /* Check if USART has new data */
  502. if (!(usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
  503. /* Return error code */
  504. return STATUS_BUSY;
  505. }
  506. /* Wait until synchronization is complete */
  507. _usart_wait_for_sync(module);
  508. /* Read out the status code and mask away all but the 3 LSBs*/
  509. error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
  510. /* Check if an error has occurred during the receiving */
  511. if (error_code) {
  512. /* Check which error occurred */
  513. if (error_code & SERCOM_USART_STATUS_FERR) {
  514. /* Clear flag by writing a 1 to it and
  515. * return with an error code */
  516. usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
  517. return STATUS_ERR_BAD_FORMAT;
  518. } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
  519. /* Clear flag by writing a 1 to it and
  520. * return with an error code */
  521. usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
  522. return STATUS_ERR_OVERFLOW;
  523. } else if (error_code & SERCOM_USART_STATUS_PERR) {
  524. /* Clear flag by writing a 1 to it and
  525. * return with an error code */
  526. usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
  527. return STATUS_ERR_BAD_DATA;
  528. }
  529. #ifdef FEATURE_USART_LIN_SLAVE
  530. else if (error_code & SERCOM_USART_STATUS_ISF) {
  531. /* Clear flag by writing 1 to it and
  532. * return with an error code */
  533. usart_hw->STATUS.reg = SERCOM_USART_STATUS_ISF;
  534. return STATUS_ERR_PROTOCOL;
  535. }
  536. #endif
  537. #ifdef FEATURE_USART_COLLISION_DECTION
  538. else if (error_code & SERCOM_USART_STATUS_COLL) {
  539. /* Clear flag by writing 1 to it
  540. * return with an error code */
  541. usart_hw->STATUS.reg = SERCOM_USART_STATUS_COLL;
  542. return STATUS_ERR_PACKET_COLLISION;
  543. }
  544. #endif
  545. }
  546. /* Read data from USART module */
  547. *rx_data = usart_hw->DATA.reg;
  548. return STATUS_OK;
  549. }
  550. /**
  551. * \brief Transmit a buffer of characters via the USART
  552. *
  553. * This blocking function will transmit a block of \c length characters
  554. * via the USART.
  555. *
  556. * \note Using this function in combination with the interrupt (\c _job) functions is
  557. * not recommended as it has no functionality to check if there is an
  558. * ongoing interrupt driven operation running or not.
  559. *
  560. * \param[in] module Pointer to USART software instance struct
  561. * \param[in] tx_data Pointer to data to transmit
  562. * \param[in] length Number of characters to transmit
  563. *
  564. * \note If using 9-bit data, the array that *tx_data point to should be defined
  565. * as uint16_t array and should be casted to uint8_t* pointer. Because it
  566. * is an address pointer, the highest byte is not discarded. For example:
  567. * \code
  568. #define TX_LEN 3
  569. uint16_t tx_buf[TX_LEN] = {0x0111, 0x0022, 0x0133};
  570. usart_write_buffer_wait(&module, (uint8_t*)tx_buf, TX_LEN);
  571. \endcode
  572. *
  573. * \return Status of the operation.
  574. * \retval STATUS_OK If operation was completed
  575. * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to invalid
  576. * arguments
  577. * \retval STATUS_ERR_TIMEOUT If operation was not completed, due to USART
  578. * module timing out
  579. * \retval STATUS_ERR_DENIED If the transmitter is not enabled
  580. */
  581. enum status_code usart_write_buffer_wait(
  582. struct usart_module *const module,
  583. const uint8_t *tx_data,
  584. uint16_t length)
  585. {
  586. /* Sanity check arguments */
  587. Assert(module);
  588. Assert(module->hw);
  589. /* Check if the buffer length is valid */
  590. if (length == 0) {
  591. return STATUS_ERR_INVALID_ARG;
  592. }
  593. /* Check that the transmitter is enabled */
  594. if (!(module->transmitter_enabled)) {
  595. return STATUS_ERR_DENIED;
  596. }
  597. /* Get a pointer to the hardware module instance */
  598. SercomUsart *const usart_hw = &(module->hw->USART);
  599. /* Wait until synchronization is complete */
  600. _usart_wait_for_sync(module);
  601. uint16_t tx_pos = 0;
  602. /* Blocks while buffer is being transferred */
  603. while (length--) {
  604. /* Wait for the USART to be ready for new data and abort
  605. * operation if it doesn't get ready within the timeout*/
  606. for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
  607. if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_DRE) {
  608. break;
  609. } else if (i == USART_TIMEOUT) {
  610. return STATUS_ERR_TIMEOUT;
  611. }
  612. }
  613. /* Data to send is at least 8 bits long */
  614. uint16_t data_to_send = tx_data[tx_pos++];
  615. /* Check if the character size exceeds 8 bit */
  616. if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
  617. data_to_send |= (tx_data[tx_pos++] << 8);
  618. }
  619. /* Send the data through the USART module */
  620. usart_write_wait(module, data_to_send);
  621. }
  622. /* Wait until Transmit is complete or timeout */
  623. for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
  624. if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_TXC) {
  625. break;
  626. } else if (i == USART_TIMEOUT) {
  627. return STATUS_ERR_TIMEOUT;
  628. }
  629. }
  630. return STATUS_OK;
  631. }
  632. /**
  633. * \brief Receive a buffer of \c length characters via the USART
  634. *
  635. * This blocking function will receive a block of \c length characters
  636. * via the USART.
  637. *
  638. * \note Using this function in combination with the interrupt (\c *_job)
  639. * functions is not recommended as it has no functionality to check if
  640. * there is an ongoing interrupt driven operation running or not.
  641. *
  642. * \param[in] module Pointer to USART software instance struct
  643. * \param[out] rx_data Pointer to receive buffer
  644. * \param[in] length Number of characters to receive
  645. *
  646. * \note If using 9-bit data, the array that *rx_data point to should be defined
  647. * as uint16_t array and should be casted to uint8_t* pointer. Because it
  648. * is an address pointer, the highest byte is not discarded. For example:
  649. * \code
  650. #define RX_LEN 3
  651. uint16_t rx_buf[RX_LEN] = {0x0,};
  652. usart_read_buffer_wait(&module, (uint8_t*)rx_buf, RX_LEN);
  653. \endcode
  654. *
  655. * \return Status of the operation.
  656. * \retval STATUS_OK If operation was completed
  657. * \retval STATUS_ERR_INVALID_ARG If operation was not completed, due to an
  658. * invalid argument being supplied
  659. * \retval STATUS_ERR_TIMEOUT If operation was not completed, due
  660. * to USART module timing out
  661. * \retval STATUS_ERR_BAD_FORMAT If the operation was not completed,
  662. * due to a configuration mismatch
  663. * between USART and the sender
  664. * \retval STATUS_ERR_BAD_OVERFLOW If the operation was not completed,
  665. * due to the baudrate being too low or the
  666. * system frequency being too high
  667. * \retval STATUS_ERR_BAD_DATA If the operation was not completed, due
  668. * to data being corrupted
  669. * \retval STATUS_ERR_DENIED If the receiver is not enabled
  670. */
  671. enum status_code usart_read_buffer_wait(
  672. struct usart_module *const module,
  673. uint8_t *rx_data,
  674. uint16_t length)
  675. {
  676. /* Sanity check arguments */
  677. Assert(module);
  678. Assert(module->hw);
  679. /* Check if the buffer length is valid */
  680. if (length == 0) {
  681. return STATUS_ERR_INVALID_ARG;
  682. }
  683. /* Check that the receiver is enabled */
  684. if (!(module->receiver_enabled)) {
  685. return STATUS_ERR_DENIED;
  686. }
  687. /* Get a pointer to the hardware module instance */
  688. SercomUsart *const usart_hw = &(module->hw->USART);
  689. uint16_t rx_pos = 0;
  690. /* Blocks while buffer is being received */
  691. while (length--) {
  692. /* Wait for the USART to have new data and abort operation if it
  693. * doesn't get ready within the timeout*/
  694. for (uint32_t i = 0; i <= USART_TIMEOUT; i++) {
  695. if (usart_hw->INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) {
  696. break;
  697. } else if (i == USART_TIMEOUT) {
  698. return STATUS_ERR_TIMEOUT;
  699. }
  700. }
  701. enum status_code retval;
  702. uint16_t received_data = 0;
  703. retval = usart_read_wait(module, &received_data);
  704. if (retval != STATUS_OK) {
  705. /* Overflow, abort */
  706. return retval;
  707. }
  708. /* Read value will be at least 8-bits long */
  709. rx_data[rx_pos++] = received_data;
  710. /* If 9-bit data, write next received byte to the buffer */
  711. if (module->character_size == USART_CHARACTER_SIZE_9BIT) {
  712. rx_data[rx_pos++] = (received_data >> 8);
  713. }
  714. }
  715. return STATUS_OK;
  716. }