i2c_master.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. /**
  2. * \file
  3. *
  4. * \brief I2C Master Driver for SAMB
  5. *
  6. * Copyright (C) 2015-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 "i2c_master.h"
  47. #if I2C_MASTER_CALLBACK_MODE == true
  48. # include "i2c_master_interrupt.h"
  49. #endif
  50. /**
  51. * \brief Gets the I<SUP>2</SUP>C master default configurations
  52. *
  53. * Use to initialize the configuration structure to known default values.
  54. *
  55. * The default configuration is as follows:
  56. * - Baudrate 100KHz
  57. * - Clock sourc I2C_CLK_INPUT_3
  58. * - Clock divider = 0x10
  59. * - Pinmux pad0 PINMUX_LP_GPIO_8_MUX2_I2C0_SDA
  60. * - Pinmux pad1 PINMUX_LP_GPIO_9_MUX2_I2C0_SCK
  61. *
  62. * \param[out] config Pointer to configuration structure to be initiated
  63. */
  64. void i2c_master_get_config_defaults(
  65. struct i2c_master_config *const config)
  66. {
  67. /* Sanity check */
  68. Assert(config);
  69. config->clock_source = I2C_CLK_INPUT_3;
  70. config->clock_divider = 0x10;
  71. config->pin_number_pad0 = PIN_LP_GPIO_8;
  72. config->pin_number_pad1 = PIN_LP_GPIO_9;
  73. config->pinmux_sel_pad0 = MUX_LP_GPIO_8_I2C0_SDA;
  74. config->pinmux_sel_pad1 = MUX_LP_GPIO_9_I2C0_SCL;
  75. }
  76. #if !defined(__DOXYGEN__)
  77. /**
  78. * \internal Sets configurations to module
  79. *
  80. * \param[out] module Pointer to software module structure
  81. * \param[in] config Configuration structure with configurations to set
  82. *
  83. */
  84. static void _i2c_master_set_config(
  85. struct i2c_master_module *const module,
  86. const struct i2c_master_config *const config)
  87. {
  88. /* Sanity check */
  89. Assert(module);
  90. Assert(module->hw);
  91. Assert(config);
  92. I2c *const i2c_module = (module->hw);
  93. /* Set the pinmux for this i2c module. */
  94. gpio_pinmux_cofiguration(config->pin_number_pad0, (uint16_t)(config->pinmux_sel_pad0));
  95. gpio_pinmux_cofiguration(config->pin_number_pad1, (uint16_t)(config->pinmux_sel_pad1));
  96. /* Set clock. */
  97. i2c_module->CLOCK_SOURCE_SELECT.reg = config->clock_source;
  98. i2c_module->I2C_CLK_DIVIDER.reg = I2C_CLK_DIVIDER_I2C_DIVIDE_RATIO(config->clock_divider);
  99. /* Enable master mode. */
  100. i2c_module->I2C_MASTER_MODE.reg = I2C_MASTER_MODE_MASTER_ENABLE_1;
  101. }
  102. #endif /* __DOXYGEN__ */
  103. /**
  104. * \brief Initializes the requested I<SUP>2</SUP>C hardware module
  105. *
  106. * Initializes the I<SUP>2</SUP>C master device requested and sets the provided
  107. * software module struct. Run this function before any further use of
  108. * the driver.
  109. *
  110. * \param[out] module Pointer to software module struct
  111. * \param[in] config Pointer to the configuration struct
  112. *
  113. * \return Status of initialization.
  114. * \retval STATUS_OK Module initiated correctly
  115. * \retval STATUS_ERR_INVALID_ARG Invalid argument in module or config structure.
  116. * \retval STATUS_ERR_ALREADY_INITIALIZED If the Pinmux is not a valid one for I2C signals.
  117. *
  118. */
  119. enum status_code i2c_master_init(
  120. struct i2c_master_module *const module,
  121. I2c *const hw,
  122. const struct i2c_master_config *const config)
  123. {
  124. /* Sanity check */
  125. Assert(module);
  126. Assert(module->hw);
  127. Assert(config);
  128. module->hw = hw;
  129. /* Sanity check arguments. */
  130. if ((module == NULL) || (config == NULL))
  131. return STATUS_ERR_INVALID_ARG;
  132. i2c_disable(module->hw);
  133. if (module->hw == I2C0) {
  134. system_peripheral_reset(PERIPHERAL_I2C0_CORE);
  135. } else if (module->hw == I2C1) {
  136. system_peripheral_reset(PERIPHERAL_I2C1_CORE);
  137. } else {
  138. return STATUS_ERR_INVALID_ARG;
  139. }
  140. #if I2C_MASTER_CALLBACK_MODE == true
  141. /* Initialize values in module. */
  142. module->registered_callback = 0;
  143. module->enabled_callback = 0;
  144. module->buffer_length = 0;
  145. module->buffer_remaining = 0;
  146. module->status = STATUS_OK;
  147. module->buffer = NULL;
  148. _i2c_instances = (void*)module;
  149. if (module->hw == I2C0) {
  150. system_register_isr(RAM_ISR_TABLE_I2CRX0_INDEX, (uint32_t)_i2c_master_isr_handler);
  151. system_register_isr(RAM_ISR_TABLE_I2CTX0_INDEX, (uint32_t)_i2c_master_isr_handler);
  152. NVIC_EnableIRQ(I2C0_RX_IRQn);
  153. NVIC_EnableIRQ(I2C0_TX_IRQn);
  154. } else if (module->hw == I2C1) {
  155. system_register_isr(RAM_ISR_TABLE_I2CRX1_INDEX, (uint32_t)_i2c_master_isr_handler);
  156. system_register_isr(RAM_ISR_TABLE_I2CTX1_INDEX, (uint32_t)_i2c_master_isr_handler);
  157. NVIC_EnableIRQ(I2C1_RX_IRQn);
  158. NVIC_EnableIRQ(I2C1_TX_IRQn);
  159. }
  160. #endif
  161. /* Set config and return status. */
  162. _i2c_master_set_config(module, config);
  163. return STATUS_OK;
  164. }
  165. /**
  166. * \internal
  167. * Starts blocking read operation.
  168. *
  169. * \param[in,out] module Pointer to software module struct
  170. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  171. *
  172. * \return Status of reading packet.
  173. * \retval STATUS_OK The packet was read successfully
  174. * \retval STATUS_ERR_TIMEOUT If no response was given within
  175. * specified timeout period
  176. * \retval STATUS_ERR_DENIED If error on bus
  177. * \retval STATUS_ERR_PACKET_COLLISION If arbitration is lost
  178. * \retval STATUS_ERR_BAD_ADDRESS If slave is busy, or no slave
  179. * acknowledged the address
  180. */
  181. static enum status_code _i2c_master_read_packet(
  182. struct i2c_master_module *const module,
  183. struct i2c_master_packet *const packet)
  184. {
  185. /* Sanity check */
  186. Assert(module);
  187. Assert(module->hw);
  188. Assert(config);
  189. uint16_t counter = 0;
  190. uint32_t status = 0;
  191. I2c *const i2c_module = (module->hw);
  192. uint16_t length = packet->data_length;
  193. if (length == 0) {
  194. return STATUS_ERR_INVALID_ARG;
  195. }
  196. i2c_wait_for_idle(i2c_module);
  197. /* Flush the FIFO */
  198. i2c_module->I2C_FLUSH.reg = 1;
  199. /* Enable I2C on bus (start condition). */
  200. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_1;
  201. /* Address I2C slave in case of Master mode enabled. */
  202. i2c_module->TRANSMIT_DATA.reg = I2C_TRANSMIT_DATA_ADDRESS_FLAG_1 |
  203. (packet->address << 1) | I2C_TRANSFER_READ;
  204. /* Now check whether the core has sent the data out and free the bus. */
  205. while (!(status & I2C_TRANSMIT_STATUS_TX_FIFO_EMPTY)) {
  206. status = i2c_module->TRANSMIT_STATUS.reg;
  207. }
  208. do {
  209. /* Send stop condition. */
  210. if ((!module->no_stop) && (counter == (length - 1))) {
  211. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_0;
  212. }
  213. status = i2c_module->RECEIVE_STATUS.reg;
  214. if (status & I2C_RECEIVE_STATUS_RX_FIFO_NOT_EMPTY)
  215. packet->data[counter++] = i2c_module->RECEIVE_DATA.reg;
  216. } while (counter < length);
  217. return STATUS_OK;
  218. }
  219. /**
  220. * \brief Reads data packet from slave
  221. *
  222. * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
  223. * bus and sends a stop condition when finished.
  224. *
  225. * \note This will stall the device from any other operation. For
  226. * interrupt-driven operation, see \ref i2c_master_read_packet_job.
  227. *
  228. * \param[in,out] module Pointer to software module struct
  229. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  230. *
  231. * \return Status of reading packet.
  232. * \retval STATUS_OK The packet was read successfully
  233. * \retval STATUS_ERR_INVALID_ARG Invalid argument in module or config strucuture
  234. * specified timeout period
  235. * \retval STATUS_BUSY If module has a pending request.
  236. */
  237. enum status_code i2c_master_read_packet_wait(
  238. struct i2c_master_module *const module,
  239. struct i2c_master_packet *const packet)
  240. {
  241. /* Sanity check */
  242. Assert(module);
  243. Assert(module->hw);
  244. Assert(packet);
  245. if((module == NULL) || (packet == NULL))
  246. return STATUS_ERR_INVALID_ARG;
  247. #if I2C_MASTER_CALLBACK_MODE == true
  248. /* Check if the I2C module is busy with a job. */
  249. if (module->buffer_remaining > 0) {
  250. return STATUS_BUSY;
  251. }
  252. #endif
  253. module->no_stop = false;
  254. return _i2c_master_read_packet(module, packet);
  255. }
  256. /**
  257. * \brief Reads data packet from slave without sending a stop condition when done
  258. *
  259. * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
  260. * bus without sending a stop condition when done, thus retaining ownership of
  261. * the bus when done. To end the transaction, a
  262. * \ref i2c_master_read_packet_wait "read" or
  263. * \ref i2c_master_write_packet_wait "write" with stop condition must be
  264. * performed.
  265. *
  266. * \note This will stall the device from any other operation. For
  267. * interrupt-driven operation, see \ref i2c_master_read_packet_job.
  268. *
  269. * \param[in,out] module Pointer to software module struct
  270. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  271. *
  272. * \return Status of reading packet.
  273. * \retval STATUS_OK The packet was read successfully
  274. * \retval STATUS_ERR_INVALID_ARG Invalid argument in module or config strucuture
  275. * specified timeout period
  276. * \retval STATUS_BUSY If module has a pending request.
  277. */
  278. enum status_code i2c_master_read_packet_wait_no_stop(
  279. struct i2c_master_module *const module,
  280. struct i2c_master_packet *const packet)
  281. {
  282. /* Sanity check */
  283. Assert(module);
  284. Assert(module->hw);
  285. Assert(packet);
  286. if((module == NULL) || (packet == NULL))
  287. return STATUS_ERR_INVALID_ARG;
  288. #if I2C_MASTER_CALLBACK_MODE == true
  289. /* Check if the I2C module is busy with a job. */
  290. if (module->buffer_remaining > 0) {
  291. return STATUS_BUSY;
  292. }
  293. #endif
  294. module->no_stop = true;
  295. return _i2c_master_read_packet(module, packet);
  296. }
  297. /**
  298. * \internal
  299. * Starts blocking write operation.
  300. *
  301. * \param[in,out] module Pointer to software module struct
  302. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  303. *
  304. * \return Status of write packet.
  305. * \retval STATUS_OK The packet was write successfully
  306. */
  307. static enum status_code _i2c_master_write_packet(
  308. struct i2c_master_module *const module,
  309. struct i2c_master_packet *const packet)
  310. {
  311. /* Sanity check */
  312. Assert(module);
  313. Assert(module->hw);
  314. Assert(packet);
  315. I2c *const i2c_module = (module->hw);
  316. uint16_t counter = 0;
  317. uint32_t status = 0;
  318. uint16_t length = packet->data_length;
  319. i2c_wait_for_idle(i2c_module);
  320. /* Flush the FIFO */
  321. i2c_module->I2C_FLUSH.reg = 1;
  322. /* Enable I2C on bus (start condition) */
  323. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_1;
  324. /* Address I2C slave in case of Master mode enabled */
  325. i2c_module->TRANSMIT_DATA.reg = I2C_TRANSMIT_DATA_ADDRESS_FLAG_1 |
  326. ((packet->address) << 1) | I2C_TRANSFER_WRITE;
  327. do {
  328. status = i2c_module->TRANSMIT_STATUS.reg;
  329. if (status & I2C_TRANSMIT_STATUS_TX_FIFO_NOT_FULL_Msk) {
  330. i2c_module->TRANSMIT_DATA.reg = packet->data[counter++];
  331. }
  332. } while (counter < length);
  333. /* Now check whether the core has sent the data out and free the bus */
  334. while (!(status & I2C_TRANSMIT_STATUS_TX_FIFO_EMPTY)) {
  335. status = i2c_module->TRANSMIT_STATUS.reg;
  336. }
  337. /* Send stop condition */
  338. if (!module->no_stop) {
  339. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_0;
  340. }
  341. return STATUS_OK;
  342. }
  343. /**
  344. * \brief Writes data packet to slave
  345. *
  346. * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
  347. * and sends a stop condition when finished.
  348. *
  349. * \note This will stall the device from any other operation. For
  350. * interrupt-driven operation, see \ref i2c_master_read_packet_job.
  351. *
  352. * \param[in,out] module Pointer to software module struct
  353. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  354. *
  355. * \return Status of write packet.
  356. * \retval STATUS_OK The packet was written successfully
  357. * \retval STATUS_ERR_INVALID_ARG Invalid argument in module or packet structure
  358. * specified timeout period
  359. * \retval STATUS_BUSY If module has a pending request.
  360. */
  361. enum status_code i2c_master_write_packet_wait(
  362. struct i2c_master_module *const module,
  363. struct i2c_master_packet *const packet)
  364. {
  365. /* Sanity check arguments. */
  366. Assert(module);
  367. Assert(module->hw);
  368. Assert(packet);
  369. if ((module == NULL) || (packet == NULL)) {
  370. return STATUS_ERR_INVALID_ARG;
  371. }
  372. #if I2C_MASTER_CALLBACK_MODE == true
  373. /* Check if the I2C module is busy with a job. */
  374. if (module->buffer_remaining > 0) {
  375. return STATUS_BUSY;
  376. }
  377. #endif
  378. module->no_stop = false;
  379. return _i2c_master_write_packet(module, packet);
  380. }
  381. /**
  382. * \brief Writes data packet to slave without sending a stop condition when done
  383. *
  384. * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
  385. * without sending a stop condition, thus retaining ownership of the bus when
  386. * done. To end the transaction, a \ref i2c_master_read_packet_wait "read" or
  387. * \ref i2c_master_write_packet_wait "write" with stop condition or sending a
  388. * stop with the \ref i2c_master_send_stop function must be performed.
  389. *
  390. * \note This will stall the device from any other operation. For
  391. * interrupt-driven operation, see \ref i2c_master_read_packet_job.
  392. *
  393. * \param[in,out] module Pointer to software module struct
  394. * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
  395. *
  396. * \return Status of write packet.
  397. * \retval STATUS_OK The packet was written successfully
  398. * \retval STATUS_ERR_INVALID_ARG Invalid argument in module or config structure
  399. * specified timeout period
  400. * \retval STATUS_BUSY If module has a pending request.
  401. */
  402. enum status_code i2c_master_write_packet_wait_no_stop(
  403. struct i2c_master_module *const module,
  404. struct i2c_master_packet *const packet)
  405. {
  406. /* Sanity check */
  407. Assert(module);
  408. Assert(module->hw);
  409. Assert(packet);
  410. if((module == NULL) || (packet == NULL)) {
  411. return STATUS_ERR_INVALID_ARG;
  412. }
  413. #if I2C_MASTER_CALLBACK_MODE == true
  414. /* Check if the I2C module is busy with a job */
  415. if (module->buffer_remaining > 0) {
  416. return STATUS_BUSY;
  417. }
  418. #endif
  419. module->no_stop = true;
  420. return _i2c_master_write_packet(module, packet);
  421. }
  422. /**
  423. * \brief Sends stop condition on bus
  424. *
  425. * Sends a stop condition on bus.
  426. *
  427. * \note This function can only be used after the
  428. * \ref i2c_master_write_packet_wait_no_stop function. If a stop condition
  429. * is to be sent after a read, the \ref i2c_master_read_packet_wait
  430. * function must be used.
  431. *
  432. * \param[in,out] module Pointer to the software instance struct
  433. */
  434. void i2c_master_send_stop(struct i2c_master_module *const module)
  435. {
  436. /* Sanity check */
  437. Assert(module);
  438. Assert(module->hw);
  439. I2c *const i2c_module = (module->hw);
  440. /* Send stop command */
  441. i2c_wait_for_idle(i2c_module);
  442. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_0;
  443. }
  444. /**
  445. * \brief Sends start condition on bus
  446. *
  447. * Sends a start condition on bus.
  448. *
  449. * \note This function can only be used after the
  450. * \ref i2c_master_write_packet_wait_no_stop function. If a stop condition
  451. * is to be sent after a read, the \ref i2c_master_read_packet_wait
  452. * function must be used.
  453. *
  454. * \param[in,out] module Pointer to the software instance struct
  455. */
  456. void i2c_master_send_start(struct i2c_master_module *const module)
  457. {
  458. I2c *const i2c_module = (module->hw);
  459. i2c_wait_for_idle(i2c_module);
  460. /* Send start command */
  461. i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_1;
  462. }
  463. /**
  464. * \brief Reads one byte data from slave
  465. *
  466. * \param[in,out] module Pointer to software module struct
  467. * \param[out] byte Read one byte data to slave
  468. *
  469. * \return Status of reading byte.
  470. * \retval STATUS_OK The packet was read successfully
  471. */
  472. enum status_code i2c_master_read_byte(
  473. struct i2c_master_module *const module,
  474. uint8_t *byte)
  475. {
  476. I2c *const i2c_module = (module->hw);
  477. /* Read a byte from slave. */
  478. i2c_wait_for_idle(i2c_module);
  479. *byte = i2c_module->RECEIVE_DATA.bit.RX_BYTE;
  480. return STATUS_OK;
  481. }
  482. /**
  483. * \brief Write Address & command to slave
  484. *
  485. * \param[in,out] module Pointer to software module struct
  486. * \param[in] byte Address of slave
  487. * \param[in] byte command 0 - Write, 1 - Read
  488. *
  489. * \return Status of writing byte.
  490. * \retval STATUS_OK The Address and command was written successfully
  491. */
  492. enum status_code i2c_master_write_address(
  493. struct i2c_master_module *const module,
  494. uint8_t address,
  495. uint8_t command)
  496. {
  497. I2c *const i2c_module = (module->hw);
  498. /* Write byte to slave. */
  499. i2c_wait_for_idle(i2c_module);
  500. i2c_module->TRANSMIT_DATA.reg = I2C_TRANSMIT_DATA_ADDRESS_FLAG_1 |
  501. (address << 1) | command;
  502. return STATUS_OK;
  503. }
  504. /**
  505. * \brief Write one byte data to slave
  506. *
  507. * \param[in,out] module Pointer to software module struct
  508. * \param[in] byte Send one byte data to slave
  509. *
  510. * \return Status of writing byte.
  511. * \retval STATUS_OK One byte was written successfully
  512. */
  513. enum status_code i2c_master_write_byte(
  514. struct i2c_master_module *const module,
  515. uint8_t byte)
  516. {
  517. I2c *const i2c_module = (module->hw);
  518. /* Write byte to slave. */
  519. i2c_wait_for_idle(i2c_module);
  520. i2c_module->TRANSMIT_DATA.reg = (uint16_t)I2C_TRANSMIT_DATA_TX_DATA(byte);
  521. return STATUS_OK;
  522. }