1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-07-15 Emuzit first version
9 * 2022-07-20 Emuzit add watchdog test
10 * 2022-07-26 Emuzit add hwtimer test
11 * 2022-07-30 Emuzit add spi master test
12 * 2022-08-04 Emuzit add pwm test
13 */
14 #include <rtthread.h>
15 #include <drivers/dev_pin.h>
16 #include "drivers/dev_watchdog.h"
17 #include <drivers/hwtimer.h>
18 #include "drivers/dev_spi.h"
19 #include <drivers/dev_pwm.h>
20 #include "board.h"
21
22 #define PWM_CYCLE_MAX 255
23
24 static const rt_base_t gpio_int_pins[8] = GPIO_INT_PINS;
25
26 /* note : PIN_IRQ_MODE_RISING_FALLING not supported */
27 static const uint32_t gpint_mode[] =
28 {
29 PIN_IRQ_MODE_RISING,
30 PIN_IRQ_MODE_RISING,
31 PIN_IRQ_MODE_RISING,
32 PIN_IRQ_MODE_RISING,
33 PIN_IRQ_MODE_FALLING,
34 PIN_IRQ_MODE_FALLING,
35 PIN_IRQ_MODE_FALLING,
36 PIN_IRQ_MODE_FALLING,
37 };
38
39 static struct rt_mailbox *gpint_mb = RT_NULL;
40 static struct rt_thread *gpint_thread = RT_NULL;
41
42 static rt_device_t wdg_dev;
43
44 static rt_base_t led0, led1;
45
gpio_int_callback(void * pin)46 static void gpio_int_callback(void *pin)
47 {
48 led1 = (led1 == PIN_LOW) ? PIN_HIGH : PIN_LOW;
49 rt_pin_write(LED1_PIN, led1);
50
51 if (gpint_mb != RT_NULL)
52 {
53 /* non-block, silently ignore RT_EFULL */
54 rt_mb_send(gpint_mb, (uint32_t)pin);
55 }
56 }
57
gpio_int_thread(void * param)58 static void gpio_int_thread(void *param)
59 {
60 while (1)
61 {
62 rt_err_t res;
63 uint32_t pin;
64
65 res = rt_mb_recv(gpint_mb, &pin, RT_WAITING_FOREVER);
66 if (res == RT_EOK)
67 {
68 rt_kprintf("gpio_int #%d (%d)\n", pin, rt_pin_read(pin));
69 }
70 rt_thread_mdelay(100);
71
72 #ifdef RT_USING_WDT
73 rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL);
74 #endif
75 }
76 }
77
test_gpio_int(void)78 static void test_gpio_int(void)
79 {
80 rt_err_t res;
81 int i;
82
83 rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
84 rt_pin_write(LED1_PIN, led1 = PIN_HIGH);
85
86 /* Enable all gpio interrupt with various modes.
87 * LED0 or GND touching can be used to trigger pin interrupt.
88 */
89 gpint_mb = rt_mb_create("pximb", 8, RT_IPC_FLAG_FIFO);
90 if (gpint_mb == RT_NULL)
91 {
92 rt_kprintf("gpint mailbox create failed !\n");
93 }
94 else
95 {
96 gpint_thread = rt_thread_create("pxith", gpio_int_thread, RT_NULL,
97 512, RT_MAIN_THREAD_PRIORITY, 50);
98 if (gpint_thread == RT_NULL)
99 {
100 rt_kprintf("gpint thread create failed !\n");
101 }
102 else
103 {
104 rt_thread_startup(gpint_thread);
105
106 for (i = 0; i < 8; i++)
107 {
108 rt_base_t pin = gpio_int_pins[i];
109 #ifdef RT_USING_PWM
110 if (pin == PWM0_PIN || pin == PWM1_PIN)
111 continue;
112 #endif
113 rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP);
114 res = rt_pin_attach_irq(
115 pin, gpint_mode[i], gpio_int_callback, (void *)pin);
116 if (res != RT_EOK)
117 {
118 rt_kprintf("rt_pin_attach_irq failed (%d:%d)\n", i, res);
119 }
120 else
121 {
122 rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
123 }
124 }
125 }
126 }
127 }
128
129 #ifdef RT_USING_WDT
test_watchdog(uint32_t seconds)130 static void test_watchdog(uint32_t seconds)
131 {
132 /* Test watchdog with 30s timeout, keepalive with gpio interrupt.
133 *
134 * CAVEAT: With only 8-bit WDOG_COUNT and fixed clocking at Fsys/524288,
135 * watchdog of ch56x may be quite limited with very short timeout.
136 */
137 seconds = 30;
138 wdg_dev = rt_device_find("wdt");
139 if (!wdg_dev)
140 {
141 rt_kprintf("watchdog device not found !\n");
142 }
143 else if (rt_device_init(wdg_dev) != RT_EOK ||
144 rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &seconds) != RT_EOK)
145 {
146 rt_kprintf("watchdog setup failed !\n");
147 }
148 else
149 {
150 rt_kprintf("WDT_TIMEOUT in %d seconds, trigger gpio interrupt to keep alive.\n\n", seconds);
151 }
152 }
153 #else
154 #define test_watchdog(tov) do {} while(0)
155 #endif
156
157 #ifdef RT_USING_HWTIMER
158 static struct rt_device *tmr_dev_0;
159 static struct rt_device *tmr_dev_1;
160
tmr_timeout_cb(rt_device_t dev,rt_size_t size)161 static rt_err_t tmr_timeout_cb(rt_device_t dev, rt_size_t size)
162 {
163 rt_tick_t tick = rt_tick_get();
164
165 int tmr = (dev == tmr_dev_1) ? 1 : 0;
166
167 rt_kprintf("hwtimer %d timeout callback fucntion @tick %d\n", tmr, tick);
168
169 return RT_EOK;
170 }
171
test_hwtimer(void)172 static void test_hwtimer(void)
173 {
174 rt_hwtimerval_t timerval;
175 rt_hwtimer_mode_t mode;
176 rt_size_t tsize;
177
178 /* setup two timers, ONESHOT & PERIOD each
179 */
180 tmr_dev_0 = rt_device_find("timer0");
181 tmr_dev_1 = rt_device_find("timer1");
182 if (tmr_dev_0 == RT_NULL || tmr_dev_1 == RT_NULL)
183 {
184 rt_kprintf("hwtimer device(s) not found !\n");
185 }
186 else if (rt_device_open(tmr_dev_0, RT_DEVICE_OFLAG_RDWR) != RT_EOK ||
187 rt_device_open(tmr_dev_1, RT_DEVICE_OFLAG_RDWR) != RT_EOK)
188 {
189 rt_kprintf("hwtimer device(s) open failed !\n");
190 }
191 else
192 {
193 rt_device_set_rx_indicate(tmr_dev_0, tmr_timeout_cb);
194 rt_device_set_rx_indicate(tmr_dev_1, tmr_timeout_cb);
195
196 timerval.sec = 3;
197 timerval.usec = 500000;
198 tsize = sizeof(timerval);
199 mode = HWTIMER_MODE_ONESHOT;
200 if (rt_device_control(tmr_dev_0, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK)
201 {
202 rt_kprintf("timer0 set mode failed !\n");
203 }
204 else if (rt_device_write(tmr_dev_0, 0, &timerval, tsize) != tsize)
205 {
206 rt_kprintf("timer0 start failed !\n");
207 }
208 else
209 {
210 rt_kprintf("timer0 started !\n");
211 }
212
213 timerval.sec = 5;
214 timerval.usec = 0;
215 tsize = sizeof(timerval);
216 mode = HWTIMER_MODE_PERIOD;
217 if (rt_device_control(tmr_dev_1, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK)
218 {
219 rt_kprintf("timer1 set mode failed !\n");
220 }
221 else if (rt_device_write(tmr_dev_1, 0, &timerval, tsize) != tsize)
222 {
223 rt_kprintf("timer1 start failed !\n");
224 }
225 else
226 {
227 rt_kprintf("timer1 started !\n\n");
228 }
229 }
230 }
231 #else
232 #define test_hwtimer() do {} while(0)
233 #endif
234
235 #ifdef RT_USING_SPI
236 static struct rt_spi_device spi_dev_w25q;
237
test_spi_master(void)238 static void test_spi_master(void)
239 {
240 struct rt_spi_configuration cfg;
241 struct rt_spi_message msg1, msg2;
242 rt_err_t res;
243
244 uint8_t buf[16];
245 int i;
246
247 cfg.max_hz = 25 * 1000000;
248 cfg.data_width = 8;
249 cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
250
251 res = rt_spi_bus_attach_device(
252 &spi_dev_w25q, W25Q32_SPI_NAME, SPI0_BUS_NAME, (void *)W25Q32_CS_PIN);
253 if (res == RT_EOK && rt_spi_configure(&spi_dev_w25q, &cfg) == RT_EOK)
254 {
255 /* cmd : Read Manufacturer / Device ID (90h) */
256 buf[0] = 0x90;
257 /* address : 0 */
258 buf[1] = buf[2] = buf[3] = 0;
259 msg1.send_buf = buf;
260 msg1.recv_buf = RT_NULL;
261 msg1.length = 4;
262 msg1.cs_take = 1;
263 msg1.cs_release = 0;
264 msg1.next = &msg2;
265
266 msg2.send_buf = RT_NULL;
267 msg2.recv_buf = buf;
268 msg2.length = 2;
269 msg2.cs_take = 0;
270 msg2.cs_release = 1;
271 msg2.next = RT_NULL;
272
273 rt_spi_transfer_message(&spi_dev_w25q, &msg1);
274 rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", buf[0], buf[1]);
275
276 /* cmd : Read Data (03h) */
277 buf[0] = 0x03;
278 /* address : 0 */
279 buf[1] = buf[2] = buf[3] = 0;
280 msg2.length = 16;
281 if (rt_spi_transfer_message(&spi_dev_w25q, &msg1) == RT_NULL)
282 {
283 rt_kprintf("SPI0 16-byte DMA read :");
284 for (i = 0; i < 16; i++)
285 rt_kprintf(" %02x", buf[i]);
286 rt_kprintf("\n\n");
287 }
288 }
289 else
290 {
291 rt_kprintf("w25q32 attach/configure failed (%d) !\n", res);
292 }
293 }
294 #else
295 #define test_spi_master() do {} while(0)
296 #endif
297
298 #ifdef RT_USING_PWM
299 static struct rt_device_pwm *pwm_dev;
300 static uint32_t pwm_period;
301
302 rt_err_t rt_pwm_get(struct rt_device_pwm *device,
303 struct rt_pwm_configuration *cfg);
304
pwm_tick_hook(void)305 static void pwm_tick_hook(void)
306 {
307 uint32_t pulse;
308
309 if (pwm_dev)
310 {
311 /* PWM.CH3 duty cycle : 0%->100% for every ~2.5 seconds */
312 pulse = (rt_tick_get() >> 1) % (PWM_CYCLE_MAX + 1);
313 pulse = (pwm_period * pulse + PWM_CYCLE_MAX/2) / PWM_CYCLE_MAX;
314 rt_pwm_set_pulse(pwm_dev, 3, pulse);
315 }
316 }
317
test_pwm(void)318 static void test_pwm(void)
319 {
320 struct rt_pwm_configuration cfg;
321 uint32_t pulse[4];
322 int ch;
323
324 pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEVICE_NAME);
325 if (pwm_dev == RT_NULL)
326 {
327 rt_kprintf("can't find %s device !\n", PWM_DEVICE_NAME);
328 }
329 else
330 {
331 /* for HCLK@80MHz, allowed period is 3187 ~ 812812 */
332 pwm_period = 800*1000;
333
334 pulse[0] = 100*1000;
335 pulse[1] = 400*1000;
336 pulse[2] = 600*1000;
337 pulse[3] = 0;
338
339 for (ch = 0; ch < PWM_CHANNELS; ch++)
340 {
341 rt_pwm_set(pwm_dev, ch, pwm_period, pulse[ch]);
342 rt_pwm_enable(pwm_dev, ch);
343
344 cfg.channel = ch;
345 rt_pwm_get(pwm_dev, &cfg);
346 rt_kprintf("pwm%d period set/get : %d/%d\n", ch, pwm_period, cfg.period);
347 rt_kprintf("pwm%d pulse set/get : %d/%d\n\n", ch, pulse[ch], cfg.pulse);
348 }
349
350 /* disable PWM.CH0 after 1 second, also start changing CH3 */
351 rt_thread_mdelay(1000);
352 rt_pwm_disable(pwm_dev, 0);
353
354 /* connect PWM3 (PB.2) to LED2 for a visualized PWM effect */
355 rt_pin_mode(LED2_PIN, PIN_MODE_INPUT);
356 rt_tick_sethook(pwm_tick_hook);
357 }
358 }
359 #else
360 #define test_pwm() do {} while(0)
361 #endif
362
363 #ifdef RT_USING_USB_DEVICE
364 #if !defined(RT_USING_EVENT) || !defined(RT_USING_MESSAGEQUEUE)
365 #error "event flag or message queue IPC not enabled"
366 #endif
367 static struct rt_thread *udvcom_thread;
368 static rt_device_t vcom;
369
usbd_vcom_thread(void * param)370 static void usbd_vcom_thread(void *param)
371 {
372 char ch;
373
374 while (1)
375 {
376 while (rt_device_read(vcom, 0, &ch, 1) != 1)
377 rt_thread_delay(1);
378 rt_kprintf("(%2d) %02x:%c\n", rt_device_write(vcom, 0, &ch, 1), ch, ch);
379 rt_pin_write(LED1_PIN, (ch & 1) ? PIN_LOW : PIN_HIGH);
380 }
381 }
382
test_usbd()383 static void test_usbd()
384 {
385 char name[] = "vcom";
386
387 vcom = rt_device_find(name);
388 if (vcom && rt_device_open(vcom, RT_DEVICE_FLAG_INT_RX) == RT_EOK)
389 {
390 rt_kprintf("%s opened\n", name);
391
392 rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
393 rt_pin_write(LED1_PIN, PIN_LOW);
394
395 udvcom_thread = rt_thread_create("udvcom", usbd_vcom_thread, vcom,
396 512, 20, 50);
397 if (udvcom_thread != RT_NULL)
398 rt_thread_startup(udvcom_thread);
399 else
400 rt_kprintf("usvcom thread create failed !\n");
401
402 rt_device_write(vcom, 0, name, rt_strlen(name));
403 }
404 }
405 #else
406 #define test_usbd() do {} while(0)
407 #endif
408
main(void)409 void main(void)
410 {
411 uint32_t wdog_timeout = 32;
412
413 rt_kprintf("\nCH569W-R0-1v0, HCLK: %dMHz\n\n", sys_hclk_get() / 1000000);
414
415 test_gpio_int();
416 test_watchdog(wdog_timeout);
417 test_hwtimer();
418 test_spi_master();
419 test_pwm();
420 test_usbd();
421
422 rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
423 rt_pin_write(LED0_PIN, led0 = PIN_LOW);
424
425 while (1)
426 {
427 /* flashing LED0 every 1 second */
428 rt_thread_mdelay(500);
429 led0 = (led0 == PIN_LOW) ? PIN_HIGH : PIN_LOW;
430 rt_pin_write(LED0_PIN, led0);
431 }
432 }
433