1 /*
2  * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024-12-30     CDT          first version
9  */
10 
11 /*
12  * 程序清单:这是 I2C 设备使用例程。
13  * 例程导出了 i2c_sample 到控制终端。
14  * 命令调用格式:i2c_sample
15  * 命令解释:
16  * 程序功能:查找I2C模块,读写I2C设备。
17  * 注意:测试要用逻辑分析仪或示波器抓取信号
18 */
19 
20 #include <rtthread.h>
21 #include <rtdevice.h>
22 #include <board.h>
23 
24 /*
25  * to readout/write  from/into i2c device, user could use this macro to choice
26  * either rt_i2c_master_send & rt_i2c_master_recv or rt_i2c_transfer
27 */
28 #if defined(RT_USING_I2C)
29 
30 #define USING_RT_I2C_TRANSFER
31 
32 /* defined EEPROM */
33 #if defined(HC32F472) || defined(HC32F460) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8) || \
34     defined(HC32F334)
35     #define EE_DEV_ADDR                 0x50
36     #define EE_TEST_PAGE_CNT            8       // Test 8 pages
37 #endif
38 
39 /* define EEPROM hardware */
40 #if defined(HC32F472) || defined(HC32F460) || defined(HC32F448) || defined(HC32F4A8) || defined(HC32F334)
41     #define EE24C256
42 #elif defined(HC32F4A0)
43     #define EE24C02
44 #endif
45 
46 #if defined (EE24C1024)
47     #define EE_PAGE_SIZE                256 // 24C1024
48     #define EE_WORD_ADR_SIZE            2   // 2 word addr
49 #elif defined (EE24C256)
50     #define EE_PAGE_SIZE                64  // 24C256
51     #define EE_WORD_ADR_SIZE            2   // 2 word addr
52 #elif defined (EE24C02)
53     #define EE_PAGE_SIZE                8   // 24C02
54     #define EE_WORD_ADR_SIZE            1   // 1 word addr
55 #endif
56 
57 /* device information */
58 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8) || defined(HC32F334)
59     #define HW_I2C_DEV                  "i2c1"
60     #define SW_I2C_DEV                  "i2c1_sw"
61 #elif defined(HC32F460)
62     #define HW_I2C_DEV                  "i2c3"
63     #define SW_I2C_DEV                  "i2c1_sw"
64 #endif
65 
66 /* this API is for eeprom size is smaller than  256Bytes */
eeprom_page_write(uint32_t page,uint8_t * pBuf)67 static void eeprom_page_write(uint32_t page, uint8_t *pBuf)
68 {
69     struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
70     uint8_t TxBuf[EE_PAGE_SIZE + EE_WORD_ADR_SIZE] = {0};
71     struct rt_i2c_msg msg[1];
72 
73 #if defined (BSP_USING_I2C_HW)
74     hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV);  //hw i2c
75 #else
76     hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV);  //sw i2c
77 #endif
78 
79     /* START --- ADR_W --- WORD_ADR(1 byte) --- DATAn --- STOP */
80     if (EE_WORD_ADR_SIZE == 2)
81     {
82         TxBuf[0] = (page * EE_PAGE_SIZE) / 256;     // addrH
83         TxBuf[1] = page * EE_PAGE_SIZE;             // addrL
84     }
85     else
86     {
87         TxBuf[0] = page * EE_PAGE_SIZE;
88     }
89     for (int i = 0; i < EE_PAGE_SIZE; i++)  // data fill
90     {
91         TxBuf[i + EE_WORD_ADR_SIZE] = *pBuf++;
92     }
93     msg[0].addr  = EE_DEV_ADDR;
94     msg[0].flags = RT_I2C_WR;
95     msg[0].len   = EE_PAGE_SIZE + EE_WORD_ADR_SIZE;
96     msg[0].buf   = TxBuf;
97 
98 #if defined(USING_RT_I2C_TRANSFER)
99     rt_i2c_transfer(hc32_i2c, &msg[0], 1);
100 #else
101     rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_STOP, TxBuf, msg[0].len / 2);
102     rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_START, TxBuf + msg[0].len / 2, msg[0].len - msg[0].len / 2);
103 #endif
104     /* write cycle 5ms */
105     rt_thread_mdelay(5);
106 }
107 
eeprom_page_read(uint32_t page,uint8_t * pBuf)108 static void eeprom_page_read(uint32_t page, uint8_t *pBuf)
109 {
110     struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
111     uint8_t readAddr[EE_WORD_ADR_SIZE];
112 #if defined(USING_RT_I2C_TRANSFER)
113     struct rt_i2c_msg msg[2];
114 #endif
115 
116 #if defined (BSP_USING_I2C_HW)
117     hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV);  //hw i2c
118 #else
119     hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV);  //sw i2c
120 #endif
121 
122     if (EE_WORD_ADR_SIZE == 2)
123     {
124         readAddr[0] = (page * EE_PAGE_SIZE) / 256;  // addrH
125         readAddr[1] = page * EE_PAGE_SIZE;          // addrL
126     }
127     else
128     {
129         readAddr[0] = page * EE_PAGE_SIZE;
130     }
131 
132 #if defined(USING_RT_I2C_TRANSFER)
133     msg[0].addr  = EE_DEV_ADDR;
134     msg[0].flags = RT_I2C_WR;
135     msg[0].len   = EE_WORD_ADR_SIZE;
136     msg[0].buf   = readAddr;
137 
138     msg[1].addr  = EE_DEV_ADDR;
139     msg[1].flags = RT_I2C_RD;
140     msg[1].len   = EE_PAGE_SIZE;
141     msg[1].buf   = pBuf;
142     rt_i2c_transfer(hc32_i2c, &msg[0], 2);
143 #else
144     rt_i2c_master_send(hc32_i2c, EE_DEV_ADDR, RT_I2C_NO_STOP, readAddr, EE_WORD_ADR_SIZE);
145     rt_i2c_master_recv(hc32_i2c, EE_DEV_ADDR, 0, pBuf, EE_PAGE_SIZE);
146 #endif
147 }
148 
eeprom_test(void)149 void eeprom_test(void)
150 {
151     uint32_t page, i;
152     uint32_t compareValueDiff = 0;
153     static rt_uint8_t trans_buf[EE_PAGE_SIZE * EE_TEST_PAGE_CNT];
154     static rt_uint8_t recv_buf[EE_PAGE_SIZE * EE_TEST_PAGE_CNT];
155 
156     /* write e2 */
157     for (i = 0; i < sizeof(trans_buf); i++)
158     {
159         trans_buf[i] = i;
160     }
161     for (page = 0; page < EE_TEST_PAGE_CNT; page++)
162     {
163         eeprom_page_write(page, trans_buf + EE_PAGE_SIZE * page);
164     }
165     /* read e2 */
166     for (i = 0; i < sizeof(trans_buf); i++)
167     {
168         recv_buf[i] = 0;
169     }
170     for (page = 0; page < EE_TEST_PAGE_CNT; page++)
171     {
172         eeprom_page_read(page, recv_buf + EE_PAGE_SIZE * page);
173     }
174     /* compare e2 */
175     for (i = 0; i < sizeof(recv_buf); i++)
176     {
177         if (trans_buf[i] != recv_buf[i])
178         {
179             compareValueDiff = 1;
180             break;
181         }
182     }
183     if (compareValueDiff == 0)
184     {
185         rt_kprintf("eeprom test ok!\r\n");
186     }
187     else
188     {
189         rt_kprintf("eeprom test failed!\r\n");
190     }
191 }
192 
193 /* TCA9539 device */
194 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8)
195 
196 /* TCA9539 define */
197 #define TCA9539_DEV_ADDR                (0x74)       // TCA9539 chip address on I2C bus
198 
199 #define TCA9539_REG_INPUT_PORT0         (0x00U)
200 #define TCA9539_REG_INPUT_PORT1         (0x01U)
201 #define TCA9539_REG_OUTPUT_PORT0        (0x02U)
202 #define TCA9539_REG_OUTPUT_PORT1        (0x03U)
203 #define TCA9539_REG_INVERT_PORT0        (0x04U)
204 #define TCA9539_REG_INVERT_PORT1        (0x05U)
205 #define TCA9539_REG_CONFIG_PORT0        (0x06U)
206 #define TCA9539_REG_CONFIG_PORT1        (0x07U)
207 
tca9539_test(void)208 void tca9539_test(void)
209 {
210     struct rt_i2c_bus_device *hc32_i2c = RT_NULL;
211     static rt_uint8_t send_buf0[0x10];
212     static rt_uint8_t send_buf1[0x10], recv_buf1[0x10];
213     struct rt_i2c_msg msg[2];
214 
215 #if defined (BSP_USING_I2C_HW)
216     hc32_i2c = rt_i2c_bus_device_find(HW_I2C_DEV);  //hw i2c
217 #else
218     hc32_i2c = rt_i2c_bus_device_find(SW_I2C_DEV);  //sw i2c
219 #endif
220     RT_ASSERT(hc32_i2c != RT_NULL);
221 
222     send_buf0[0] = TCA9539_REG_CONFIG_PORT1;
223     send_buf0[1] = 0xFF;
224     msg[0].addr  = TCA9539_DEV_ADDR;
225     msg[0].flags = RT_I2C_WR;
226     msg[0].len   = 2;
227     msg[0].buf   = send_buf0;
228     rt_i2c_transfer(hc32_i2c, &msg[0], 1);
229 
230     send_buf0[0] = TCA9539_REG_OUTPUT_PORT1;
231     send_buf0[1] = 0xAC;
232     msg[1].addr  = TCA9539_DEV_ADDR;
233     msg[1].flags = RT_I2C_WR;
234     msg[1].len   = 2;
235     msg[1].buf   = send_buf0;
236     rt_i2c_transfer(hc32_i2c, &msg[1], 1);
237 
238     /* read */
239     send_buf1[0] = TCA9539_REG_OUTPUT_PORT1;
240     msg[0].addr  = TCA9539_DEV_ADDR;
241     msg[0].flags = RT_I2C_WR;
242     msg[0].len   = 1;
243     msg[0].buf   = send_buf1;
244 
245     msg[1].addr  = TCA9539_DEV_ADDR;
246     msg[1].flags = RT_I2C_RD;
247     msg[1].len   = 1;
248     msg[1].buf   = recv_buf1;
249     rt_i2c_transfer(hc32_i2c, &msg[0], 2);
250 
251     if (recv_buf1[0] == 0xAC)
252     {
253         rt_kprintf("tca9539 test ok!\r\n");
254     }
255     else
256     {
257         rt_kprintf("tca9539 test failed!\r\n");
258     }
259 }
260 #endif
261 
i2c_sample(int argc,char * argv[])262 static void i2c_sample(int argc, char *argv[])
263 {
264     eeprom_test();
265 #if defined(HC32F472) || defined(HC32F4A0) || defined(HC32F448) || defined(HC32F4A8)
266     tca9539_test();
267 #endif
268 }
269 
270 MSH_CMD_EXPORT(i2c_sample, i2c sample);
271 
272 #endif/* RT_USING_I2C */
273 
274 /*
275  EOF
276 */
277