diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript b/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript index 7b79db221a..b3c2736e2b 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/SConscript @@ -12,6 +12,9 @@ if GetDepend('SOC_SERIES_CH569'): if GetDepend('RT_USING_WDT'): src += ['ch56x_wdt.c'] +if GetDepend('RT_USING_PWM'): + src += ['ch56x_pwm.c'] + if GetDepend('RT_USING_HWTIMER'): src += ['ch56x_timer.c'] diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c new file mode 100644 index 0000000000..f9961a495e --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-08-04 Emuzit first version + */ +#include +#include +#include +#include +#include "ch56x_pwm.h" +#include "ch56x_sys.h" + +#define PWM_CYCLE_MAX 255 // must be 255 for 0%~100% duty cycle + +struct pwm_device +{ + struct rt_device_pwm parent; + volatile struct pwm_registers *reg_base; + uint32_t period; +}; +static struct pwm_device pwmx_device; + +static const uint8_t pwmx_pin[] = {PWM0_PIN, PWM1_PIN, PWM2_PIN, PWM3_PIN}; + +/** + * @brief Enable or disable PWM channel output. + * Make sure PWM clock is ON for writing registers. + * + * @param device is pointer to the rt_device_pwm device. + * + * @param channel is the PWM channel (0~3) to operate on. + * + * @param enable is to enable PWM when RT_TRUE, or disable when RT_FALSE. + * + * @return None. + */ +static void pwm_channel_enable(struct rt_device_pwm *device, + uint32_t channel, rt_bool_t enable) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + volatile struct pwm_registers *pxreg = pwm_device->reg_base; + + uint8_t ctrl_mod, polar; + + if (enable) + { + /* set pwm_out_en to allow pwm output */ + ctrl_mod = pxreg->CTRL_MOD.reg; + pxreg->CTRL_MOD.reg = ctrl_mod | (RB_PWM0_OUT_EN << channel); + } + else + { + /* ch56x has no disable bit, set pin out to quiesce */ + ctrl_mod = pxreg->CTRL_MOD.reg; + polar = ctrl_mod & (RB_PWM0_POLAR << channel); + rt_pin_write(pwmx_pin[channel], polar ? PIN_HIGH : PIN_LOW); + ctrl_mod &= ~(RB_PWM0_OUT_EN << channel); + pxreg->CTRL_MOD.reg = ctrl_mod; + } +} + +/** + * @brief Set period of the PWM channel. + * Make sure PWM clock is ON for writing registers. + * + * @param device is pointer to the rt_device_pwm device. + * + * @param channel is the PWM channel (0~3) to operate on. + * + * @param period is PWM period in nanoseconds. + * + * @return RT_EOK if successful. + */ +static rt_err_t pwm_channel_period(struct rt_device_pwm *device, + uint32_t channel, uint32_t period) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + + uint32_t clock_div; + + /* All ch56x PWMX channels share the same period, channel ignored. + * + * Max allowed period is when Fsys@2MHz and CLOCK_DIV is 0 (256) : + * (1 / 2MHz) * 256 * PWM_CYCLE_MAX => 32640000 ns + * Note that `period * F_MHz` won't overflow in calculation below. + */ + if (period > (256 * PWM_CYCLE_MAX * 1000 / 2)) + return -RT_EINVAL; + + if (period != pwm_device->period) + { + uint32_t Fsys = sys_hclk_get(); + uint32_t F_MHz = Fsys / 1000000; + uint32_t F_mod = Fsys % 1000000; + + /* period = (clock_div / Fsys) * 10^9 * PWM_CYCLE_MAX */ + clock_div = period * F_MHz + (1000 * PWM_CYCLE_MAX / 2); + /* Fsys is mostly in integer MHz, likely to be skipped */ + if (F_mod != 0) + { + uint64_t u64v = ((uint64_t)period * F_mod) / 1000000; + clock_div += (uint32_t)u64v; + } + clock_div = clock_div / (1000 * PWM_CYCLE_MAX); + if (clock_div > 256) + return -RT_EINVAL; + /* CLOCK_DIV will be 0 if `clock_div` is 256 */ + pwm_device->reg_base->CLOCK_DIV = (uint8_t)clock_div; + /* cycle_sel set to PWM_CYCLE_SEL_255 for 0%~100% duty cycle */ + pwmx_device.reg_base->CTRL_CFG.cycle_sel = PWM_CYCLE_SEL_255; + pwm_device->period = period; + } + + return RT_EOK; +} + +/** + * @brief Set pulse duration of the PWM channel. + * Make sure PWM clock is ON for writing registers. + * + * @param device is pointer to the rt_device_pwm device. + * + * @param channel is the PWM channel (0~3) to operate on. + * + * @param pulse is PWM pulse duration in nanoseconds. + * + * @return RT_EOK if successful. + */ +static rt_err_t pwm_channel_pulse(struct rt_device_pwm *device, + uint32_t channel, uint32_t pulse) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + + uint32_t pdata, period; + + /* duty cycle is calculated with "raw" period setting */ + period = pwm_device->period; + if (!period || pulse > period) + return -RT_EINVAL; + + pdata = (pulse * PWM_CYCLE_MAX + (period >> 1)) / period; + pwm_device->reg_base->PWM_DATA[channel] = pdata; + + return RT_EOK; +} + +/** + * @brief Set period & pulse of the PWM channel, remain disabled. + * Make sure PWM clock is ON for writing registers. + * + * @param device is pointer to the rt_device_pwm device. + * + * @param configuration is the channel/period/pulse specification. + * ch56x PWM has no complementary pin, complementary ignored. + * FIXME: can we specify PWM output polarity somehow ? + * + * @return RT_EOK if successful. + */ +static rt_err_t pwm_device_set(struct rt_device_pwm *device, + struct rt_pwm_configuration *configuration) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + + uint32_t channel = configuration->channel; + + rt_err_t res; + + res = pwm_channel_period(device, channel, configuration->period); + if (res == RT_EOK) + { + res = pwm_channel_pulse(device, channel, configuration->pulse); + if (res == RT_EOK) + { + rt_pin_mode(pwmx_pin[channel], PIN_MODE_OUTPUT); + /* seems to be kept disabled according to sample code */ + pwm_channel_enable(device, channel, RT_FALSE); + } + } + + return res; +} + +/** + * @brief Get period & pulse of the PWM channel. + * The returned information is calculated with h/w setting. + * + * @param device is pointer to the rt_device_pwm device. + * + * @param configuration->channel specify the PWM channel (0~3). + * configuration->period & pulse return the calculated result. + * + * @return RT_EOK if successful. + */ +static rt_err_t pwm_device_get(struct rt_device_pwm *device, + struct rt_pwm_configuration *configuration) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + volatile struct pwm_registers *pxreg = pwm_device->reg_base; + + uint32_t channel = configuration->channel; + + uint32_t Fsys = sys_hclk_get(); + + uint32_t clock_div; + uint32_t pdata; + uint64_t u64v; + + /* clock_div is actually 256 when CLOCK_DIV is 0 */ + clock_div = pxreg->CLOCK_DIV; + if (clock_div == 0) + clock_div = 256; + + u64v = clock_div; + u64v = (u64v * 1000*1000*1000 * PWM_CYCLE_MAX + (Fsys >> 1)) / Fsys; + configuration->period = (uint32_t)u64v; + + /* `pdata` <= PWM_CYCLE_MAX, calculated pulse won't exceed period */ + pdata = pxreg->PWM_DATA[channel]; + u64v = clock_div; + u64v = (u64v * 1000*1000*1000 * pdata + (Fsys >> 1)) / Fsys; + configuration->pulse = (uint32_t)u64v; + + return RT_EOK; +} + +static rt_err_t pwm_control(struct rt_device_pwm *device, int cmd, void *arg) +{ + struct pwm_device *pwm_device = (struct pwm_device *)device; + + struct rt_pwm_configuration *configuration = arg; + uint32_t channel = configuration->channel; + + rt_err_t res = RT_EOK; + + RT_ASSERT(device != RT_NULL); + + if (channel >= PWM_CHANNELS) + return -RT_EINVAL; + + /* PWM clock needs to be ON to write PWM registers */ + sys_slp_clk_off0(RB_SLP_CLK_PWMX, SYS_SLP_CLK_ON); + + switch (cmd) + { + case PWM_CMD_ENABLE: + pwm_channel_enable(device, channel, RT_TRUE); + break; + case PWM_CMD_DISABLE: + pwm_channel_enable(device, channel, RT_FALSE); + break; + case PWM_CMD_SET: + return pwm_device_set(device, configuration); + case PWM_CMD_GET: + return pwm_device_get(device, configuration); + case PWM_CMD_SET_PERIOD: + return pwm_channel_period(device, channel, configuration->period); + case PWM_CMD_SET_PULSE: + return pwm_channel_pulse(device, channel, configuration->pulse); + default: + res = -RT_EINVAL; + } + + /* disable PWMX clocking, if all channels are disabled */ + if ((pwm_device->reg_base->CTRL_MOD.reg & PWM_OUT_EN_MASK) == 0) + sys_slp_clk_off0(RB_SLP_CLK_PWMX, SYS_SLP_CLK_OFF); + + return res; +} + +static struct rt_pwm_ops pwm_ops = +{ + .control = pwm_control +}; + +static int rt_hw_pwm_init(void) +{ + /* init pwmx_device with code to save some flash space */ + pwmx_device.reg_base = (struct pwm_registers *)PWMX_REG_BASE; + /* Note: PWM clock OFF here => PWM registers not writable */ + + return rt_device_pwm_register( + &pwmx_device.parent, PWM_DEVICE_NAME, &pwm_ops, RT_NULL); +} +INIT_DEVICE_EXPORT(rt_hw_pwm_init); diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.h new file mode 100644 index 0000000000..cacf019be6 --- /dev/null +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_pwm.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-08-04 Emuzit first version + */ +#ifndef __CH56X_PWM_H__ +#define __CH56X_PWM_H__ + +#include "soc.h" +#include "ch56x_gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PWM_DEVICE_NAME "pwmx" + +#define PWM_CHANNELS 4 + +#define PWM0_PIN GET_PIN(B, 15) +#define PWM1_PIN GET_PIN(A, 4) +#define PWM2_PIN GET_PIN(B, 1) +#define PWM3_PIN GET_PIN(B, 2) + +union _pwm_ctrl_mod +{ + uint8_t reg; + struct + { + uint8_t pwm0_out_en : 1; // RW, PWM output enable + uint8_t pwm1_out_en : 1; + uint8_t pwm2_out_en : 1; + uint8_t pwm3_out_en : 1; + uint8_t pwm0_polar : 1; // RW, PWM output polarity + uint8_t pwm1_polar : 1; + uint8_t pwm2_polar : 1; + uint8_t pwm3_polar : 1; + }; +}; +#define RB_PWM0_OUT_EN 0x01 +#define RB_PWM1_OUT_EN 0x02 +#define RB_PWM2_OUT_EN 0x04 +#define RB_PWM3_OUT_EN 0x08 +#define RB_PWM0_POLAR 0x10 +#define RB_PWM1_POLAR 0x20 +#define RB_PWM2_POLAR 0x40 +#define RB_PWM3_POLAR 0x80 + +#define PWM_OUT_EN_MASK 0x0f + +union _pwm_ctrl_cfg +{ + uint8_t reg; + struct + { + uint8_t cycle_sel : 1; // RW, PWM cycle select, 0/1 for 256/255 + uint8_t resv_1 : 7; + }; +}; +#define RB_PWM_CYCLE_SEL 0x01 + +#define PWM_CYCLE_SEL_256 0 +#define PWM_CYCLE_SEL_255 1 + +/* + * 0x00 R8_PWM_CTRL_MOD: PWM control register + * 0x01 R8_PWM_CTRL_CFG: PWM control configuration register + * 0x02 R8_PWM_CLOCK_DIV: PWM clock divisor register + * 0x04 R8_PWM0_DATA: PWM0 data holding register + * 0x05 R8_PWM1_DATA: PWM1 data holding register + * 0x06 R8_PWM2_DATA: PWM2 data holding register + * 0x07 R8_PWM3_DATA: PWM3 data holding register + */ +struct pwm_registers +{ + union _pwm_ctrl_mod CTRL_MOD; + union _pwm_ctrl_cfg CTRL_CFG; + uint8_t CLOCK_DIV; + uint8_t resv_3; + union + { + uint32_t R32_PWM_DATA; + uint8_t PWM_DATA[4]; + struct + { + uint8_t PWM0_DATA; + uint8_t PWM1_DATA; + uint8_t PWM2_DATA; + uint8_t PWM3_DATA; + }; + }; +}; +CHECK_STRUCT_SIZE(struct pwm_registers, 8); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c index 49cfa330a7..6ed44f503e 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.c @@ -164,11 +164,25 @@ static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_config return RT_EOK; } -static rt_uint32_t _spi_xfer_1(struct rt_spi_device *device, struct rt_spi_message *message) +/** + * @brief Transfer SPI data for single message. + * Message traversing is done by rt_spi_message(). + * + * @param device is pointer to the rt_spi_device device. + * + * @param message is a link list for data/control information, + * only the first entry is processed. + * Note: ch56x can't do SPI send & recv at the same time. + * + * @return `message->length1 if successful, 0 otherwise. + */ +static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) { struct spi_bus *spi_bus = (struct spi_bus *)device->bus; volatile struct spi_registers *sxreg = spi_bus->reg_base; + union _spi_ctrl_mod ctrl_mod; + uint8_t *data; uint32_t size; @@ -179,22 +193,28 @@ static rt_uint32_t _spi_xfer_1(struct rt_spi_device *device, struct rt_spi_messa if (size == 0 || size > 4095) return 0; + ctrl_mod.reg = sxreg->CTRL_MOD.reg | RB_SPI_ALL_CLEAR; + /* ch56x can't do SPI send & recv at the same time */ if (message->send_buf && !message->recv_buf) { data = (uint8_t *)message->send_buf; - sxreg->CTRL_MOD.fifo_dir = SPI_FIFO_DIR_OUTPUT; + ctrl_mod.fifo_dir = SPI_FIFO_DIR_OUTPUT; } else if (!message->send_buf && message->recv_buf) { data = (uint8_t *)message->recv_buf; - sxreg->CTRL_MOD.fifo_dir = SPI_FIFO_DIR_INPUT; + ctrl_mod.fifo_dir = SPI_FIFO_DIR_INPUT; } else { return 0; } + sxreg->CTRL_MOD.reg = ctrl_mod.reg; + ctrl_mod.all_clear = 0; + sxreg->CTRL_MOD.reg = ctrl_mod.reg; + /* set MISO pin direction to match xfer if shared SI/SO pin */ if (device->config.mode & RT_SPI_3WIRE) { @@ -202,7 +222,7 @@ static rt_uint32_t _spi_xfer_1(struct rt_spi_device *device, struct rt_spi_messa rt_pin_mode(spi_bus->miso_pin, mode); } - cs_pin = (rt_base_t)device->user_data; + cs_pin = (rt_base_t)device->parent.user_data; cs_high = device->config.mode & RT_SPI_CS_HIGH; if (message->cs_take) @@ -236,6 +256,8 @@ static rt_uint32_t _spi_xfer_1(struct rt_spi_device *device, struct rt_spi_messa /* wait for transfer done */ while (sxreg->TOTAL_COUNT > 0); + /* disable DMA, anyway */ + sxreg->CTRL_CFG.dma_enable = 0; /* non-DMA recv => read data from FIFO */ if (size > 0) @@ -259,26 +281,6 @@ static rt_uint32_t _spi_xfer_1(struct rt_spi_device *device, struct rt_spi_messa return message->length; } -static rt_uint32_t spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message) -{ - uint32_t total_xsize = 0; - uint32_t xsize; - - RT_ASSERT(device != NULL); - RT_ASSERT(message != NULL); - - while (message != RT_NULL) - { - xsize = _spi_xfer_1(device, message); - if (xsize != message->length) - return 0; - total_xsize += xsize; - message = message->next; - } - - return total_xsize; -} - static const struct rt_spi_ops spi_ops = { .configure = spi_configure, diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.h index dbceff7b89..2d04df692c 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.h +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_spi.h @@ -179,9 +179,6 @@ union _spi_int_flag * 0x14 R32_SPIx_DMA_NOW: SPI DMA current address * 0x18 R32_SPIx_DMA_BEG: SPI DMA start address * 0x1c R32_SPIx_DMA_END: SPI DMA end address - * - * CAVEAT: gcc (as of 8.2.0) tends to read 32-bit word for bit field test. - * Be careful for those with side effect for read (e.g. RBR, IIR). */ struct spi_registers { diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c index 899f173aed..d9696b6f9e 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_sys.c @@ -101,12 +101,15 @@ void sys_slp_clk_off0(uint8_t bits, int off) uint8_t u8v; u8v = sys->SLP_CLK_OFF0.reg; - u8v = off ? (u8v | bits) : (u8v & ~bits); - level = rt_hw_interrupt_disable(); - sys_safe_access_enter(sys); - sys->SLP_CLK_OFF0.reg = u8v; - sys_safe_access_leave(sys); - rt_hw_interrupt_enable(level); + if ((u8v & bits) != (off ? bits : 0)) + { + u8v = off ? (u8v | bits) : (u8v & ~bits); + level = rt_hw_interrupt_disable(); + sys_safe_access_enter(sys); + sys->SLP_CLK_OFF0.reg = u8v; + sys_safe_access_leave(sys); + rt_hw_interrupt_enable(level); + } } /** @@ -123,12 +126,15 @@ void sys_slp_clk_off1(uint8_t bits, int off) uint8_t u8v; u8v = sys->SLP_CLK_OFF1.reg; - u8v = off ? (u8v | bits) : (u8v & ~bits); - level = rt_hw_interrupt_disable(); - sys_safe_access_enter(sys); - sys->SLP_CLK_OFF1.reg = u8v; - sys_safe_access_leave(sys); - rt_hw_interrupt_enable(level); + if ((u8v & bits) != (off ? bits : 0)) + { + u8v = off ? (u8v | bits) : (u8v & ~bits); + level = rt_hw_interrupt_disable(); + sys_safe_access_enter(sys); + sys->SLP_CLK_OFF1.reg = u8v; + sys_safe_access_leave(sys); + rt_hw_interrupt_enable(level); + } } /** @@ -171,12 +177,15 @@ int sys_clk_off_by_irqn(uint8_t irqn, int off) volatile uint8_t *cxreg = (void *)sys; rt_base_t level; u8v = cxreg[offset]; - u8v = off ? (u8v | bitpos) : (u8v & ~bitpos); - level = rt_hw_interrupt_disable(); - sys_safe_access_enter(sys); - cxreg[offset] = u8v; - sys_safe_access_leave(sys); - rt_hw_interrupt_enable(level); + if ((u8v & bitpos) != (off ? bitpos : 0)) + { + u8v = off ? (u8v | bitpos) : (u8v & ~bitpos); + level = rt_hw_interrupt_disable(); + sys_safe_access_enter(sys); + cxreg[offset] = u8v; + sys_safe_access_leave(sys); + rt_hw_interrupt_enable(level); + } } } diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c index d0230d21fb..24d2183339 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.c @@ -16,6 +16,7 @@ #else #include #endif +#include #include "ch56x_sys.h" #include "ch56x_uart.h" #include "isr_sp.h" @@ -25,11 +26,17 @@ #error "Please define at least one UARTx" #endif +/* Type of irqn/rxd_pin/txd_pin are per uart driver perspective + * to save some space, still compatible to RT api call, anyway. +*/ struct serial_device { struct rt_serial_device parent; volatile struct uart_registers *reg_base; - irq_number_t irqn; + uint8_t irqn; + uint8_t resv; + uint8_t rxd_pin; + uint8_t txd_pin; char *name; }; @@ -38,6 +45,8 @@ static struct serial_device serial_device_0 = { .reg_base = (struct uart_registers *)UART0_REG_BASE, .irqn = UART0_IRQn, + .rxd_pin = UART_RXD0_PIN, + .txd_pin = UART_TXD0_PIN, .name = "uart0", }; #endif @@ -47,6 +56,8 @@ static struct serial_device serial_device_1 = { .reg_base = (struct uart_registers *)UART1_REG_BASE, .irqn = UART1_IRQn, + .rxd_pin = UART_RXD1_PIN, + .txd_pin = UART_TXD1_PIN, .name = "uart1", }; #endif @@ -56,6 +67,8 @@ static struct serial_device serial_device_2 = { .reg_base = (struct uart_registers *)UART2_REG_BASE, .irqn = UART2_IRQn, + .rxd_pin = UART_RXD2_PIN, + .txd_pin = UART_TXD2_PIN, .name = "uart2", }; #endif @@ -65,6 +78,8 @@ static struct serial_device serial_device_3 = { .reg_base = (struct uart_registers *)UART3_REG_BASE, .irqn = UART3_IRQn, + .rxd_pin = UART_RXD3_PIN, + .txd_pin = UART_TXD3_PIN, .name = "uart3", }; #endif @@ -233,15 +248,25 @@ int rt_hw_uart_init(void) devices[n++] = &serial_device_0; #endif - /* IMPORTANT: pin mode should be set properly @ board init */ - while (--n >= 0) { - uint32_t flag; + uint32_t flag, txd_pin, rxd_pin; struct serial_device *serial = devices[n]; serial->parent.ops = &uart_ops; serial->parent.config = config; + txd_pin = serial->txd_pin; + rxd_pin = serial->rxd_pin; +#ifdef BSP_USING_UART0_PIN_ALT + if (serial->irqn == UART0_IRQn) + { + txd_pin = UART_TXD0_ALT; + rxd_pin = UART_RXD0_ALT; + } +#endif + rt_pin_mode(txd_pin, PIN_MODE_OUTPUT); + rt_pin_mode(rxd_pin, PIN_MODE_INPUT_PULLUP); + sys_clk_off_by_irqn(serial->irqn, SYS_SLP_CLK_ON); flag = RT_DEVICE_FLAG_RDWR | diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h index c34c6b5c21..aaec4e0d73 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/ch56x_uart.h @@ -11,11 +11,24 @@ #define __CH56X_UART_H__ #include "soc.h" +#include "ch56x_gpio.h" #ifdef __cplusplus extern "C" { #endif +#define UART_RXD0_ALT GET_PIN(A, 5) +#define UART_TXD0_ALT GET_PIN(A, 6) + +#define UART_RXD0_PIN GET_PIN(B, 5) +#define UART_TXD0_PIN GET_PIN(B, 6) +#define UART_RXD1_PIN GET_PIN(A, 7) +#define UART_TXD1_PIN GET_PIN(A, 8) +#define UART_RXD2_PIN GET_PIN(A, 2) +#define UART_TXD2_PIN GET_PIN(A, 3) +#define UART_RXD3_PIN GET_PIN(B, 3) +#define UART_TXD3_PIN GET_PIN(B, 4) + #ifndef UART_FIFO_SIZE #define UART_FIFO_SIZE 8 #endif diff --git a/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h b/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h index 579996bcdd..01e5f6de39 100644 --- a/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h +++ b/bsp/wch/risc-v/Libraries/ch56x_drivers/soc.h @@ -13,6 +13,7 @@ #include #include #include +#include #if !defined(SOC_CH567) && \ !defined(SOC_CH568) && \ diff --git a/bsp/wch/risc-v/ch569w-evt/.config b/bsp/wch/risc-v/ch569w-evt/.config index 7512b2f132..5f007224f2 100644 --- a/bsp/wch/risc-v/ch569w-evt/.config +++ b/bsp/wch/risc-v/ch569w-evt/.config @@ -110,7 +110,7 @@ CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_SERIAL_USING_DMA is not set CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set -CONFIG_RT_USING_HWTIMER=y +# CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set @@ -123,14 +123,8 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_PM is not set # CONFIG_RT_USING_RTC is not set # CONFIG_RT_USING_SDIO is not set -CONFIG_RT_USING_SPI=y -# CONFIG_RT_USING_SPI_BITOPS is not set -# CONFIG_RT_USING_QSPI is not set -# CONFIG_RT_USING_SPI_MSD is not set -# CONFIG_RT_USING_SFUD is not set -# CONFIG_RT_USING_ENC28J60 is not set -# CONFIG_RT_USING_SPI_WIFI is not set -CONFIG_RT_USING_WDT=y +# CONFIG_RT_USING_SPI is not set +# CONFIG_RT_USING_WDT is not set # CONFIG_RT_USING_AUDIO is not set # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set @@ -313,6 +307,7 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_RAPIDJSON is not set # CONFIG_PKG_USING_JSMN is not set # CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PARSON is not set # # XML: Extensible Markup Language @@ -491,8 +486,10 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_SHT2X is not set # CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_ADT74XX is not set # CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set +# CONFIG_PKG_USING_RTT_ESP_IDF is not set # CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_BUTTON is not set # CONFIG_PKG_USING_PCF8574 is not set @@ -656,13 +653,8 @@ CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_UART2 is not set # CONFIG_BSP_USING_UART3 is not set -CONFIG_BSP_USING_TIMER=y -CONFIG_BSP_USING_TMR0=y -CONFIG_BSP_USING_TMR1=y -# CONFIG_BSP_USING_TMR2 is not set -CONFIG_BSP_USING_SPI=y -CONFIG_BSP_USING_SPI0=y -# CONFIG_BSP_USING_SPI1 is not set +# CONFIG_BSP_USING_TIMER is not set +# CONFIG_BSP_USING_SPI is not set # # Onboard Peripheral Drivers diff --git a/bsp/wch/risc-v/ch569w-evt/applications/main.c b/bsp/wch/risc-v/ch569w-evt/applications/main.c index 7716789025..a83dc5c09c 100644 --- a/bsp/wch/risc-v/ch569w-evt/applications/main.c +++ b/bsp/wch/risc-v/ch569w-evt/applications/main.c @@ -5,304 +5,23 @@ * * Change Logs: * Date Author Notes - * 2022-07-15 Emuzit first version - * 2022-07-20 Emuzit add watchdog test - * 2022-07-26 Emuzit add hwtimer test - * 2022-07-30 Emuzit add spi master test + * 2018-11-27 balanceTWK first version */ #include -#include +#include #include -#include -#include -#include #include "board.h" -static const rt_base_t gpio_int_pins[8] = GPIO_INT_PINS; - -/* note : PIN_IRQ_MODE_RISING_FALLING not supported */ -static const uint32_t gpint_mode[] = -{ - PIN_IRQ_MODE_RISING, - PIN_IRQ_MODE_RISING, - PIN_IRQ_MODE_RISING, - PIN_IRQ_MODE_RISING, - PIN_IRQ_MODE_FALLING, - PIN_IRQ_MODE_FALLING, - PIN_IRQ_MODE_FALLING, - PIN_IRQ_MODE_FALLING, -}; - -static struct rt_mailbox *gpint_mb = RT_NULL; -static struct rt_thread *gpint_thread = RT_NULL; - -static rt_device_t wdg_dev; - -static rt_base_t led0, led1; - -static void gpio_int_callback(void *pin) -{ - led1 = (led1 == PIN_LOW) ? PIN_HIGH : PIN_LOW; - rt_pin_write(LED1_PIN, led1); - - if (gpint_mb != RT_NULL) - { - /* non-block, silently ignore RT_EFULL */ - rt_mb_send(gpint_mb, (uint32_t)pin); - } -} - -static void gpio_int_thread(void *param) -{ - while (1) - { - rt_err_t res; - uint32_t pin; - - res = rt_mb_recv(gpint_mb, &pin, RT_WAITING_FOREVER); - if (res == RT_EOK) - { - rt_kprintf("gpio_int #%d (%d)\n", pin, rt_pin_read(pin)); - } - rt_thread_mdelay(100); - -#ifdef RT_USING_WDT - rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); -#endif - } -} - -static void test_gpio_int(void) -{ - rt_err_t res; - int i; - - rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); - rt_pin_write(LED1_PIN, led1 = PIN_HIGH); - - /* Enable all gpio interrupt with various modes. - * LED0 or GND touching can be used to trigger pin interrupt. - */ - gpint_mb = rt_mb_create("pximb", 8, RT_IPC_FLAG_FIFO); - if (gpint_mb == RT_NULL) - { - rt_kprintf("gpint mailbox create failed !\n"); - } - else - { - gpint_thread = rt_thread_create("pxith", gpio_int_thread, RT_NULL, - 512, RT_MAIN_THREAD_PRIORITY, 50); - if (gpint_thread == RT_NULL) - { - rt_kprintf("gpint thread create failed !\n"); - } - else - { - rt_thread_startup(gpint_thread); - - for (i = 0; i < 8; i++) - { - rt_base_t pin = gpio_int_pins[i]; - rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP); - res = rt_pin_attach_irq( - pin, gpint_mode[i], gpio_int_callback, (void *)pin); - if (res != RT_EOK) - { - rt_kprintf("rt_pin_attach_irq failed (%d:%d)\n", i, res); - } - else - { - rt_pin_irq_enable(pin, PIN_IRQ_ENABLE); - } - } - } - } -} - -#ifdef RT_USING_WDT -static void test_watchdog(uint32_t seconds) -{ - /* Test watchdog with 30s timeout, keepalive with gpio interrupt. - * - * CAVEAT: With only 8-bit WDOG_COUNT and fixed clocking at Fsys/524288, - * watchdog of ch56x may be quite limited with very short timeout. - */ - seconds = 30; - wdg_dev = rt_device_find("wdt"); - if (!wdg_dev) - { - rt_kprintf("watchdog device not found !\n"); - } - else if (rt_device_init(wdg_dev) != RT_EOK || - rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &seconds) != RT_EOK) - { - rt_kprintf("watchdog setup failed !\n"); - } - else - { - rt_kprintf("WDT_TIMEOUT in %d seconds, trigger gpio interrupt to keep alive.\n\n", seconds); - } -} -#else - #define test_watchdog(tov) do {} while(0) -#endif - -#ifdef RT_USING_HWTIMER -static struct rt_device *tmr_dev_0; -static struct rt_device *tmr_dev_1; - -static rt_err_t tmr_timeout_cb(rt_device_t dev, rt_size_t size) -{ - rt_tick_t tick = rt_tick_get(); - - int tmr = (dev == tmr_dev_1) ? 1 : 0; - - rt_kprintf("hwtimer %d timeout callback fucntion @tick %d\n", tmr, tick); - - return RT_EOK; -} - -static void test_hwtimer(void) -{ - rt_hwtimerval_t timerval; - rt_hwtimer_mode_t mode; - rt_size_t tsize; - - /* setup two timers, ONESHOT & PERIOD each - */ - tmr_dev_0 = rt_device_find("timer0"); - tmr_dev_1 = rt_device_find("timer1"); - if (tmr_dev_0 == RT_NULL || tmr_dev_1 == RT_NULL) - { - rt_kprintf("hwtimer device(s) not found !\n"); - } - else if (rt_device_open(tmr_dev_0, RT_DEVICE_OFLAG_RDWR) != RT_EOK || - rt_device_open(tmr_dev_1, RT_DEVICE_OFLAG_RDWR) != RT_EOK) - { - rt_kprintf("hwtimer device(s) open failed !\n"); - } - else - { - rt_device_set_rx_indicate(tmr_dev_0, tmr_timeout_cb); - rt_device_set_rx_indicate(tmr_dev_1, tmr_timeout_cb); - - timerval.sec = 3; - timerval.usec = 500000; - tsize = sizeof(timerval); - mode = HWTIMER_MODE_ONESHOT; - if (rt_device_control(tmr_dev_0, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK) - { - rt_kprintf("timer0 set mode failed !\n"); - } - else if (rt_device_write(tmr_dev_0, 0, &timerval, tsize) != tsize) - { - rt_kprintf("timer0 start failed !\n"); - } - else - { - rt_kprintf("timer0 started !\n"); - } - - timerval.sec = 5; - timerval.usec = 0; - tsize = sizeof(timerval); - mode = HWTIMER_MODE_PERIOD; - if (rt_device_control(tmr_dev_1, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK) - { - rt_kprintf("timer1 set mode failed !\n"); - } - else if (rt_device_write(tmr_dev_1, 0, &timerval, tsize) != tsize) - { - rt_kprintf("timer1 start failed !\n"); - } - else - { - rt_kprintf("timer1 started !\n\n"); - } - } -} -#else - #define test_hwtimer() do {} while(0) -#endif - -#ifdef RT_USING_SPI -static struct rt_spi_device spi_dev_w25q; - -static void test_spi_master(void) -{ - struct rt_spi_configuration cfg; - struct rt_spi_message msg1, msg2; - rt_err_t res; - - uint8_t buf[16]; - - cfg.max_hz = 25 * 1000000; - cfg.data_width = 8; - cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB | RT_SPI_CS_HIGH; - - res = rt_spi_bus_attach_device( - &spi_dev_w25q, W25Q32_SPI_NAME, SPI0_BUS_NAME, (void *)W25Q32_CS_PIN); - if (res == RT_EOK && rt_spi_configure(&spi_dev_w25q, &cfg) == RT_EOK) - { - /* cmd : Read Manufacturer / Device ID (90h) */ - buf[0] = 0x90; - /* address : 0 */ - buf[1] = buf[2] = buf[3] = 0; - msg1.send_buf = buf; - msg1.recv_buf = RT_NULL; - msg1.length = 4; - msg1.cs_take = 1; - msg1.cs_release = 0; - msg1.next = &msg2; - - msg2.send_buf = RT_NULL; - msg2.recv_buf = buf; - msg2.length = 2; - msg2.cs_take = 0; - msg2.cs_release = 1; - msg2.next = RT_NULL; - - rt_spi_transfer_message(&spi_dev_w25q, &msg1); - rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", buf[0], buf[1]); - - /* cmd : Read Data (03h) */ - buf[0] = 0x03; - /* address : 0 */ - buf[1] = buf[2] = buf[3] = 0; - msg2.length = 16; - if (rt_spi_transfer_message(&spi_dev_w25q, &msg1) == RT_NULL) - { - rt_kprintf("rt_spi_transfer_message() 16-byte-read DMA done\n\n"); - } - } - else - { - rt_kprintf("w25q32 attach/configure failed (%d) !\n", res); - } -} -#else - #define test_spi_master() do {} while(0) -#endif - void main(void) { - uint32_t wdog_timeout = 32; - - rt_kprintf("\nCH569W-R0-1v0, HCLK: %dMHz\n\n", sys_hclk_get() / 1000000); - - test_gpio_int(); - test_watchdog(wdog_timeout); - test_hwtimer(); - test_spi_master(); - + /* set LED0 pin mode to output */ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); - rt_pin_write(LED0_PIN, led0 = PIN_LOW); while (1) { - /* flashing LED0 every 1 second */ + rt_pin_write(LED0_PIN, PIN_HIGH); + rt_thread_mdelay(500); + rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(500); - led0 = (led0 == PIN_LOW) ? PIN_HIGH : PIN_LOW; - rt_pin_write(LED0_PIN, led0); } } diff --git a/bsp/wch/risc-v/ch569w-evt/applications/test.c b/bsp/wch/risc-v/ch569w-evt/applications/test.c new file mode 100644 index 0000000000..4a6d114936 --- /dev/null +++ b/bsp/wch/risc-v/ch569w-evt/applications/test.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-07-15 Emuzit first version + * 2022-07-20 Emuzit add watchdog test + * 2022-07-26 Emuzit add hwtimer test + * 2022-07-30 Emuzit add spi master test + * 2022-08-04 Emuzit add pwm test + */ +#include +#include +#include +#include +#include +#include +#include +#include "board.h" + +#define PWM_CYCLE_MAX 255 + +static const rt_base_t gpio_int_pins[8] = GPIO_INT_PINS; + +/* note : PIN_IRQ_MODE_RISING_FALLING not supported */ +static const uint32_t gpint_mode[] = +{ + PIN_IRQ_MODE_RISING, + PIN_IRQ_MODE_RISING, + PIN_IRQ_MODE_RISING, + PIN_IRQ_MODE_RISING, + PIN_IRQ_MODE_FALLING, + PIN_IRQ_MODE_FALLING, + PIN_IRQ_MODE_FALLING, + PIN_IRQ_MODE_FALLING, +}; + +static struct rt_mailbox *gpint_mb = RT_NULL; +static struct rt_thread *gpint_thread = RT_NULL; + +static rt_device_t wdg_dev; + +static rt_base_t led0, led1; + +static void gpio_int_callback(void *pin) +{ + led1 = (led1 == PIN_LOW) ? PIN_HIGH : PIN_LOW; + rt_pin_write(LED1_PIN, led1); + + if (gpint_mb != RT_NULL) + { + /* non-block, silently ignore RT_EFULL */ + rt_mb_send(gpint_mb, (uint32_t)pin); + } +} + +static void gpio_int_thread(void *param) +{ + while (1) + { + rt_err_t res; + uint32_t pin; + + res = rt_mb_recv(gpint_mb, &pin, RT_WAITING_FOREVER); + if (res == RT_EOK) + { + rt_kprintf("gpio_int #%d (%d)\n", pin, rt_pin_read(pin)); + } + rt_thread_mdelay(100); + +#ifdef RT_USING_WDT + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, RT_NULL); +#endif + } +} + +static void test_gpio_int(void) +{ + rt_err_t res; + int i; + + rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT); + rt_pin_write(LED1_PIN, led1 = PIN_HIGH); + + /* Enable all gpio interrupt with various modes. + * LED0 or GND touching can be used to trigger pin interrupt. + */ + gpint_mb = rt_mb_create("pximb", 8, RT_IPC_FLAG_FIFO); + if (gpint_mb == RT_NULL) + { + rt_kprintf("gpint mailbox create failed !\n"); + } + else + { + gpint_thread = rt_thread_create("pxith", gpio_int_thread, RT_NULL, + 512, RT_MAIN_THREAD_PRIORITY, 50); + if (gpint_thread == RT_NULL) + { + rt_kprintf("gpint thread create failed !\n"); + } + else + { + rt_thread_startup(gpint_thread); + + for (i = 0; i < 8; i++) + { + rt_base_t pin = gpio_int_pins[i]; +#ifdef RT_USING_PWM + if (pin == PWM0_PIN || pin == PWM1_PIN) + continue; +#endif + rt_pin_mode(pin, PIN_MODE_INPUT_PULLUP); + res = rt_pin_attach_irq( + pin, gpint_mode[i], gpio_int_callback, (void *)pin); + if (res != RT_EOK) + { + rt_kprintf("rt_pin_attach_irq failed (%d:%d)\n", i, res); + } + else + { + rt_pin_irq_enable(pin, PIN_IRQ_ENABLE); + } + } + } + } +} + +#ifdef RT_USING_WDT +static void test_watchdog(uint32_t seconds) +{ + /* Test watchdog with 30s timeout, keepalive with gpio interrupt. + * + * CAVEAT: With only 8-bit WDOG_COUNT and fixed clocking at Fsys/524288, + * watchdog of ch56x may be quite limited with very short timeout. + */ + seconds = 30; + wdg_dev = rt_device_find("wdt"); + if (!wdg_dev) + { + rt_kprintf("watchdog device not found !\n"); + } + else if (rt_device_init(wdg_dev) != RT_EOK || + rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &seconds) != RT_EOK) + { + rt_kprintf("watchdog setup failed !\n"); + } + else + { + rt_kprintf("WDT_TIMEOUT in %d seconds, trigger gpio interrupt to keep alive.\n\n", seconds); + } +} +#else + #define test_watchdog(tov) do {} while(0) +#endif + +#ifdef RT_USING_HWTIMER +static struct rt_device *tmr_dev_0; +static struct rt_device *tmr_dev_1; + +static rt_err_t tmr_timeout_cb(rt_device_t dev, rt_size_t size) +{ + rt_tick_t tick = rt_tick_get(); + + int tmr = (dev == tmr_dev_1) ? 1 : 0; + + rt_kprintf("hwtimer %d timeout callback fucntion @tick %d\n", tmr, tick); + + return RT_EOK; +} + +static void test_hwtimer(void) +{ + rt_hwtimerval_t timerval; + rt_hwtimer_mode_t mode; + rt_size_t tsize; + + /* setup two timers, ONESHOT & PERIOD each + */ + tmr_dev_0 = rt_device_find("timer0"); + tmr_dev_1 = rt_device_find("timer1"); + if (tmr_dev_0 == RT_NULL || tmr_dev_1 == RT_NULL) + { + rt_kprintf("hwtimer device(s) not found !\n"); + } + else if (rt_device_open(tmr_dev_0, RT_DEVICE_OFLAG_RDWR) != RT_EOK || + rt_device_open(tmr_dev_1, RT_DEVICE_OFLAG_RDWR) != RT_EOK) + { + rt_kprintf("hwtimer device(s) open failed !\n"); + } + else + { + rt_device_set_rx_indicate(tmr_dev_0, tmr_timeout_cb); + rt_device_set_rx_indicate(tmr_dev_1, tmr_timeout_cb); + + timerval.sec = 3; + timerval.usec = 500000; + tsize = sizeof(timerval); + mode = HWTIMER_MODE_ONESHOT; + if (rt_device_control(tmr_dev_0, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK) + { + rt_kprintf("timer0 set mode failed !\n"); + } + else if (rt_device_write(tmr_dev_0, 0, &timerval, tsize) != tsize) + { + rt_kprintf("timer0 start failed !\n"); + } + else + { + rt_kprintf("timer0 started !\n"); + } + + timerval.sec = 5; + timerval.usec = 0; + tsize = sizeof(timerval); + mode = HWTIMER_MODE_PERIOD; + if (rt_device_control(tmr_dev_1, HWTIMER_CTRL_MODE_SET, &mode) != RT_EOK) + { + rt_kprintf("timer1 set mode failed !\n"); + } + else if (rt_device_write(tmr_dev_1, 0, &timerval, tsize) != tsize) + { + rt_kprintf("timer1 start failed !\n"); + } + else + { + rt_kprintf("timer1 started !\n\n"); + } + } +} +#else + #define test_hwtimer() do {} while(0) +#endif + +#ifdef RT_USING_SPI +static struct rt_spi_device spi_dev_w25q; + +static void test_spi_master(void) +{ + struct rt_spi_configuration cfg; + struct rt_spi_message msg1, msg2; + rt_err_t res; + + uint8_t buf[16]; + int i; + + cfg.max_hz = 25 * 1000000; + cfg.data_width = 8; + cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB; + + res = rt_spi_bus_attach_device( + &spi_dev_w25q, W25Q32_SPI_NAME, SPI0_BUS_NAME, (void *)W25Q32_CS_PIN); + if (res == RT_EOK && rt_spi_configure(&spi_dev_w25q, &cfg) == RT_EOK) + { + /* cmd : Read Manufacturer / Device ID (90h) */ + buf[0] = 0x90; + /* address : 0 */ + buf[1] = buf[2] = buf[3] = 0; + msg1.send_buf = buf; + msg1.recv_buf = RT_NULL; + msg1.length = 4; + msg1.cs_take = 1; + msg1.cs_release = 0; + msg1.next = &msg2; + + msg2.send_buf = RT_NULL; + msg2.recv_buf = buf; + msg2.length = 2; + msg2.cs_take = 0; + msg2.cs_release = 1; + msg2.next = RT_NULL; + + rt_spi_transfer_message(&spi_dev_w25q, &msg1); + rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", buf[0], buf[1]); + + /* cmd : Read Data (03h) */ + buf[0] = 0x03; + /* address : 0 */ + buf[1] = buf[2] = buf[3] = 0; + msg2.length = 16; + if (rt_spi_transfer_message(&spi_dev_w25q, &msg1) == RT_NULL) + { + rt_kprintf("SPI0 16-byte DMA read :"); + for (i = 0; i < 16; i++) + rt_kprintf(" %02x", buf[i]); + rt_kprintf("\n\n"); + } + } + else + { + rt_kprintf("w25q32 attach/configure failed (%d) !\n", res); + } +} +#else + #define test_spi_master() do {} while(0) +#endif + +#ifdef RT_USING_PWM +static struct rt_device_pwm *pwm_dev; +static uint32_t pwm_period; + +rt_err_t rt_pwm_get(struct rt_device_pwm *device, + struct rt_pwm_configuration *cfg); + +static void pwm_tick_hook(void) +{ + uint32_t pulse; + + if (pwm_dev) + { + /* PWM.CH3 duty cycle : 0%->100% for every ~2.5 seconds */ + pulse = (rt_tick_get() >> 1) % (PWM_CYCLE_MAX + 1); + pulse = (pwm_period * pulse + PWM_CYCLE_MAX/2) / PWM_CYCLE_MAX; + rt_pwm_set_pulse(pwm_dev, 3, pulse); + } +} + +static void test_pwm(void) +{ + struct rt_pwm_configuration cfg; + uint32_t pulse[4]; + int ch; + + pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEVICE_NAME); + if (pwm_dev == RT_NULL) + { + rt_kprintf("can't find %s device !\n", PWM_DEVICE_NAME); + } + else + { + /* for HCLK@80MHz, allowed period is 3187 ~ 812812 */ + pwm_period = 800*1000; + + pulse[0] = 100*1000; + pulse[1] = 400*1000; + pulse[2] = 600*1000; + pulse[3] = 0; + + for (ch = 0; ch < PWM_CHANNELS; ch++) + { + rt_pwm_set(pwm_dev, ch, pwm_period, pulse[ch]); + rt_pwm_enable(pwm_dev, ch); + + cfg.channel = ch; + rt_pwm_get(pwm_dev, &cfg); + rt_kprintf("pwm%d period set/get : %d/%d\n", ch, pwm_period, cfg.period); + rt_kprintf("pwm%d pulse set/get : %d/%d\n\n", ch, pulse[ch], cfg.pulse); + } + + /* disable PWM.CH0 after 1 second, also start changing CH3 */ + rt_thread_mdelay(1000); + rt_pwm_disable(pwm_dev, 0); + + /* connect PWM3 (PB.2) to LED2 for a visualized PWM effect */ + rt_pin_mode(LED2_PIN, PIN_MODE_INPUT); + rt_tick_sethook(pwm_tick_hook); + } +} +#else + #define test_pwm() do {} while(0) +#endif + +void main(void) +{ + uint32_t wdog_timeout = 32; + + rt_kprintf("\nCH569W-R0-1v0, HCLK: %dMHz\n\n", sys_hclk_get() / 1000000); + + test_gpio_int(); + test_watchdog(wdog_timeout); + test_hwtimer(); + test_spi_master(); + test_pwm(); + + rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); + rt_pin_write(LED0_PIN, led0 = PIN_LOW); + + while (1) + { + /* flashing LED0 every 1 second */ + rt_thread_mdelay(500); + led0 = (led0 == PIN_LOW) ? PIN_HIGH : PIN_LOW; + rt_pin_write(LED0_PIN, led0); + } +} diff --git a/bsp/wch/risc-v/ch569w-evt/board/Kconfig b/bsp/wch/risc-v/ch569w-evt/board/Kconfig index c760c1338b..2f23098a3c 100644 --- a/bsp/wch/risc-v/ch569w-evt/board/Kconfig +++ b/bsp/wch/risc-v/ch569w-evt/board/Kconfig @@ -17,20 +17,25 @@ config BSP_USING_UART if BSP_USING_UART config BSP_USING_UART0 - bool "using UART0" - default n + bool "using UART0" + default n + if BSP_USING_UART0 + config BSP_USING_UART0_PIN_ALT + bool "UART0 PIN_ALTERNATE (PA5/PA6)" + default n + endif config BSP_USING_UART1 - bool "using UART1" - default y + bool "using UART1" + default y config BSP_USING_UART2 - bool "using UART2" - default n + bool "using UART2" + default n config BSP_USING_UART3 - bool "using UART3" - default n + bool "using UART3" + default n endif config BSP_USING_TIMER @@ -40,16 +45,16 @@ config BSP_USING_TIMER if BSP_USING_TIMER config BSP_USING_TMR0 - bool "using TMR0" - default y + bool "using TMR0" + default n config BSP_USING_TMR1 - bool "using TMR1" - default n + bool "using TMR1" + default n config BSP_USING_TMR2 - bool "using TMR2" - default n + bool "using TMR2" + default n endif config BSP_USING_SPI diff --git a/bsp/wch/risc-v/ch569w-evt/board/board.c b/bsp/wch/risc-v/ch569w-evt/board/board.c index 6b4b6dbc81..03c699b1bb 100644 --- a/bsp/wch/risc-v/ch569w-evt/board/board.c +++ b/bsp/wch/risc-v/ch569w-evt/board/board.c @@ -69,9 +69,6 @@ void rt_hw_board_init() #endif #ifdef RT_USING_CONSOLE - /* console is uart1, TXD1/RXD1 : PA8/PA7 */ - rt_pin_mode(GET_PIN(A, 8), PIN_MODE_OUTPUT); - rt_pin_mode(GET_PIN(A, 7), PIN_MODE_INPUT_PULLUP); rt_hw_uart_init(); rt_console_set_device(RT_CONSOLE_DEVICE_NAME); #endif diff --git a/bsp/wch/risc-v/ch569w-evt/board/board.h b/bsp/wch/risc-v/ch569w-evt/board/board.h index 08a5c5b9d2..5956d55082 100644 --- a/bsp/wch/risc-v/ch569w-evt/board/board.h +++ b/bsp/wch/risc-v/ch569w-evt/board/board.h @@ -14,6 +14,7 @@ #include "ch56x_sys.h" #include "ch56x_gpio.h" #include "ch56x_spi.h" +#include "ch56x_pwm.h" #define LED0_PIN GET_PIN(B, 24) #define LED1_PIN GET_PIN(B, 22) diff --git a/bsp/wch/risc-v/ch569w-evt/rtconfig.h b/bsp/wch/risc-v/ch569w-evt/rtconfig.h index acf5ce234f..3a2d452356 100644 --- a/bsp/wch/risc-v/ch569w-evt/rtconfig.h +++ b/bsp/wch/risc-v/ch569w-evt/rtconfig.h @@ -70,10 +70,7 @@ #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_HWTIMER #define RT_USING_PIN -#define RT_USING_SPI -#define RT_USING_WDT /* Using USB */ @@ -181,11 +178,6 @@ #define BSP_USING_UART #define BSP_USING_UART1 -#define BSP_USING_TIMER -#define BSP_USING_TMR0 -#define BSP_USING_TMR1 -#define BSP_USING_SPI -#define BSP_USING_SPI0 /* Onboard Peripheral Drivers */