diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c index ceae24365..be4f3b20c 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/board.c @@ -28,6 +28,7 @@ * @date 2024-4-29 */ #include "ch32v20x.h" +#include "connect_can.h" #include "connect_uart.h" #include "core_riscv.h" #include "xsconfig.h" @@ -86,6 +87,9 @@ void InitBoardHardware() #ifdef BSP_USING_BLE WCHBLE_Init(); HAL_Init(); +#endif +#ifdef BSP_USING_CAN + InitHwCan(); #endif KPrintf("consle init completed.\n"); KPrintf("board initialization......\n"); diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig index a431fca48..a91fcbebd 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Kconfig @@ -17,4 +17,12 @@ menuconfig BSP_USING_ADC menuconfig BSP_USING_BLE bool "Using BLE" default y + +menuconfig BSP_USING_CAN + bool "Using CAN device" + default y + select RESOURCES_CAN + if BSP_USING_CAN + source "$BSP_DIR/third_party_driver/can/Kconfig" + endif \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile index 583632455..90ba02065 100644 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/Makefile @@ -13,4 +13,7 @@ endif ifeq ($(CONFIG_BSP_USING_BLE),y) SRC_DIR += ble endif +ifeq ($(CONFIG_BSP_USING_CAN),y) + SRC_DIR += can +endif include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ble/test/peripheral_main.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ble/test/peripheral_main.c index 77b8582ed..6acb42626 100755 --- a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ble/test/peripheral_main.c +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/ble/test/peripheral_main.c @@ -62,6 +62,8 @@ void Main_Circulation(void) int test_ble(int argc, char *argv[]) { KPrintf("%s\n", VER_LIB); + WCHBLE_Init(); + HAL_Init(); GAPRole_PeripheralInit(); Peripheral_Init(); KPrintf("BLE Peripheral Slave Init Success.\n"); diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/Makefile new file mode 100755 index 000000000..f3fd6ea31 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := connect_can.c +SRC_DIR := test + +include $(KERNEL_ROOT)/compiler.mk \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/connect_can.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/connect_can.c new file mode 100644 index 000000000..6110f54c6 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/connect_can.c @@ -0,0 +1,248 @@ + +#include +#include +#include +#include + +static struct CanSendConfigure can_send_deconfig = +{ + .stdid = 0x12, + .exdid = 0x12, + .ide = 0 , + .rtr = 0, + .data_lenth = 8 +}; + +static void CanGPIOInit(void) +{ + CAN_FilterInitTypeDef can1_filter = {0}; + GPIO_InitTypeDef gpio_initstructure = {0}; + CAN_InitTypeDef can_initstruction = {0}; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOA, ENABLE); // 如果CAN引脚映射到PA,需要设置A时钟源,否则设置成B时钟源 + RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); + + // GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE); + /* 这里需要和原理图的引脚对应 */ + gpio_initstructure.GPIO_Pin = GPIO_Pin_12; // CAN1_TX + gpio_initstructure.GPIO_Mode = GPIO_Mode_AF_PP; + gpio_initstructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &gpio_initstructure); // 初始化引脚 + gpio_initstructure.GPIO_Pin = GPIO_Pin_11; // CAN1_RX + gpio_initstructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_Init(GPIOA, &gpio_initstructure); // 初始化引脚 +} + +static void Can1NvicConfig(void) +{ + NVIC_InitTypeDef can_nvic_config; + + can_nvic_config.NVIC_IRQChannel = CAN1_RX1_IRQn; + can_nvic_config.NVIC_IRQChannelPreemptionPriority = 2; + can_nvic_config.NVIC_IRQChannelSubPriority = 2; + can_nvic_config.NVIC_IRQChannelCmd = ENABLE; + CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); + NVIC_Init(&can_nvic_config); +} + +static uint32 CanModeInit(void *drv, struct BusConfigureInfo *configure_info) +{ + NULL_PARAM_CHECK(drv); + NULL_PARAM_CHECK(configure_info); + CAN_FilterInitTypeDef can1_filter; + CAN_InitTypeDef can_initstruction; + + struct CanDriverConfigure *config = ( struct CanDriverConfigure *)configure_info->private_data; + + can_initstruction.CAN_TTCM = DISABLE; + can_initstruction.CAN_ABOM = DISABLE; + can_initstruction.CAN_AWUM = DISABLE; + can_initstruction.CAN_NART = ENABLE; + can_initstruction.CAN_TXFP = DISABLE; + can_initstruction.CAN_Mode = config->mode; + can_initstruction.CAN_RFLM = DISABLE; + can_initstruction.CAN_SJW = config->tsjw; + can_initstruction.CAN_BS1 = config->tbs1; + can_initstruction.CAN_BS2 = config->tbs2; + can_initstruction.CAN_Prescaler = config->brp; + + CAN_Init(CAN1, &can_initstruction); + + can1_filter.CAN_FilterNumber=0; + can1_filter.CAN_FilterMode=CAN_FilterMode_IdMask; + can1_filter.CAN_FilterScale=CAN_FilterScale_32bit; + can1_filter.CAN_FilterIdHigh=0x0000; + can1_filter.CAN_FilterIdLow=0x0000; + can1_filter.CAN_FilterMaskIdHigh=0x0000; + can1_filter.CAN_FilterMaskIdLow=0x0006; + can1_filter.CAN_FilterFIFOAssignment=CAN_Filter_FIFO1; + can1_filter.CAN_FilterActivation=ENABLE; + CAN_FilterInit(&can1_filter); + + #ifdef CAN_USING_INTERRUPT + Can1NvicConfig(); + #endif + + return 0; +} + +static uint32 CanSendMsg(void * dev , struct BusBlockWriteParam *write_param ) +{ + NULL_PARAM_CHECK(write_param); + + uint8 *data = (uint8 * ) write_param->buffer; + u8 messege_box; + u16 i = 0; + u16 timer_count = 1000; + CanTxMsg tx_data; + tx_data.StdId = 0x55; + tx_data.ExtId = 0x00; + tx_data.IDE = 0; + tx_data.RTR = 0; + tx_data.DLC = write_param->size; + + for(i = 0;i < tx_data.DLC;i ++) { + tx_data.Data[i] = data[i]; + } + + messege_box = CAN_Transmit(CAN1,&tx_data); + + while (CAN_TransmitStatus(CAN1,messege_box)== CAN_TxStatus_Failed &&timer_count) { + timer_count--; + } + + if (timer_count<=0) { + return ERROR; + } + return EOK; +} + +static uint32 CanRecvMsg(void *dev , struct BusBlockReadParam *databuf) +{ + NULL_PARAM_CHECK(dev); + int i; + uint8 * buf = (uint8 *)databuf->buffer; + CanRxMsg msg; + if (CAN_MessagePending(CAN1, CAN_FIFO0) == 0) + return 0; + CAN_Receive(CAN1, CAN_FIFO0, &msg); + for(i = 0 ;i < msg.DLC;i ++) + buf[i] = msg.Data[i]; + databuf->size = msg.DLC ; + + return msg.DLC; +} + +static struct CanDevDone dev_done = +{ + .open = NONE, + .close = NONE, + .write = CanSendMsg, + .read = CanRecvMsg +}; + +static struct CanHardwareDevice dev; + +#ifdef CAN_USING_INTERRUPT +void CAN1_RX0_IRQHandler(void) +{ + CanRxMsg rxmsg; + int i = 0; + CAN_Receive(CAN1, 0, &rxmsg); + for (i = 0;i < 8;i ++) + KPrintf("rxbuf [%d] = :%d",i,rxmsg.Data[i]); +} +DECLARE_HW_IRQ(CAN1_RX0_IRQn, CAN1_RX0_IRQHandler, NONE); +#endif + +static int BoardCanBusInit(struct CanDev *CanDev_bus, struct CanDriver *can_driver) +{ + x_err_t ret = EOK; + + /*Init the can bus */ + ret = CanBusInit(&CanDev_bus->can_bus, CanDev_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_can_init canBusInit error %d\n", ret); + return ERROR; + } + + /*Init the can driver*/ + ret = CanDriverInit(can_driver, CAN_DRIVER_NAME); + if (EOK != ret) { + KPrintf("Board_can_init canDriverInit error %d\n", ret); + return ERROR; + } + + /*Attach the can driver to the can bus*/ + ret = CanDriverAttachToBus(CAN_DRIVER_NAME, CanDev_bus->bus_name); + if (EOK != ret) { + KPrintf("Board_can_init CanDriverAttachToBus error %d\n", ret); + return ERROR; + } + + return ret; +} + +static x_err_t HwCanDeviceAttach(const char *bus_name, const char *device_name) +{ + NULL_PARAM_CHECK(bus_name); + NULL_PARAM_CHECK(device_name); + + x_err_t result; + struct CanHardwareDevice *can_device; + + /* attach the device to can bus*/ + can_device = (struct CanHardwareDevice *)x_malloc(sizeof(struct CanHardwareDevice)); + CHECK(can_device); + memset(can_device, 0, sizeof(struct CanHardwareDevice)); + can_device->dev_done = &dev_done; + + result = CanDeviceRegister(can_device, NONE, device_name); + if (EOK != result) { + KPrintf("board_can_init canDeviceInit device %s error %d\n", "can1", result); + return ERROR; + } + + result = CanDeviceAttachToBus(device_name, bus_name); + if (result != EOK) { + SYS_ERR("%s attach to %s faild, %d\n", device_name, bus_name, result); + } + + CHECK(result == EOK); + + KPrintf("%s attach to %s done\n", device_name, bus_name); + + return result; +} + +struct CanDev can1; + +int InitHwCan(void) +{ + x_err_t ret = EOK; + struct CanDev *can_bus; + + static struct CanDriver can_driver; + memset(&can_driver, 0, sizeof(struct CanDriver)); + can_driver.configure = CanModeInit; + + CanGPIOInit(); + can_bus = &can1; + can_bus->instance = CAN1; + can_bus->bus_name = CAN_BUS_NAME_1; + can_bus->can_bus.private_data = &can1; + + ret = BoardCanBusInit(can_bus, &can_driver); + + if (EOK != ret) { + KPrintf(" can_bus_init %s error ret %u\n", can_bus->bus_name, ret); + return ERROR; + } + + ret = HwCanDeviceAttach(CAN_BUS_NAME_1,CAN_1_DEVICE_NAME_1); + if (EOK != ret) { + KPrintf(" HwCanDeviceAttach %s error ret %u\n", can_bus->bus_name, ret); + return ERROR; + } + return EOK; +} \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/Makefile b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/Makefile new file mode 100755 index 000000000..44c989594 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/Makefile @@ -0,0 +1,4 @@ +SRC_FILES := can_test.c + + +include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/can_test.c b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/can_test.c new file mode 100644 index 000000000..df4a88a22 --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/can/test/can_test.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2020 AIIT XUOS Lab + * XiUOS is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan + * PSL v2. You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY + * KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO + * NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the + * Mulan PSL v2 for more details. + */ + +/** + * @file can_test.c + * @brief test ch32v307 can + * @version 1.0 + * @author AIIT XUOS Lab + * @date 2024-03-14 + */ +#include +#include +#include + +#include "ch32v20x.h" +#include "connect_can.h" +#include "debug.h" +#include "shell.h" + +/* CAN Mode Definition */ +#define TX_MODE 0 +#define RX_MODE 1 + +/* Frame Format Definition */ +#define Standard_Frame 0 +#define Extended_Frame 1 + +/* CAN Communication Mode Selection */ +#define CAN_MODE TX_MODE +// #define CAN_MODE RX_MODE + +/* Frame Formate Selection */ +#define Frame_Format Standard_Frame +// #define Frame_Format Extended_Frame + +/********************************************************************* + * @fn CAN_Mode_Init + * + * @brief Initializes CAN communication test mode. + * Bps =Fpclk1/((tpb1+1+tbs2+1+1)*brp) + * 波特率设置https://www.cnblogs.com/wchmcu/p/17546797.html + * + * @param tsjw - CAN synchronisation jump width. + * tbs2 - CAN time quantum in bit segment 1. + * tbs1 - CAN time quantum in bit segment 2. + * brp - Specifies the length of a time quantum. + * mode - Test mode. + * CAN_Mode_Normal. + * CAN_Mode_LoopBack. + * CAN_Mode_Silent. + * CAN_Mode_Silent_LoopBack. + * + * @return none + */ +static int init_can(u8 tsjw, u8 tbs2, u8 tbs1, u16 brp, u8 mode) { + CAN_InitTypeDef CAN_InitSturcture = {0}; + CAN_FilterInitTypeDef CAN_FilterInitSturcture = {0}; + + CAN_InitSturcture.CAN_TTCM = DISABLE; + CAN_InitSturcture.CAN_ABOM = DISABLE; + CAN_InitSturcture.CAN_AWUM = DISABLE; + CAN_InitSturcture.CAN_NART = ENABLE; + CAN_InitSturcture.CAN_RFLM = DISABLE; + CAN_InitSturcture.CAN_TXFP = DISABLE; + CAN_InitSturcture.CAN_Mode = mode; + CAN_InitSturcture.CAN_SJW = tsjw; + CAN_InitSturcture.CAN_BS1 = tbs1; + CAN_InitSturcture.CAN_BS2 = tbs2; + CAN_InitSturcture.CAN_Prescaler = brp; + CAN_Init(CAN1, &CAN_InitSturcture); + + CAN_FilterInitSturcture.CAN_FilterNumber = 0; + +#if (Frame_Format == Standard_Frame) + /* identifier/mask mode, One 32-bit filter, StdId: 0x317 */ + CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask; + CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit; + CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0; + CAN_FilterInitSturcture.CAN_FilterIdLow = 0; + CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0xFFE0; + CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x0006; + + /* identifier/mask mode, Two 16-bit filters, StdId: 0x317锟斤拷0x316 */ + // CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask; + // CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_16bit; + // CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0; + // CAN_FilterInitSturcture.CAN_FilterIdLow = 0xFFF8; + // CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x62C0; + // CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0xFFF8; + + /* identifier list mode, One 32-bit filter, StdId: 0x317锟斤拷0x316 */ + // CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList; + // CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit; + // CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0; + // CAN_FilterInitSturcture.CAN_FilterIdLow = 0; + // CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x62C0; + // CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0; + + /* identifier list mode, Two 16-bit filters, StdId: 0x317,0x316,0x315,0x314 + */ + // CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdList; + // CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_16bit; + // CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x62E0; + // CAN_FilterInitSturcture.CAN_FilterIdLow = 0x62C0; + // CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0x62A0; + // CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0x6280; + +#elif (Frame_Format == Extended_Frame) + /* identifier/mask mode, One 32-bit filter, ExtId: 0x12124567 */ + CAN_FilterInitSturcture.CAN_FilterMode = CAN_FilterMode_IdMask; + CAN_FilterInitSturcture.CAN_FilterScale = CAN_FilterScale_32bit; + CAN_FilterInitSturcture.CAN_FilterIdHigh = 0x9092; + CAN_FilterInitSturcture.CAN_FilterIdLow = 0x2B3C; + CAN_FilterInitSturcture.CAN_FilterMaskIdHigh = 0xFFFF; + CAN_FilterInitSturcture.CAN_FilterMaskIdLow = 0xFFFE; + +#endif + + CAN_FilterInitSturcture.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; + CAN_FilterInitSturcture.CAN_FilterActivation = ENABLE; + CAN_FilterInit(&CAN_FilterInitSturcture); + + return 0; +} + +static u8 CAN_Send_Msg(u8 *msg, u8 len) { + u8 mbox; + u16 i = 0; + + CanTxMsg CanTxStructure; + + CanTxStructure.StdId = 0x317; + CanTxStructure.IDE = CAN_Id_Standard; + CanTxStructure.RTR = CAN_RTR_Data; + CanTxStructure.DLC = len; + + for (i = 0; i < len; i++) { + CanTxStructure.Data[i] = msg[i]; + } + + mbox = CAN_Transmit(CAN1, &CanTxStructure); + + i = 0; + + while ((CAN_TransmitStatus(CAN1, mbox) != CAN_TxStatus_Ok) && (i < 0xFFF)) { + i++; + } + + if (i == 0xFFF) { + return 1; + } else { + return 0; + } +} + +static u8 CAN_Receive_Msg(u8 *buf) { + u8 i; + + CanRxMsg CanRxStructure; + + if (CAN_MessagePending(CAN1, CAN_FIFO1) == 0) { + return 0; + } + + CAN_Receive(CAN1, CAN_FIFO1, &CanRxStructure); + + for (i = 0; i < 8; i++) { + buf[i] = CanRxStructure.Data[i]; + } + + return CanRxStructure.DLC; +} + +int test_can(int argc, char *argv[]) { + u8 i; + u8 cnt = 0; + u8 tx, rx; + u8 txbuf[8]; + u8 rxbuf[8]; + init_can( + CAN_SJW_1tq, CAN_BS2_5tq, CAN_BS1_6tq, 20, + CAN_Mode_Normal); // 在这种参数下,设置时钟源为外部时钟120M,对应的波特率是250kbps +#if (CAN_MODE == TX_MODE) + for (cnt = 0; cnt < 8; cnt++) { + for (i = 0; i < 8; i++) { + txbuf[i] = cnt + i; + } + tx = CAN_Send_Msg(txbuf, 8); + + if (tx) { + KPrintf("CAN1 Send Failed\r\n"); + } else { + KPrintf("CAN1 Send Success\r\n"); + KPrintf("CAN1 Send Data:\r\n"); + + for (i = 0; i < 8; i++) { + KPrintf("%02x\r\n", txbuf[i]); + } + } + Delay_Ms(1000); + } +#elif (CAN_MODE == RX_MODE) + rx = CAN_Receive_Msg(rxbuf); + + if (rx) { + KPrintf("CAN1 Receive Data:\r\n"); + + for (i = 0; i < 8; i++) { + KPrintf("%02x\r\n", txbuf[i]); + } + } else { + KPrintf("CAN1 No Receive Data\r\n"); + } +#endif + return 0; +} + +SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), + test_can, test_can, test CAN); \ No newline at end of file diff --git a/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_can.h b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_can.h new file mode 100644 index 000000000..47e0c494b --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/board/ch32v208rbt6/third_party_driver/include/connect_can.h @@ -0,0 +1,33 @@ + + + + + + +#ifndef CONNECT_CAN_H +#define CONNECT_CAN_H + + +#include +#include + + +#include +#include + + +struct CanDev +{ + CAN_TypeDef *instance; + + char *bus_name; + + // CAN_InitTypeDef init; + + uint8 can_flag; + struct CanBus can_bus; +}; + +int InitHwCan(void); + +#endif \ No newline at end of file