基于aithinker_Ai-M6X_SDK的I2C封装

[复制链接]
查看398 | 回复5 | 2023-11-29 13:06:07 | 显示全部楼层 |阅读模式



                               
登录/注册后可看大图


目前aithinker_Ai-M6X_SDK 使用I2C 不是很友好。所以参考其他封装代码修改成适配SDK的封装代码。

Wire.h


  1. #pragma once

  2. // #include "bouffalo_sdk.h"
  3. #include "bflb_gpio.h"
  4. #include "bl616_gpio.h"
  5. #include "bl616_glb.h"
  6. #include "bl616_glb_gpio.h"
  7. #include "../../drivers/lhal/include/hardware/i2c_reg.h"
  8. #include "bflb_i2c.h"
  9. #define lowByte(w) ((uint8_t) ((w) & 0xff))
  10. #define highByte(w) ((uint8_t) ((w) >> 8))

  11. bool getWireTimeoutFlag();
  12. bool clearWireTimeoutFlag();
  13. void setWireTimeout(int timeout, bool reset_on_timeout);
  14. void onRequest(void (*callback)());
  15. void onReceive(void (*callback)(int));
  16. void setClock(int clockFrequency);
  17. int readI2c();
  18. int available();
  19. int write_len(uint8_t *str, int len);
  20. int write_str(uint8_t *str);
  21. int write_char(unsigned char value);
  22. void endTransmission_stop(bool stop);
  23. void endTransmission();
  24. void beginTransmission(unsigned char addr);
  25. int requestFrom_stop(unsigned char addr, int quantity, bool stop);
  26. int requestFrom(unsigned char addr, int quantity);
  27. void end();
  28. void begin_addr(unsigned char addr);
  29. void begin();
复制代码
Wire.c

  1. #include "Wire.h"

  2. #define PUT_UINT32_LE(field, value)            \
  3.     do {                                       \
  4.         (field)[0] = (uint8_t)((value) >> 0);  \
  5.         (field)[1] = (uint8_t)((value) >> 8);  \
  6.         (field)[2] = (uint8_t)((value) >> 16); \
  7.         (field)[3] = (uint8_t)((value) >> 24); \
  8.     } while (0)



  9. struct bflb_device_s *i2c0;
  10. uint8_t rbuf[128];
  11. int available_count;
  12. int indexi2c;
  13. int wire_timeout;
  14. bool wire_timeout_flag;

  15. void board_i2c_pinmux_init(void)
  16. {
  17.     GLB_GPIO_Type pinlist[] = {
  18.         GLB_GPIO_PIN_30,
  19.         GLB_GPIO_PIN_31
  20.     };
  21.     GLB_GPIO_Func_Init(GPIO_FUN_I2C0, pinlist, 2);
  22. }

  23. bool bflb_i2c_isend(struct bflb_device_s *dev)
  24. {
  25.     uint32_t regval;
  26.     uint32_t reg_base;

  27.     reg_base = dev->reg_base;

  28.     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);

  29.     if (regval & I2C_END_INT) {
  30.         return true;
  31.     }

  32.     return false;
  33. }

  34. bool bflb_i2c_isnak(struct bflb_device_s *dev)
  35. {
  36.     uint32_t regval;
  37.     uint32_t reg_base;

  38.     reg_base = dev->reg_base;

  39.     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);

  40.     if (regval & I2C_NAK_INT) {
  41.         return true;
  42.     }

  43.     return false;
  44. }

  45. bool bflb_i2c_isbusy(struct bflb_device_s *dev)
  46. {
  47.     uint32_t regval;
  48.     uint32_t reg_base;

  49.     reg_base = dev->reg_base;

  50.     regval = getreg32(reg_base + I2C_BUS_BUSY_OFFSET);

  51.     if (regval & I2C_STS_I2C_BUS_BUSY) {
  52.         return true;
  53.     }

  54.     return false;
  55. }

  56. void bflb_i2c_enable(struct bflb_device_s *dev)
  57. {
  58.     uint32_t regval;
  59.     uint32_t reg_base;

  60.     reg_base = dev->reg_base;

  61.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
  62.     regval |= I2C_CR_I2C_M_EN;
  63.     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
  64. }

  65. bool bflb_i2c_isenable(struct bflb_device_s *dev)
  66. {
  67.     uint32_t regval;
  68.     uint32_t reg_base;

  69.     reg_base = dev->reg_base;

  70.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
  71.     if (regval & I2C_CR_I2C_M_EN) {
  72.         return true;
  73.     }

  74.     return false;
  75. }

  76. void bflb_i2c_disable(struct bflb_device_s *dev)
  77. {
  78.     uint32_t regval;
  79.     uint32_t reg_base;

  80.     reg_base = dev->reg_base;

  81.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
  82.     regval &= ~I2C_CR_I2C_M_EN;
  83.     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
  84.     /* Clear I2C fifo */
  85.     regval = getreg32(reg_base + I2C_FIFO_CONFIG_0_OFFSET);
  86.     regval |= I2C_TX_FIFO_CLR;
  87.     regval |= I2C_RX_FIFO_CLR;
  88.     putreg32(regval, reg_base + I2C_FIFO_CONFIG_0_OFFSET);
  89.     /* Clear I2C interrupt status */
  90.     regval = getreg32(reg_base + I2C_INT_STS_OFFSET);
  91.     regval |= I2C_CR_I2C_END_CLR;
  92.     regval |= I2C_CR_I2C_NAK_CLR;
  93.     regval |= I2C_CR_I2C_ARB_CLR;
  94.     putreg32(regval, reg_base + I2C_INT_STS_OFFSET);
  95. }


  96. void bflb_i2c_addr_config(struct bflb_device_s *dev, uint16_t slaveaddr, uint16_t subaddr, uint8_t subaddr_size, bool is_addr_10bit)
  97. {
  98.     uint32_t regval;
  99.     uint32_t reg_base;

  100.     reg_base = dev->reg_base;

  101.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);

  102.     if (subaddr_size > 0) {
  103.         regval |= I2C_CR_I2C_SUB_ADDR_EN;
  104.         regval &= ~I2C_CR_I2C_SUB_ADDR_BC_MASK;
  105.         regval |= ((subaddr_size - 1) << I2C_CR_I2C_SUB_ADDR_BC_SHIFT);
  106.     } else {
  107.         regval &= ~I2C_CR_I2C_SUB_ADDR_EN;
  108.     }

  109.     regval &= ~I2C_CR_I2C_SLV_ADDR_MASK;
  110.     regval |= (slaveaddr << I2C_CR_I2C_SLV_ADDR_SHIFT);
  111. #if !defined(BL602) && !defined(BL702)
  112.     if (is_addr_10bit) {
  113.         regval |= I2C_CR_I2C_10B_ADDR_EN;
  114.     } else {
  115.         regval &= ~I2C_CR_I2C_10B_ADDR_EN;
  116.     }
  117. #endif
  118.     putreg32(subaddr, reg_base + I2C_SUB_ADDR_OFFSET);
  119.     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
  120. }

  121. void bflb_i2c_set_datalen(struct bflb_device_s *dev, uint16_t data_len)
  122. {
  123.     uint32_t regval;
  124.     uint32_t reg_base;

  125.     reg_base = dev->reg_base;

  126.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);
  127.     regval &= ~I2C_CR_I2C_PKT_LEN_MASK;
  128.     regval |= ((data_len - 1) << I2C_CR_I2C_PKT_LEN_SHIFT) & I2C_CR_I2C_PKT_LEN_MASK;
  129.     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
  130. }


  131. void bflb_i2c_set_dir(struct bflb_device_s *dev, bool is_in)
  132. {
  133.     uint32_t regval;
  134.     uint32_t reg_base;

  135.     reg_base = dev->reg_base;

  136.     regval = getreg32(reg_base + I2C_CONFIG_OFFSET);

  137.     if (is_in) {
  138.         regval |= I2C_CR_I2C_PKT_DIR;
  139.     } else {
  140.         regval &= ~I2C_CR_I2C_PKT_DIR;
  141.     }
  142.     putreg32(regval, reg_base + I2C_CONFIG_OFFSET);
  143. }


  144. int bflb_i2c_write_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len, uint32_t timeout)
  145. {
  146.     uint32_t reg_base;
  147.     uint32_t temp = 0;
  148.     uint8_t *tmp_buf;
  149.     uint64_t start_time;

  150.     reg_base = dev->reg_base;
  151.     tmp_buf = data;
  152.     while (len >= 4) {
  153.         for (uint8_t i = 0; i < 4; i++) {
  154.             temp += (tmp_buf[i] << ((i % 4) * 8));
  155.         }
  156.         tmp_buf += 4;
  157.         len -= 4;
  158.         start_time = bflb_mtimer_get_time_ms();
  159.         while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
  160.             if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  161.                 return -ETIMEDOUT;
  162.             }
  163.         }
  164.         putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
  165.         if (!bflb_i2c_isenable(dev)) {
  166.             bflb_i2c_enable(dev);
  167.         }
  168.         temp = 0;
  169.     }

  170.     if (len > 0) {
  171.         for (uint8_t i = 0; i < len; i++) {
  172.             temp += (tmp_buf[i] << ((i % 4) * 8));
  173.         }
  174.         start_time = bflb_mtimer_get_time_ms();
  175.         while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_TX_FIFO_CNT_MASK) == 0) {
  176.             if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  177.                 return -ETIMEDOUT;
  178.             }
  179.         }
  180.         putreg32(temp, reg_base + I2C_FIFO_WDATA_OFFSET);
  181.         if (!bflb_i2c_isenable(dev)) {
  182.             bflb_i2c_enable(dev);
  183.         }
  184.     }

  185.     start_time = bflb_mtimer_get_time_ms();
  186.     while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev) || bflb_i2c_isnak(dev)) {
  187.         if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  188.             return -ETIMEDOUT;
  189.         }
  190.     }
  191.     bflb_i2c_disable(dev);

  192.     return 0;
  193. }


  194. int bflb_i2c_read_bytes(struct bflb_device_s *dev, uint8_t *data, uint32_t len, uint32_t timeout)
  195. {
  196.     uint32_t reg_base;
  197.     uint32_t temp = 0;
  198.     uint8_t *tmp_buf;
  199.     uint64_t start_time;

  200.     reg_base = dev->reg_base;
  201.     tmp_buf = data;

  202.     bflb_i2c_enable(dev);

  203.     while (len >= 4) {
  204.         start_time = bflb_mtimer_get_time_ms();
  205.         while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
  206.             if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  207.                 return -ETIMEDOUT;
  208.             }
  209.         }
  210.         temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);
  211.         PUT_UINT32_LE(tmp_buf, temp);
  212.         tmp_buf += 4;
  213.         len -= 4;
  214.     }

  215.     if (len > 0) {
  216.         start_time = bflb_mtimer_get_time_ms();
  217.         while ((getreg32(reg_base + I2C_FIFO_CONFIG_1_OFFSET) & I2C_RX_FIFO_CNT_MASK) == 0) {
  218.             if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  219.                 return -ETIMEDOUT;
  220.             }
  221.         }
  222.         temp = getreg32(reg_base + I2C_FIFO_RDATA_OFFSET);

  223.         for (uint8_t i = 0; i < len; i++) {
  224.             tmp_buf[i] = (temp >> (i * 8)) & 0xff;
  225.         }
  226.     }

  227.     start_time = bflb_mtimer_get_time_ms();
  228.     while (bflb_i2c_isbusy(dev) || !bflb_i2c_isend(dev)) {
  229.         if ((bflb_mtimer_get_time_ms() - start_time) > timeout) {
  230.             return -ETIMEDOUT;
  231.         }
  232.     }
  233.     bflb_i2c_disable(dev);

  234.     return 0;
  235. }



  236. /*
  237. * address: the 7-bit slave address (optional); if not specified, join the bus as a controller device.
  238. */
  239. void begin_addr(unsigned char addr) {
  240.     wire_timeout = 100;
  241.     wire_timeout_flag = false;
  242.     board_i2c_pinmux_init();
  243.     i2c0 = bflb_device_get_by_name("i2c0");
  244.     bflb_i2c_init(i2c0, 50000);
  245. }

  246. void begin() {
  247.     wire_timeout = 100;
  248.     wire_timeout_flag = false;
  249.     board_i2c_pinmux_init();
  250.     i2c0 = bflb_device_get_by_name("i2c0");
  251.     bflb_i2c_init(i2c0, 50000);
  252. }

  253. void end() {
  254.     bflb_i2c_deinit(i2c0);
  255. }
  256. /*
  257. * address: the 7-bit slave address of the device to request bytes from.
  258. *
  259. * quantity: the number of bytes to request.
  260. *
  261. * stop: true or false. true will send a stop message after the request, releasing the bus.
  262. * False will continually send a restart after the request, keeping the connection active.
  263. */

  264. int requestFrom_stop(unsigned char addr, int quantity, bool stop) {
  265.     indexi2c = 0;
  266.     bflb_i2c_disable(i2c0);
  267.     bflb_i2c_enable(i2c0);
  268.     bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
  269.     bflb_i2c_set_datalen(i2c0,quantity);
  270.     bflb_i2c_set_dir(i2c0, 1);
  271.     bflb_i2c_read_bytes(i2c0, rbuf,quantity,wire_timeout);
  272.     available_count = quantity;
  273.     if(true == stop){
  274.         bflb_i2c_disable(i2c0);
  275.     }
  276.     return 0;
  277. }

  278. int requestFrom(unsigned char addr, int quantity) {
  279.     indexi2c = 0;
  280.     bflb_i2c_disable(i2c0);
  281.     bflb_i2c_enable(i2c0);
  282.     bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
  283.     bflb_i2c_set_datalen(i2c0,quantity);
  284.     bflb_i2c_set_dir(i2c0, 1);
  285.     bflb_i2c_read_bytes(i2c0, rbuf,quantity,wire_timeout);
  286.     available_count = quantity;
  287.     return 0;
  288. }

  289. /*
  290. * address: the 7-bit address of the device to transmit to.
  291. */
  292. void beginTransmission(unsigned char addr) {
  293.     //bflb_i2c_enable(i2c0);
  294.     bflb_i2c_addr_config(i2c0, addr, 0, 0, false);
  295.     bflb_i2c_set_dir(i2c0, 0);
  296. }

  297. /*
  298. * stop: true or false. True will send a stop message, releasing the bus after transmission.
  299. * False will send a restart, keeping the connection active.
  300. *
  301. * Returns
  302. * 0: success.
  303. * 1: data too long to fit in transmit buffer.
  304. * 2: received NACK on transmit of address.
  305. * 3: received NACK on transmit of data.
  306. * 4: other error.
  307. * 5: timeout
  308. */

  309. void endTransmission_stop(bool stop) {
  310.     bflb_i2c_disable(i2c0);
  311. }

  312. void endTransmission() {
  313.     bflb_i2c_disable(i2c0);

  314. }

  315. /*
  316. * Description
  317. * This function writes data from a peripheral device in response to a request from
  318. * a controller device, or queues bytes for transmission from a controller to
  319. * peripheral device (in-between calls to beginTransmission() and endTransmission()).
  320. * Syntax
  321. * Wire.write(value) Wire.write(string) Wire.write(data, length)
  322. * Parameters
  323. * value: a value to send as a single byte.
  324. * string: a string to send as a series of bytes.
  325. * data: an array of data to send as bytes.
  326. * length: the number of bytes to transmit.
  327. * Returns
  328. * The number of bytes written (reading this number is optional).
  329. */
  330. int write_char(unsigned char value) {
  331.     bflb_i2c_set_datalen(i2c0, 1);
  332.     bflb_i2c_write_bytes(i2c0, &value, 1,wire_timeout);
  333.   return 0;
  334. }
  335. int write_str(uint8_t *str) {
  336.     bflb_i2c_set_datalen(i2c0, strlen((const char*)str));
  337.     bflb_i2c_write_bytes(i2c0, str, strlen((const char*)str),wire_timeout);
  338.   return 0;
  339. }
  340. int write_len(uint8_t *str, int len) {
  341.     bflb_i2c_set_datalen(i2c0, len);
  342.     int ret = bflb_i2c_write_bytes(i2c0, str, len,wire_timeout);
  343.   return ret;
  344. }

  345. /*
  346. * Description
  347. * This function returns the number of bytes available for retrieval with read().
  348. * This function should be called on a controller device after a call to
  349. * requestFrom() or on a peripheral inside the onReceive() handler.
  350. * available() inherits from the Stream utility class.
  351. */

  352. int available() {
  353.     return available_count;
  354. }

  355. /*
  356. * Description
  357. * This function reads a byte that was transmitted from a peripheral device to
  358. * a controller device after a call to requestFrom() or was transmitted from a
  359. * controller device to a peripheral device. read() inherits from the Stream utility class.
  360. * Syntax
  361. * Wire.read()
  362. * Parameters
  363. * None.
  364. * Returns
  365. * The next byte received.
  366. */

  367. int readI2c() {
  368.     unsigned char ret;
  369.     if(available_count){
  370.         available_count--;
  371.         ret = rbuf[indexi2c];
  372.         indexi2c++;
  373.         return ret;
  374.     }
  375.     return 0;
  376. }

  377. /*
  378. * Description
  379. * This function modifies the clock frequency for I2C communication.
  380. * I2C peripheral devices have no minimum working clock frequency,
  381. * however 100KHz is usually the baseline.
  382. * Syntax
  383. * Wire.setClock(clockFrequency)
  384. * Parameters
  385. * clockFrequency: the value (in Hertz) of the desired communication clock.
  386. * Accepted values are 100000 (standard mode) and 400000 (fast mode).
  387. * Some processors also support 10000 (low speed mode), 1000000 (fast mode plus)
  388. * and 3400000 (high speed mode). Please refer to the specific processor documentation
  389. * to make sure the desired mode is supported.
  390. * Returns
  391. * None.
  392. */
  393. void setClock(int clockFrequency) {
  394.     bflb_i2c_deinit(i2c0);
  395.     bflb_i2c_init(i2c0, clockFrequency);
  396. }

  397. /*
  398. * Description
  399. * This function registers a function to be called when a peripheral device receives
  400. * a transmission from a controller device.
  401. * Syntax
  402. * Wire.onReceive(handler)
  403. * Parameters
  404. * handler: the function to be called when the peripheral device receives data;
  405. * this should take a single int parameter (the number of bytes read from the controller
  406. * device) and return nothing.
  407. * Returns
  408. * None.
  409. */
  410. void onReceive(void (*callback)(int)) {
  411.     //we not support slave mode yet
  412. }

  413. /*
  414. * Description
  415. * This function registers a function to be called when a controller device requests data from a peripheral device.
  416. * Syntax
  417. * Wire.onRequest(handler)
  418. * Parameters
  419. * handler: the function to be called, takes no parameters and returns nothing.
  420. * Returns
  421. * None.
  422. */
  423. void onRequest(void (*callback)()) {
  424.     //we not support slave mode yet
  425. }

  426. /*
  427. * Description
  428. * Sets the timeout for Wire transmissions in master mode.
  429. * Syntax
  430. * Wire.setWireTimeout(timeout, reset_on_timeout)
  431. * Wire.setWireTimeout()
  432. * Parameters
  433. * timeout a timeout: timeout in microseconds, if zero then timeout checking is disabled
  434. * reset_on_timeout: if true then Wire hardware will be automatically reset on timeout
  435. * When this function is called without parameters, a default timeout is configured that
  436. * should be sufficient to prevent lockups in a typical single-master configuration.
  437. * Returns
  438. * None.
  439. */
  440. void setWireTimeout(int timeout, bool reset_on_timeout) {
  441.     wire_timeout = timeout;
  442.     wire_timeout_flag = true;
  443. }

  444. /* Description
  445. * Clears the timeout flag.
  446. * Timeouts might not be enabled by default. See the documentation for Wire.setWireTimeout()
  447. * for more information on how to configure timeouts and how they work.
  448. * Syntax
  449. * Wire.clearTimeout()
  450. * Parameters
  451. * None.
  452. * Returns
  453. * bool: The current value of the flag
  454. */
  455. bool clearWireTimeoutFlag() {
  456.     wire_timeout_flag = false;
  457.   return true;
  458. }

  459. /*
  460. * Description
  461. * Checks whether a timeout has occured since the last time the flag was cleared.
  462. * This flag is set is set whenever a timeout occurs and cleared when Wire.clearWireTimeoutFlag()
  463. * is called, or when the timeout is changed using Wire.setWireTimeout().
  464. * Syntax
  465. * Wire.getWireTimeoutFlag()
  466. * Parameters
  467. * None.
  468. * Returns
  469. * bool: The current value of the flag
  470. */

  471. bool getWireTimeoutFlag() {
  472.   return wire_timeout_flag;
  473. }

复制代码
代码可以直接放到项目里面引用。



目前arduino 平台已经支持 I2C 的常用功能能。这里多了一种选择。
回复

使用道具 举报

干簧管 | 2023-11-29 13:17:44 | 显示全部楼层
回复

使用道具 举报

lazy | 2023-11-30 09:31:27 | 显示全部楼层
回复

使用道具 举报

lazy | 2023-11-30 09:40:11 | 显示全部楼层
这种干货帖子再多点
回复 支持 反对

使用道具 举报

1084504793 | 2024-1-2 15:51:42 | 显示全部楼层
回复

使用道具 举报

lazy | 2024-1-4 08:49:23 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则