diff --git a/bsp/at32/Libraries/AT32_Std_Driver/AT32F4xx_StdPeriph_Driver/inc/at32f4xx_ertc.h b/bsp/at32/Libraries/AT32_Std_Driver/AT32F4xx_StdPeriph_Driver/inc/at32f4xx_ertc.h index d133b594ed6d70cfc5d3e52be1057f5edaa2fbeb..4ec1055642ef43b782e58ee2a34b437d990dfb4b 100644 --- a/bsp/at32/Libraries/AT32_Std_Driver/AT32F4xx_StdPeriph_Driver/inc/at32f4xx_ertc.h +++ b/bsp/at32/Libraries/AT32_Std_Driver/AT32F4xx_StdPeriph_Driver/inc/at32f4xx_ertc.h @@ -11,6 +11,9 @@ #ifndef __AT32F4xx_ERTC_H #define __AT32F4xx_ERTC_H +#ifdef __cplusplus +extern "C" { +#endif /* Includes ------------------------------------------------------------------*/ #include "at32f4xx.h" diff --git a/bsp/at32/Libraries/rt_drivers/SConscript b/bsp/at32/Libraries/rt_drivers/SConscript index 52758085ee09d2383d139bf6090fba19aae4bec0..7f59cd06f389d839d94400fe8c540f445d837931 100644 --- a/bsp/at32/Libraries/rt_drivers/SConscript +++ b/bsp/at32/Libraries/rt_drivers/SConscript @@ -43,9 +43,15 @@ if GetDepend('BSP_USING_SRAM'): if GetDepend('BSP_USING_RTC'): src += ['drv_rtc.c'] +if GetDepend('BSP_USING_ON_CHIP_FLASH'): + src += ['drv_flash.c'] + if GetDepend(['BSP_USING_WDT']): src += ['drv_wdt.c'] +if GetDepend(['BSP_USING_CAN']): + src += ['drv_can.c'] + if GetDepend(['BSP_USING_SDIO']): src += ['drv_sdio.c'] diff --git a/bsp/at32/Libraries/rt_drivers/drv_can.c b/bsp/at32/Libraries/rt_drivers/drv_can.c new file mode 100644 index 0000000000000000000000000000000000000000..43f5a287e3825d3a54474734b1a721c9a5ddaf9f --- /dev/null +++ b/bsp/at32/Libraries/rt_drivers/drv_can.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-09 shelton the first version + */ + +#include "drv_can.h" +#ifdef BSP_USING_CAN + +#define LOG_TAG "drv_can" +#include + +/* attention !!! baud calculation example: apbclk / ((ss + bs1 + bs2) * brp), ep: 120 / ((1 + 8 + 3) * 10) = 1MHz*/ +static const struct at32_baud_rate_tab can_baud_rate_tab[] = +{ + {CAN1MBaud, CAN_SJW_2tq, CAN_BS1_8tq, CAN_BS2_3tq, 10}, + {CAN800kBaud, CAN_SJW_2tq, CAN_BS1_7tq, CAN_BS2_2tq, 15}, + {CAN500kBaud, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_2tq, 20}, + {CAN250kBaud, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_2tq, 40}, + {CAN125kBaud, CAN_SJW_2tq, CAN_BS1_9tq, CAN_BS2_2tq, 80}, + {CAN100kBaud, CAN_SJW_2tq, CAN_BS1_13tq, CAN_BS2_2tq, 75}, + {CAN50kBaud, CAN_SJW_2tq, CAN_BS1_13tq, CAN_BS2_2tq, 150}, + {CAN20kBaud, CAN_SJW_2tq, CAN_BS1_13tq, CAN_BS2_2tq, 375}, + {CAN10kBaud, CAN_SJW_2tq, CAN_BS1_13tq, CAN_BS2_2tq, 750} +}; + +#ifdef BSP_USING_CAN1 +static struct at32_can can_instance1 = +{ + .name = "can1", + .CanConfig.Instance = CAN1, +}; +#endif + +#ifdef BSP_USING_CAN2 +static struct at32_can can_instance2 = +{ + .name = "can2", + .CanConfig.Instance = CAN2, +}; +#endif + +static rt_uint32_t get_can_baud_index(rt_uint32_t baud) +{ + rt_uint32_t len, index; + + len = sizeof(can_baud_rate_tab) / sizeof(can_baud_rate_tab[0]); + for (index = 0; index < len; index++) + { + if (can_baud_rate_tab[index].baud_rate == baud) + return index; + } + + return 0; /* default baud is CAN1MBaud */ +} + +static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg) +{ + struct at32_can *can_instance; + rt_uint32_t baud_index; + + RT_ASSERT(can); + RT_ASSERT(cfg); + can_instance = (struct at32_can *)can->parent.user_data; + RT_ASSERT(can_instance); + + at32_msp_can_init((void *)can_instance->CanConfig.Instance); + + CAN_StructInit(&(can_instance->CanConfig.CanInit)); + + can_instance->CanConfig.CanInit.CAN_Mode = DISABLE; + can_instance->CanConfig.CanInit.CAN_ABO = ENABLE; + can_instance->CanConfig.CanInit.CAN_AWU = ENABLE; + can_instance->CanConfig.CanInit.CAN_NART = DISABLE; + can_instance->CanConfig.CanInit.CAN_RFL = DISABLE; + can_instance->CanConfig.CanInit.CAN_TFP = ENABLE; + + switch (cfg->mode) + { + case RT_CAN_MODE_NORMAL: + can_instance->CanConfig.CanInit.CAN_Mode = CAN_Mode_Normal; + break; + case RT_CAN_MODE_LISEN: + can_instance->CanConfig.CanInit.CAN_Mode = CAN_Mode_Silent; + break; + case RT_CAN_MODE_LOOPBACK: + can_instance->CanConfig.CanInit.CAN_Mode = CAN_Mode_LoopBack; + break; + case RT_CAN_MODE_LOOPBACKANLISEN: + can_instance->CanConfig.CanInit.CAN_Mode = CAN_Mode_Silent_LoopBack; + break; + } + + baud_index = get_can_baud_index(cfg->baud_rate); + can_instance->CanConfig.CanInit.CAN_SJW = can_baud_rate_tab[baud_index].sjw; + can_instance->CanConfig.CanInit.CAN_BS1 = can_baud_rate_tab[baud_index].bs1; + can_instance->CanConfig.CanInit.CAN_BS2 = can_baud_rate_tab[baud_index].bs2; + can_instance->CanConfig.CanInit.CAN_Prescaler = can_baud_rate_tab[baud_index].psc; + + /* init can */ + if (CAN_Init(can_instance->CanConfig.Instance, &(can_instance->CanConfig.CanInit)) != CAN_InitStatus_Success) + { + return -RT_ERROR; + } + + /* default filter config */ + CAN_FilterInit(can_instance->CanConfig.Instance, &can_instance->CanConfig.FilterConfig); + + return RT_EOK; +} + +static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg) +{ + rt_uint32_t argval; + NVIC_InitType NVIC_InitStruct; + struct at32_can *can_instance; + struct rt_can_filter_config *filter_cfg; + + RT_ASSERT(can != RT_NULL); + can_instance = (struct at32_can *)can->parent.user_data; + RT_ASSERT(can_instance != RT_NULL); + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: + argval = (rt_uint32_t) arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + + NVIC_InitStruct.NVIC_IRQChannel = CAN1_RX1_IRQn; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_RX0_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + + NVIC_InitStruct.NVIC_IRQChannel = CAN2_RX1_IRQn; + NVIC_Init(&NVIC_InitStruct); + } +#endif + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFP0, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFFU0, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFOV0, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFP1, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFFU1, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFOV1, DISABLE); + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_TX_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#endif + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_TSME, DISABLE); + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN1_SCE_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_SCE_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#endif + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERG, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERP, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_BU, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_LEC, DISABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERR, DISABLE); + } + break; + case RT_DEVICE_CTRL_SET_INT: + argval = (rt_uint32_t) arg; + if (argval == RT_DEVICE_FLAG_INT_RX) + { + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFP0, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFFU0, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFOV0, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFP1, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFFU1, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_RFOV1, ENABLE); + + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + + NVIC_InitStruct.NVIC_IRQChannel = CAN1_RX1_IRQn; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_RX0_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + + NVIC_InitStruct.NVIC_IRQChannel = CAN2_RX1_IRQn; + NVIC_Init(&NVIC_InitStruct); + } +#endif + } + else if (argval == RT_DEVICE_FLAG_INT_TX) + { + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_TSME, ENABLE); + + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = USB_HP_CAN1_TX_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_TX_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#endif + } + else if (argval == RT_DEVICE_CAN_INT_ERR) + { + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERG, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERP, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_BU, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_LEC, ENABLE); + CAN_INTConfig(can_instance->CanConfig.Instance, CAN_INT_ERR, ENABLE); + + if (CAN1 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN1_SCE_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#ifdef CAN2 + if (CAN2 == can_instance->CanConfig.Instance) + { + NVIC_InitStruct.NVIC_IRQChannel = CAN2_SCE_IRQn; + NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; + NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; + NVIC_Init(&NVIC_InitStruct); + } +#endif + } + break; + case RT_CAN_CMD_SET_FILTER: + if (RT_NULL == arg) + { + /* default filter config */ + CAN_FilterInit(can_instance->CanConfig.Instance, &can_instance->CanConfig.FilterConfig); + } + else + { + filter_cfg = (struct rt_can_filter_config *)arg; + /* get default filter */ + for (int i = 0; i < filter_cfg->count; i++) + { + can_instance->CanConfig.FilterConfig.CAN_FilterNumber = filter_cfg->items[i].hdr & (0x1fU); + can_instance->CanConfig.FilterConfig.CAN_FilterIdHigh = (filter_cfg->items[i].id >> 13) & 0xFFFF; + can_instance->CanConfig.FilterConfig.CAN_FilterIdLow = ((filter_cfg->items[i].id << 3) | + (filter_cfg->items[i].ide << 2) | + (filter_cfg->items[i].rtr << 1)) & 0xFFFF; + can_instance->CanConfig.FilterConfig.CAN_FilterMskIdHigh = (filter_cfg->items[i].mask >> 16) & 0xFFFF; + can_instance->CanConfig.FilterConfig.CAN_FilterMskIdLow = filter_cfg->items[i].mask & 0xFFFF; + can_instance->CanConfig.FilterConfig.CAN_FilterMode = filter_cfg->items[i].mode; + /* Filter conf */ + CAN_FilterInit(can_instance->CanConfig.Instance, &can_instance->CanConfig.FilterConfig); + } + } + break; + case RT_CAN_CMD_SET_MODE: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_NORMAL && + argval != RT_CAN_MODE_LISEN && + argval != RT_CAN_MODE_LOOPBACK && + argval != RT_CAN_MODE_LOOPBACKANLISEN) + { + return -RT_ERROR; + } + if (argval != can_instance->device.config.mode) + { + can_instance->device.config.mode = argval; + return _can_config(&can_instance->device, &can_instance->device.config); + } + break; + case RT_CAN_CMD_SET_BAUD: + argval = (rt_uint32_t) arg; + if (argval != CAN1MBaud && + argval != CAN800kBaud && + argval != CAN500kBaud && + argval != CAN250kBaud && + argval != CAN125kBaud && + argval != CAN100kBaud && + argval != CAN50kBaud && + argval != CAN20kBaud && + argval != CAN10kBaud) + { + return -RT_ERROR; + } + if (argval != can_instance->device.config.baud_rate) + { + can_instance->device.config.baud_rate = argval; + return _can_config(&can_instance->device, &can_instance->device.config); + } + break; + case RT_CAN_CMD_SET_PRIV: + argval = (rt_uint32_t) arg; + if (argval != RT_CAN_MODE_PRIV && + argval != RT_CAN_MODE_NOPRIV) + { + return -RT_ERROR; + } + if (argval != can_instance->device.config.privmode) + { + can_instance->device.config.privmode = argval; + return _can_config(&can_instance->device, &can_instance->device.config); + } + break; + case RT_CAN_CMD_GET_STATUS: + { + rt_uint32_t errtype; + errtype = can_instance->CanConfig.Instance->ESTS; + can_instance->device.status.rcverrcnt = errtype >> 24; + can_instance->device.status.snderrcnt = (errtype >> 16 & 0xFF); + can_instance->device.status.lasterrtype = errtype & 0x70; + can_instance->device.status.errcode = errtype & 0x07; + + rt_memcpy(arg, &can_instance->device.status, sizeof(can_instance->device.status)); + } + break; + } + + return RT_EOK; +} + +static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num) +{ + struct CAN_Handler *hcan; + hcan = &((struct at32_can *) can->parent.user_data)->CanConfig; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + CanTxMsg TxMessage; + rt_uint32_t i; + + /* Check the parameters */ + RT_ASSERT(IS_CAN_DLC(pmsg->len)); + + /*check select mailbox is empty */ + switch (1 << box_num) + { + case CAN_TX_MAILBOX0: + if ((hcan->Instance->TSTS & CAN_TSTS_TSME0) != CAN_TSTS_TSME0) + { + /* Return function status */ + return -RT_ERROR; + } + break; + case CAN_TX_MAILBOX1: + if ((hcan->Instance->TSTS & CAN_TSTS_TSME1) != CAN_TSTS_TSME1) + { + /* Return function status */ + return -RT_ERROR; + } + break; + case CAN_TX_MAILBOX2: + if ((hcan->Instance->TSTS & CAN_TSTS_TSME2) != CAN_TSTS_TSME2) + { + /* Return function status */ + return -RT_ERROR; + } + break; + default: + RT_ASSERT(0); + break; + } + + if (RT_CAN_STDID == pmsg->ide) + { + TxMessage.IDT = CAN_ID_STD; + RT_ASSERT(IS_CAN_STDID(pmsg->id)); + TxMessage.StdId = pmsg->id; + } + else + { + TxMessage.IDT = CAN_ID_EXT; + RT_ASSERT(IS_CAN_EXTID(pmsg->id)); + TxMessage.ExtId = pmsg->id; + } + + if (RT_CAN_DTR == pmsg->rtr) + { + TxMessage.RTR = CAN_RTR_DATA; + } + else + { + TxMessage.RTR = CAN_RTR_REMOTE; + } + + /* Set up the DLC */ + TxMessage.DLC = pmsg->len & 0x0FU; + /* Set up the data field */ + TxMessage.Data[0] = (uint32_t)pmsg->data[0]; + TxMessage.Data[1] = (uint32_t)pmsg->data[1]; + TxMessage.Data[2] = (uint32_t)pmsg->data[2]; + TxMessage.Data[3] = (uint32_t)pmsg->data[3]; + TxMessage.Data[4] = (uint32_t)pmsg->data[4]; + TxMessage.Data[5] = (uint32_t)pmsg->data[5]; + TxMessage.Data[6] = (uint32_t)pmsg->data[6]; + TxMessage.Data[7] = (uint32_t)pmsg->data[7]; + + CAN_Transmit(hcan->Instance, &TxMessage); + while((CAN_TransmitStatus(hcan->Instance, box_num) != CANTXOK) && (i != 0xFFFF)) + { + i++; + } + + return RT_EOK; +} + +static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo) +{ + struct CAN_Handler *hcan; + hcan = &((struct at32_can *) can->parent.user_data)->CanConfig; + struct rt_can_msg *pmsg = (struct rt_can_msg *) buf; + CanRxMsg RxMessage; + + RT_ASSERT(can); + + /* get data */ + CAN_Receive(hcan->Instance, fifo, &RxMessage); + + pmsg->data[0] = RxMessage.Data[0]; + pmsg->data[1] = RxMessage.Data[1]; + pmsg->data[2] = RxMessage.Data[2]; + pmsg->data[3] = RxMessage.Data[3]; + pmsg->data[4] = RxMessage.Data[4]; + pmsg->data[5] = RxMessage.Data[5]; + pmsg->data[6] = RxMessage.Data[6]; + pmsg->data[7] = RxMessage.Data[7]; + + pmsg->len = RxMessage.DLC; + pmsg->id = RxMessage.IDT; + + if (RxMessage.IDT == CAN_ID_STD) + pmsg->id = RxMessage.StdId; + else + pmsg->ide = RxMessage.ExtId; + pmsg->rtr = RxMessage.RTR; + + return RT_EOK; +} + +static const struct rt_can_ops _can_ops = +{ + _can_config, + _can_control, + _can_sendmsg, + _can_recvmsg, +}; + +static void _can_rx_isr(struct rt_can_device *can, rt_uint32_t fifo) +{ + struct CAN_Handler *hcan; + RT_ASSERT(can); + hcan = &((struct at32_can *) can->parent.user_data)->CanConfig; + + switch (fifo) + { + case CAN_FIFO0: + /* save to user list */ + if (CAN_MessagePending(hcan->Instance, CAN_FIFO0) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFP0)) + { + rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8); + } + /* Check FULL flag for FIFO0 */ + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RFFU0) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFFU0)) + { + /* Clear FIFO0 FULL Flag */ + CAN_ClearFlag(hcan->Instance, CAN_FLAG_RFFU0); + } + + /* Check Overrun flag for FIFO0 */ + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RFOV0) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFOV0)) + { + /* Clear FIFO0 Overrun Flag */ + CAN_ClearFlag(hcan->Instance, CAN_FLAG_RFOV0); + rt_hw_can_isr(can, RT_CAN_EVENT_RXOF_IND | fifo << 8); + } + break; + case CAN_FIFO1: + /* save to user list */ + if (CAN_MessagePending(hcan->Instance, CAN_FIFO1) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFP1)) + { + rt_hw_can_isr(can, RT_CAN_EVENT_RX_IND | fifo << 8); + } + /* Check FULL flag for FIFO1 */ + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RFFU1) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFFU1)) + { + /* Clear FIFO1 FULL Flag */ + CAN_ClearFlag(hcan->Instance, CAN_FLAG_RFFU1); + } + + /* Check Overrun flag for FIFO1 */ + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RFOV1) && CAN_GetINTStatus(hcan->Instance, CAN_INT_RFOV1)) + { + /* Clear FIFO1 Overrun Flag */ + CAN_ClearFlag(hcan->Instance, CAN_FLAG_RFOV1); + rt_hw_can_isr(can, RT_CAN_EVENT_RXOF_IND | fifo << 8); + } + break; + } +} + +#ifdef BSP_USING_CAN1 +/** + * @brief This function handles CAN1 TX interrupts. transmit fifo0/1/2 is empty can trigger this interrupt + */ +void USB_HP_CAN1_TX_IRQHandler(void) +{ + rt_interrupt_enter(); + struct CAN_Handler *hcan; + hcan = &can_instance1.CanConfig; + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP0)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK0) == CAN_TSTS_TOK0) + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_DONE | 0 << 8); + } + else + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC0; + } + else if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP1)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK1) == CAN_TSTS_TOK1) + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_DONE | 1 << 8); + } + else + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 1 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC1; + } + else if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP2)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK2) == CAN_TSTS_TOK2) + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_DONE | 2 << 8); + } + else + { + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 2 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC2; + } + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN1 RX0 interrupts. + */ +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_instance1.device, CAN_FIFO0); + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN1 RX1 interrupts. + */ +void CAN1_RX1_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_instance1.device, CAN_FIFO1); + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN1 SCE interrupts. + */ +void CAN1_SCE_IRQHandler(void) +{ + rt_uint32_t errtype; + struct CAN_Handler *hcan; + + hcan = &can_instance1.CanConfig; + errtype = hcan->Instance->ESTS; + + rt_interrupt_enter(); + + switch ((errtype & 0x70) >> 4) + { + case RT_CAN_BUS_BIT_PAD_ERR: + can_instance1.device.status.bitpaderrcnt++; + break; + case RT_CAN_BUS_FORMAT_ERR: + can_instance1.device.status.formaterrcnt++; + break; + case RT_CAN_BUS_ACK_ERR:/* attention !!! test ack err's unit is transmit unit */ + can_instance1.device.status.ackerrcnt++; + if (!(can_instance1.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 0 << 8); + else if (!(can_instance1.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 1 << 8); + else if (!(can_instance1.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance1.device, RT_CAN_EVENT_TX_FAIL | 2 << 8); + break; + case RT_CAN_BUS_IMPLICIT_BIT_ERR: + case RT_CAN_BUS_EXPLICIT_BIT_ERR: + can_instance1.device.status.biterrcnt++; + break; + case RT_CAN_BUS_CRC_ERR: + can_instance1.device.status.crcerrcnt++; + break; + } + + can_instance1.device.status.lasterrtype = errtype & 0x70; + can_instance1.device.status.rcverrcnt = errtype >> 24; + can_instance1.device.status.snderrcnt = (errtype >> 16 & 0xFF); + can_instance1.device.status.errcode = errtype & 0x07; + hcan->Instance->MSTS |= CAN_MSTS_ERIT; + rt_interrupt_leave(); +} +#endif /* BSP_USING_CAN1 */ + +#ifdef BSP_USING_CAN2 +/** + * @brief This function handles CAN2 TX interrupts. + */ +void CAN2_TX_IRQHandler(void) +{ + rt_interrupt_enter(); + struct CAN_Handler *hcan; + hcan = &can_instance2.CanConfig; + if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP0)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK0) == CAN_TSTS_TOK0) + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_DONE | 0 << 8); + } + else + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 0 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC0; + } + else if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP1)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK1) == CAN_TSTS_TOK1) + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_DONE | 1 << 8); + } + else + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 1 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC1; + } + else if (CAN_GetFlagStatus(hcan->Instance, CAN_FLAG_RQCP2)) + { + if ((hcan->Instance->TSTS & CAN_TSTS_TOK2) == CAN_TSTS_TOK2) + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_DONE | 2 << 8); + } + else + { + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 2 << 8); + } + /* Write 0 to Clear transmission status flag RQCPx */ + hcan->Instance->TSTS |= CAN_TSTS_RQC2; + } + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN2 RX0 interrupts. + */ +void CAN2_RX0_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_instance2.device, CAN_FIFO0); + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN2 RX1 interrupts. + */ +void CAN2_RX1_IRQHandler(void) +{ + rt_interrupt_enter(); + _can_rx_isr(&can_instance2.device, CAN_FIFO1); + rt_interrupt_leave(); +} + +/** + * @brief This function handles CAN2 SCE interrupts. + */ +void CAN2_SCE_IRQHandler(void) +{ + rt_uint32_t errtype; + struct CAN_Handler *hcan; + + hcan = &can_instance2.CanConfig; + errtype = hcan->Instance->ESTS; + + rt_interrupt_enter(); + + switch ((errtype & 0x70) >> 4) + { + case RT_CAN_BUS_BIT_PAD_ERR: + can_instance2.device.status.bitpaderrcnt++; + break; + case RT_CAN_BUS_FORMAT_ERR: + can_instance2.device.status.formaterrcnt++; + break; + case RT_CAN_BUS_ACK_ERR: + can_instance2.device.status.ackerrcnt++; + if (!(can_instance1.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 0 << 8); + else if (!(can_instance2.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 1 << 8); + else if (!(can_instance2.CanConfig.Instance->TSTS & CAN_TSTS_TOK0)) + rt_hw_can_isr(&can_instance2.device, RT_CAN_EVENT_TX_FAIL | 2 << 8); + break; + case RT_CAN_BUS_IMPLICIT_BIT_ERR: + case RT_CAN_BUS_EXPLICIT_BIT_ERR: + can_instance2.device.status.biterrcnt++; + break; + case RT_CAN_BUS_CRC_ERR: + can_instance2.device.status.crcerrcnt++; + break; + } + + can_instance2.device.status.lasterrtype = errtype & 0x70; + can_instance2.device.status.rcverrcnt = errtype >> 24; + can_instance2.device.status.snderrcnt = (errtype >> 16 & 0xFF); + can_instance2.device.status.errcode = errtype & 0x07; + hcan->Instance->MSTS |= CAN_MSTS_ERIT; + rt_interrupt_leave(); +} +#endif /* BSP_USING_CAN2 */ + +/** + * @brief Error CAN callback. + * @param hcan pointer to a CAN_HandleTypeDef structure that contains + * the configuration information for the specified CAN. + * @retval None + */ +void HAL_CAN_ErrorCallback(struct CAN_Handler *hcan) +{ + CAN_INTConfig(hcan->Instance, CAN_INT_TSME | + CAN_INT_RFP0 | + CAN_INT_RFFU0 | + CAN_INT_RFOV0 | + CAN_INT_RFP1 | + CAN_INT_RFFU1 | + CAN_INT_RFOV1 | + CAN_INT_ERG | + CAN_INT_ERP | + CAN_INT_LEC | + CAN_INT_ERR | + CAN_INT_WK, ENABLE); +} + +int rt_hw_can_init(void) +{ + struct can_configure config = CANDEFAULTCONFIG; + config.privmode = RT_CAN_MODE_NOPRIV; + config.ticks = 50; +#ifdef RT_CAN_USING_HDR + config.maxhdr = 14; +#endif + /* config default filter */ + CAN_FilterInitType filterConf = {0}; + filterConf.CAN_FilterIdHigh = 0x0000; + filterConf.CAN_FilterIdLow = 0x0000; + filterConf.CAN_FilterMskIdHigh = 0x0000; + filterConf.CAN_FilterMskIdLow = 0x0000; + filterConf.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; + filterConf.CAN_FilterNumber = 0; + filterConf.CAN_FilterMode = CAN_FilterMode_IdMask; + filterConf.CAN_FilterScale = CAN_FilterScale_32bit; + filterConf.CAN_FilterActivation = ENABLE; + +#ifdef BSP_USING_CAN1 + filterConf.CAN_FilterNumber = 0; + + can_instance1.CanConfig.FilterConfig = filterConf; + can_instance1.device.config = config; + /* register CAN1 device */ + rt_hw_can_register(&can_instance1.device, + can_instance1.name, + &_can_ops, + &can_instance1); +#endif /* BSP_USING_CAN1 */ + +#ifdef BSP_USING_CAN2 + filterConf.CAN_FilterNumber = 0; + + can_instance2.CanConfig.FilterConfig = filterConf; + can_instance2.device.config = config; + /* register CAN2 device */ + rt_hw_can_register(&can_instance2.device, + can_instance2.name, + &_can_ops, + &can_instance2); +#endif /* BSP_USING_CAN2 */ + + return 0; +} + +INIT_BOARD_EXPORT(rt_hw_can_init); + +#endif /* BSP_USING_CAN */ + +/************************** end of file ******************/ diff --git a/bsp/at32/Libraries/rt_drivers/drv_can.h b/bsp/at32/Libraries/rt_drivers/drv_can.h new file mode 100644 index 0000000000000000000000000000000000000000..d89bacda26b9730d248f21f543deb1a942c6dd45 --- /dev/null +++ b/bsp/at32/Libraries/rt_drivers/drv_can.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-09 shelton the first version + */ + +#ifndef __DRV_CAN_H__ +#define __DRV_CAN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define CAN_TX_MAILBOX0 (0x00000001U) /*!< Tx Mailbox 0 */ +#define CAN_TX_MAILBOX1 (0x00000002U) /*!< Tx Mailbox 1 */ +#define CAN_TX_MAILBOX2 (0x00000004U) /*!< Tx Mailbox 2 */ + +struct at32_baud_rate_tab +{ + rt_uint32_t baud_rate; + rt_uint32_t sjw; + rt_uint32_t bs1; + rt_uint32_t bs2; + rt_uint32_t psc; +}; + +struct CAN_Handler +{ + CAN_Type *Instance; + CAN_InitType CanInit; + CAN_FilterInitType FilterConfig; +}; + +/* at32 can device */ +struct at32_can +{ + char *name; + struct CAN_Handler CanConfig; + struct rt_can_device device; /* inherit from can device */ +}; + +int rt_hw_can_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /*__DRV_CAN_H__ */ + +/************************** end of file ******************/ diff --git a/bsp/at32/Libraries/rt_drivers/drv_flash.c b/bsp/at32/Libraries/rt_drivers/drv_flash.c new file mode 100644 index 0000000000000000000000000000000000000000..8104f9b61290a62110f52124ef5b4657ca57fdc8 --- /dev/null +++ b/bsp/at32/Libraries/rt_drivers/drv_flash.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-09 shelton the first version + */ + +#include +#include + +#ifdef BSP_USING_ON_CHIP_FLASH +#include "drv_flash.h" + +#if defined(PKG_USING_FAL) +#include "fal.h" +#endif + +//#define DRV_DEBUG +#define LOG_TAG "drv.flash" +#include + +/** + * @brief Gets the page of a given address + * @param addr: address of the flash memory + * @retval The page of a given address + */ +static rt_uint32_t get_page(uint32_t addr) +{ + rt_uint32_t page = 0; + + page = RT_ALIGN_DOWN(addr, FLASH_PAGE_SIZE); + + return page; +} + +/** + * Read data from flash. + * @note This operation's units is word. + * + * @param addr flash address + * @param buf buffer to store read data + * @param size read bytes size + * + * @return result + */ +int at32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size) +{ + size_t i; + + if ((addr + size) > AT32_FLASH_END_ADDRESS) + { + LOG_E("read outrange flash size! addr is (0x%p)", (void *)(addr + size)); + return -RT_EINVAL; + } + + for (i = 0; i < size; i++, buf++, addr++) + { + *buf = *(rt_uint8_t *) addr; + } + + return size; +} + +/** + * Write data to flash. + * @note This operation's units is word. + * @note This operation must after erase. @see flash_erase. + * + * @param addr flash address + * @param buf the write data buffer + * @param size write bytes size + * + * @return result + */ +int at32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size) +{ + rt_err_t result = RT_EOK; + rt_uint32_t end_addr = addr + size; + + if (addr % 4 != 0) + { + LOG_E("write addr must be 4-byte alignment"); + return -RT_EINVAL; + } + + if ((end_addr) > AT32_FLASH_END_ADDRESS) + { + LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size)); + return -RT_EINVAL; + } + + FLASH_Unlock(); + + while (addr < end_addr) + { + if (FLASH_ProgramWord(addr, *((rt_uint32_t *)buf)) == FLASH_PRC_DONE) + { + if (*(rt_uint32_t *)addr != *(rt_uint32_t *)buf) + { + result = -RT_ERROR; + break; + } + addr += 4; + buf += 4; + } + else + { + result = -RT_ERROR; + break; + } + } + + FLASH_Lock(); + + if (result != RT_EOK) + { + return result; + } + + return size; +} + +/** + * Erase data on flash . + * @note This operation is irreversible. + * @note This operation's units is different which on many chips. + * + * @param addr flash address + * @param size erase bytes size + * + * @return result + */ +int at32_flash_erase(rt_uint32_t addr, size_t size) +{ + rt_err_t result = RT_EOK; + rt_uint32_t end_addr = addr + size; + rt_uint32_t page_addr = 0; + + FLASH_Unlock(); + + if ((end_addr) > AT32_FLASH_END_ADDRESS) + { + LOG_E("erase outrange flash size! addr is (0x%p)", (void *)(addr + size)); + return -RT_EINVAL; + } + + while(addr < end_addr) + { + page_addr = get_page(addr); + + if(FLASH_ErasePage(page_addr) != FLASH_PRC_DONE) + { + result = -RT_ERROR; + goto __exit; + } + + addr += FLASH_PAGE_SIZE; + } + + FLASH_Lock(); + +__exit: + if(result != RT_EOK) + { + return result; + } + + return size; +} + +#if defined(PKG_USING_FAL) + +static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size); +static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size); +static int fal_flash_erase(long offset, size_t size); + +const struct fal_flash_dev at32_onchip_flash = +{ + "onchip_flash", + AT32_FLASH_START_ADRESS, + AT32_FLASH_SIZE, + FLASH_PAGE_SIZE, + { + NULL, + fal_flash_read, + fal_flash_write, + fal_flash_erase + } +}; + +static int fal_flash_read(long offset, rt_uint8_t *buf, size_t size) +{ + return at32_flash_read(at32_onchip_flash.addr + offset, buf, size); +} + +static int fal_flash_write(long offset, const rt_uint8_t *buf, size_t size) +{ + return at32_flash_write(at32_onchip_flash.addr + offset, buf, size); +} + +static int fal_flash_erase(long offset, size_t size) +{ + return at32_flash_erase(at32_onchip_flash.addr + offset, size); +} + +#endif +#endif /* BSP_USING_ON_CHIP_FLASH */ diff --git a/bsp/at32/Libraries/rt_drivers/drv_flash.h b/bsp/at32/Libraries/rt_drivers/drv_flash.h new file mode 100644 index 0000000000000000000000000000000000000000..9392ff430336349164128537d0e7f3ecea8e903f --- /dev/null +++ b/bsp/at32/Libraries/rt_drivers/drv_flash.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-09 shelton the first version + */ + +#ifndef __DRV_FLASH_H__ +#define __DRV_FLASH_H__ + +#include +#include "rtdevice.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int at32_flash_read(rt_uint32_t addr, rt_uint8_t *buf, size_t size); +int at32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size); +int at32_flash_erase(rt_uint32_t addr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* __DRV_FLASH_H__ */ diff --git a/bsp/at32/at32f403a-start/README.md b/bsp/at32/at32f403a-start/README.md index 3f470905eab2c7ebbdbcdde047dc85b14f8e2dfc..6460062bda30dde7ca7daabc219260f004866e62 100644 --- a/bsp/at32/at32f403a-start/README.md +++ b/bsp/at32/at32f403a-start/README.md @@ -46,8 +46,10 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以 | PWM | 支持 | TMR1/2 | | HWTIMER | 支持 | TMR3/4/5 | | SDIO | 支持 | SDIO1 | +| CAN | 支持 | CAN1/2 | | WDT | 支持 | | | RTC | 支持 | | +| FLASH | 支持 | | ### IO在板级支持包中的映射情况 @@ -88,6 +90,10 @@ AT32F403A-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以 | PC3 | ADC1/2_IN13 | | PC4 | ADC1/2_IN14 | | PC5 | ADC1/2_IN15 | +| PA11 | CAN1_RX | +| PA12 | CAN1_TX | +| PB5 | CAN2_RX | +| PB6 | CAN2_TX | ## 使用说明 diff --git a/bsp/at32/at32f403a-start/board/Kconfig b/bsp/at32/at32f403a-start/board/Kconfig index ed6811f2052974fcfb3b52ec520a562a45d331e3..9816ab4729b306236606c2786c4b6c697ecf06c3 100644 --- a/bsp/at32/at32f403a-start/board/Kconfig +++ b/bsp/at32/at32f403a-start/board/Kconfig @@ -24,6 +24,10 @@ menu "On-chip Peripheral Drivers" select RT_USING_PIN default y + config BSP_USING_ON_CHIP_FLASH + bool "Enable on-chip FLASH" + default n + menuconfig BSP_USING_RTC bool "Enable RTC" select RT_USING_RTC @@ -151,6 +155,19 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_CAN + bool "Enable CAN" + default n + select RT_USING_CAN + if BSP_USING_CAN + config BSP_USING_CAN1 + bool "using CAN1" + default n + config BSP_USING_CAN2 + bool "using CAN2" + default n + endif + menuconfig BSP_USING_SDIO bool "Enable SDIO" default n diff --git a/bsp/at32/at32f403a-start/board/board.h b/bsp/at32/at32f403a-start/board/board.h index 28bb16bf47309e67a7cba7287834a5f13a1ecde6..976863d3ebb3d4e709c097297b804a497cc12803 100644 --- a/bsp/at32/at32f403a-start/board/board.h +++ b/bsp/at32/at32f403a-start/board/board.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2020-01-15 shelton first version + * 2021-02-09 shelton add flash macros */ #ifndef __BOARD_H__ @@ -18,6 +19,12 @@ extern "C" { #endif +/* Just only support for AT32F40xxG */ +#define AT32_FLASH_START_ADRESS ((uint32_t)0x08000000) +#define FLASH_PAGE_SIZE (2 * 1024) +#define AT32_FLASH_SIZE (1024 * 1024) +#define AT32_FLASH_END_ADDRESS ((uint32_t)(AT32_FLASH_START_ADRESS + AT32_FLASH_SIZE)) + /* Internal SRAM memory size[Kbytes] <96>, Default: 96*/ #define AT32_SRAM_SIZE 96 #define AT32_SRAM_END (0x20000000 + AT32_SRAM_SIZE * 1024) diff --git a/bsp/at32/at32f403a-start/board/msp/at32_msp.c b/bsp/at32/at32f403a-start/board/msp/at32_msp.c index 5ea74628f35e6d46561cd625dc6710315020af48..1392b0e0cf29fdec7243f53a85dec21bc55bfe8d 100644 --- a/bsp/at32/at32f403a-start/board/msp/at32_msp.c +++ b/bsp/at32/at32f403a-start/board/msp/at32_msp.c @@ -2,8 +2,8 @@ ****************************************************************************** * @file at32_msp.c * @author Artery Technology - * @version V1.0.0 - * @date 2020-01-10 + * @version V1.0.1 + * @date 2021-02-09 * @brief Msp source file ****************************************************************************** * @attention @@ -256,3 +256,44 @@ void at32_msp_hwtmr_init(void *Instance) #endif } #endif + +#ifdef BSP_USING_CAN +void at32_msp_can_init(void *Instance) +{ + GPIO_InitType GPIO_InitStruct; + CAN_Type *CANx = (CAN_Type *)Instance; + + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz; +#ifdef BSP_USING_CAN1 + if(CAN1 == CANx) + { + RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_CAN1, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA, ENABLE); + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_12; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_11; + GPIO_Init(GPIOA, &GPIO_InitStruct); + } +#endif +#ifdef BSP_USING_CAN2 + if(CAN2 == CANx) + { + RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_CAN2, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB, ENABLE); + GPIO_PinsRemapConfig(AFIO_MAP6_CAN2_0001, ENABLE); + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_6; + GPIO_Init(GPIOB, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_5; + GPIO_Init(GPIOB, &GPIO_InitStruct); + } +#endif +} +#endif /* BSP_USING_CAN */ diff --git a/bsp/at32/at32f403a-start/board/msp/at32_msp.h b/bsp/at32/at32f403a-start/board/msp/at32_msp.h index c59bab2b2cebb1f96a33e26c8ceed2bda0395184..7b31c3bbff7f839207faa0001c10b652f92629f6 100644 --- a/bsp/at32/at32f403a-start/board/msp/at32_msp.h +++ b/bsp/at32/at32f403a-start/board/msp/at32_msp.h @@ -2,8 +2,8 @@ ****************************************************************************** * @file at32_msp.h * @author Artery Technology - * @version V1.0.0 - * @date 2020-01-10 + * @version V1.0.1 + * @date 2021-02-09 * @brief Msp header file ****************************************************************************** * @attention @@ -29,5 +29,6 @@ void at32_msp_i2c_init(void *Instance); void at32_msp_sdio_init(void *Instance); void at32_msp_adc_init(void *Instance); void at32_msp_hwtmr_init(void *Instance); +void at32_msp_can_init(void *Instance); #endif /* __AT32_MSP_H__ */ diff --git a/bsp/at32/at32f407-start/README.md b/bsp/at32/at32f407-start/README.md index b02b72c3eeb79dd272836f8be889ccba5e683ae9..9c9ca665bf994eab1077301d03b1ed567d6fc04a 100644 --- a/bsp/at32/at32f407-start/README.md +++ b/bsp/at32/at32f407-start/README.md @@ -46,8 +46,10 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以 | PWM | 支持 | TMR1/2 | | HWTIMER | 支持 | TMR3/4/5 | | SDIO | 支持 | SDIO1 | +| CAN | 支持 | CAN1/2 | | WDT | 支持 | | | RTC | 支持 | | +| FLASH | 支持 | | | ETH | 支持 | | ### IO在板级支持包中的映射情况 @@ -89,6 +91,10 @@ AT32F407-START板级包支持MDK4﹑MDK5﹑IAR开发环境和GCC编译器,以 | PC3 | ADC1/2_IN13 | | PC4 | ADC1/2_IN14 | | PC5 | ADC1/2_IN15 | +| PA11 | CAN1_RX | +| PA12 | CAN1_TX | +| PB5 | CAN2_RX | +| PB6 | CAN2_TX | | PB11 | ETH_RMII_TX_EN | | PB12 | ETH_RMII_TX0 | | PB13 | ETH_RMII_TX1 | diff --git a/bsp/at32/at32f407-start/board/Kconfig b/bsp/at32/at32f407-start/board/Kconfig index 28ba92b67b87f6dd99ec8a9b76755daa9e6c7947..5a3b46274c3d3e6cfab86c600c61ac603886c678 100644 --- a/bsp/at32/at32f407-start/board/Kconfig +++ b/bsp/at32/at32f407-start/board/Kconfig @@ -24,6 +24,10 @@ menu "On-chip Peripheral Drivers" select RT_USING_PIN default y + config BSP_USING_ON_CHIP_FLASH + bool "Enable on-chip FLASH" + default n + config BSP_USING_ETH bool "Enable Ethernet" default n @@ -157,6 +161,19 @@ menu "On-chip Peripheral Drivers" default n endif + menuconfig BSP_USING_CAN + bool "Enable CAN" + default n + select RT_USING_CAN + if BSP_USING_CAN + config BSP_USING_CAN1 + bool "using CAN1" + default n + config BSP_USING_CAN2 + bool "using CAN2" + default n + endif + menuconfig BSP_USING_SDIO bool "Enable SDIO" default n diff --git a/bsp/at32/at32f407-start/board/board.h b/bsp/at32/at32f407-start/board/board.h index 28bb16bf47309e67a7cba7287834a5f13a1ecde6..976863d3ebb3d4e709c097297b804a497cc12803 100644 --- a/bsp/at32/at32f407-start/board/board.h +++ b/bsp/at32/at32f407-start/board/board.h @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2020-01-15 shelton first version + * 2021-02-09 shelton add flash macros */ #ifndef __BOARD_H__ @@ -18,6 +19,12 @@ extern "C" { #endif +/* Just only support for AT32F40xxG */ +#define AT32_FLASH_START_ADRESS ((uint32_t)0x08000000) +#define FLASH_PAGE_SIZE (2 * 1024) +#define AT32_FLASH_SIZE (1024 * 1024) +#define AT32_FLASH_END_ADDRESS ((uint32_t)(AT32_FLASH_START_ADRESS + AT32_FLASH_SIZE)) + /* Internal SRAM memory size[Kbytes] <96>, Default: 96*/ #define AT32_SRAM_SIZE 96 #define AT32_SRAM_END (0x20000000 + AT32_SRAM_SIZE * 1024) diff --git a/bsp/at32/at32f407-start/board/msp/at32_msp.c b/bsp/at32/at32f407-start/board/msp/at32_msp.c index 5ea74628f35e6d46561cd625dc6710315020af48..1392b0e0cf29fdec7243f53a85dec21bc55bfe8d 100644 --- a/bsp/at32/at32f407-start/board/msp/at32_msp.c +++ b/bsp/at32/at32f407-start/board/msp/at32_msp.c @@ -2,8 +2,8 @@ ****************************************************************************** * @file at32_msp.c * @author Artery Technology - * @version V1.0.0 - * @date 2020-01-10 + * @version V1.0.1 + * @date 2021-02-09 * @brief Msp source file ****************************************************************************** * @attention @@ -256,3 +256,44 @@ void at32_msp_hwtmr_init(void *Instance) #endif } #endif + +#ifdef BSP_USING_CAN +void at32_msp_can_init(void *Instance) +{ + GPIO_InitType GPIO_InitStruct; + CAN_Type *CANx = (CAN_Type *)Instance; + + GPIO_StructInit(&GPIO_InitStruct); + GPIO_InitStruct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz; +#ifdef BSP_USING_CAN1 + if(CAN1 == CANx) + { + RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_CAN1, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOA, ENABLE); + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_12; + GPIO_Init(GPIOA, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_11; + GPIO_Init(GPIOA, &GPIO_InitStruct); + } +#endif +#ifdef BSP_USING_CAN2 + if(CAN2 == CANx) + { + RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_CAN2, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB, ENABLE); + GPIO_PinsRemapConfig(AFIO_MAP6_CAN2_0001, ENABLE); + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_6; + GPIO_Init(GPIOB, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_InitStruct.GPIO_Pins = GPIO_Pins_5; + GPIO_Init(GPIOB, &GPIO_InitStruct); + } +#endif +} +#endif /* BSP_USING_CAN */ diff --git a/bsp/at32/at32f407-start/board/msp/at32_msp.h b/bsp/at32/at32f407-start/board/msp/at32_msp.h index c59bab2b2cebb1f96a33e26c8ceed2bda0395184..7b31c3bbff7f839207faa0001c10b652f92629f6 100644 --- a/bsp/at32/at32f407-start/board/msp/at32_msp.h +++ b/bsp/at32/at32f407-start/board/msp/at32_msp.h @@ -2,8 +2,8 @@ ****************************************************************************** * @file at32_msp.h * @author Artery Technology - * @version V1.0.0 - * @date 2020-01-10 + * @version V1.0.1 + * @date 2021-02-09 * @brief Msp header file ****************************************************************************** * @attention @@ -29,5 +29,6 @@ void at32_msp_i2c_init(void *Instance); void at32_msp_sdio_init(void *Instance); void at32_msp_adc_init(void *Instance); void at32_msp_hwtmr_init(void *Instance); +void at32_msp_can_init(void *Instance); #endif /* __AT32_MSP_H__ */ diff --git a/bsp/ls1bdev/Kconfig b/bsp/ls1bdev/Kconfig index c1788b1c6b01ac0716494f36bec1055d70f1bb9f..b02aee337a32bf2320c7258c067ca2e9e07b3b7e 100644 --- a/bsp/ls1bdev/Kconfig +++ b/bsp/ls1bdev/Kconfig @@ -16,7 +16,6 @@ config PKGS_DIR default "packages" source "$RTT_DIR/Kconfig" -source "$RTT_DIR/libcpu/mips/common/Kconfig" source "$PKGS_DIR/Kconfig" config SOC_LS1B @@ -25,16 +24,33 @@ config SOC_LS1B select RT_USING_USER_MAIN default y +config RT_MEM_SIZE + int "Memory Size (MByte)" + default 256 + +config RT_OSC_CLK + int "Oscillator Clock (Hz)" + default 25000000 + if RT_USING_SERIAL config RT_USING_UART0 bool "Using RT_USING_UART0" - default y + default n config RT_USING_UART1 bool "Using RT_USING_UART1" default n +config RT_USING_UART2 + bool "Using RT_USING_UART2" + default n config RT_USING_UART3 bool "Using RT_USING_UART3" default n +config RT_USING_UART4 + bool "Using RT_USING_UART4" + default n +config RT_USING_UART5 + bool "Using RT_USING_UART5" + default y config RT_UART_RX_BUFFER_SIZE int "The rx buffer size" diff --git a/bsp/ls1bdev/drivers/board.c b/bsp/ls1bdev/drivers/board.c index a3f907f664973e4565cc6327fd3341ea13e96907..8a42f8e3a03b04515ac27fa18bf8ccb2d7c50589 100644 --- a/bsp/ls1bdev/drivers/board.c +++ b/bsp/ls1bdev/drivers/board.c @@ -19,7 +19,7 @@ #include #include "board.h" -#include "uart.h" +#include "drv_uart.h" #include "ls1b.h" #ifdef RT_USING_RTGUI @@ -84,6 +84,6 @@ void rt_hw_board_init(void) #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif - + rt_kprintf("current sr: 0x%08x\n", read_c0_status()); } /*@}*/ diff --git a/bsp/ls1bdev/drivers/board.h b/bsp/ls1bdev/drivers/board.h index 9ba4f9f25c9407fd03eae9a4c7b394b9380576d2..fbe2ed8f9cb09ddd024ebfd608ef25f064fda87b 100644 --- a/bsp/ls1bdev/drivers/board.h +++ b/bsp/ls1bdev/drivers/board.h @@ -19,7 +19,7 @@ void rt_hw_board_init(void); /* 64M SDRAM */ -#define RT_HW_HEAP_END (0x80000000 + 64 * 1024 * 1024) +#define RT_HW_HEAP_END (0x80000000 + RT_MEM_SIZE * 1024 * 1024) #define CPU_HZ (125 * 1000000) #endif diff --git a/bsp/ls1bdev/drivers/drv_uart.c b/bsp/ls1bdev/drivers/drv_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..8f469f26ed2b04ce4b1af2c1fb1cebd987cd9a06 --- /dev/null +++ b/bsp/ls1bdev/drivers/drv_uart.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-08 zhuangwei the first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ +#include +#include +#include +#include "drv_uart.h" +#include "ls1b_pin.h" +#include "ls1b_uart.h" + +/* STM32 uart driver */ +struct rt_uart_ls1b +{ + ls1b_uart_t UARTx; + rt_uint32_t IRQ; +}; + +static rt_err_t ls1b_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + ls1b_uart_info_t uart_info = {0}; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + + // 初始化串口 + uart_info.UARTx = uart_dev->UARTx; + uart_info.baudrate = cfg->baud_rate; + uart_info.rx_enable = TRUE; + uart_init(&uart_info); + + return RT_EOK; + +} + +static rt_err_t ls1b_uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ + rt_hw_interrupt_mask(uart_dev->IRQ); + break; + + case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ + rt_hw_interrupt_umask(uart_dev->IRQ); + break; + + default: + break; + } + + return RT_EOK; + +} + +static int ls1b_uart_putc(struct rt_serial_device *serial, char c) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + uart_putc(uart_dev->UARTx, c); + + return 1; +} + +static int ls1b_uart_getc(struct rt_serial_device *serial) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + void *uart_base = uart_get_base(uart_dev->UARTx); + + if (LSR_RXRDY & reg_read_8(uart_base + LS1B_UART_LSR_OFFSET)) + { + return reg_read_8(uart_base + LS1B_UART_DAT_OFFSET); + } + + return -1; +} + +/* UART interrupt handler */ +static void uart_irq_handler(int vector, void *param) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)param; + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + void *uart_base = uart_get_base(uart_dev->UARTx); + unsigned char iir = reg_read_8(uart_base + LS1B_UART_IIR_OFFSET); + + // 判断是否为接收超时或接收到有效数据 + if ((IIR_RXTOUT & iir) || (IIR_RXRDY & iir)) + { + rt_interrupt_enter(); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + rt_interrupt_leave(); + } + +} + +static const struct rt_uart_ops ls1b_uart_ops = +{ + ls1b_uart_configure, + ls1b_uart_control, + ls1b_uart_putc, + ls1b_uart_getc, +}; + + +#if defined(RT_USING_UART1) +struct rt_uart_ls1b uart1 = +{ + LS1B_UART1, + LS1B_UART1_IRQ, +}; +struct rt_serial_device serial1; +#endif /* RT_USING_UART1 */ + +#if defined(RT_USING_UART2) +struct rt_uart_ls1b uart2 = +{ + LS1B_UART2, + LS1B_UART2_IRQ, +}; +struct rt_serial_device serial2; +#endif /* RT_USING_UART2 */ + + +#if defined(RT_USING_UART3) +struct rt_uart_ls1b uart3 = +{ + LS1B_UART3, + LS1B_UART3_IRQ, +}; +struct rt_serial_device serial3; +#endif /* RT_USING_UART3 */ + +#if defined(RT_USING_UART4) +struct rt_uart_ls1b uart4 = +{ + LS1B_UART4, + LS1B_UART4_IRQ, +}; +struct rt_serial_device serial4; +#endif /* RT_USING_UART4 */ + +#if defined(RT_USING_UART5) +struct rt_uart_ls1b uart5 = +{ + LS1B_UART5, + LS1B_UART5_IRQ, +}; +struct rt_serial_device serial5; +#endif /* RT_USING_UART5 */ + + + +void rt_hw_uart_init(void) +{ + struct rt_uart_ls1b *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART5 + uart = &uart5; + + serial5.ops = &ls1b_uart_ops; + serial5.config = config; + + rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial5, "UART5"); + + /* register UART5 device */ + rt_hw_serial_register(&serial5, + "uart5", + //RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); +#endif /* RT_USING_UART5 */ + + +#ifdef RT_USING_UART2 + uart = &uart2; + + serial2.ops = &ls1b_uart_ops; + serial2.config = config; + + pin_set_purpose(36, PIN_PURPOSE_OTHER); + pin_set_purpose(37, PIN_PURPOSE_OTHER); + pin_set_remap(36, PIN_REMAP_SECOND); + pin_set_remap(37, PIN_REMAP_SECOND); + + rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial2, "UART2"); + + /* register UART2 device */ + rt_hw_serial_register(&serial2, + "uart2", + //RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); +#endif /* RT_USING_UART2 */ + +} + diff --git a/bsp/ls1bdev/drivers/drv_uart.h b/bsp/ls1bdev/drivers/drv_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..01dfd9aae0ce5dabbb7be5a78c36101f0009f99b --- /dev/null +++ b/bsp/ls1bdev/drivers/drv_uart.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-08 zhuangwei the first version + */ + +#ifndef __DRV_UART_H__ +#define __DRV_UART_H__ + +#include "ls1b.h" +#include + +#define DEV_CLK 252000000 // 252MHz +#define UART_BAUDRATE 115200 + +#define UART0_BASE 0xBFE40000 +//#define UART0_1_BASE 0xBFE41000 +#define UART1_BASE 0xBFE44000 +#define UART2_BASE 0xBFE48000 +#define UART3_BASE 0xBFE4C000 +#define UART4_BASE 0xBFE4C400 +#define UART5_BASE 0xBFE4C500 +#define UART6_BASE 0xBFE4C600 +#define UART7_BASE 0xBFE4C700 +#define UART8_BASE 0xBFE4C800 +#define UART9_BASE 0xBFE4C900 +#define UART10_BASE 0xBFE4Ca00 +#define UART11_BASE 0xBFE4Cb00 + +/* UART registers */ +#define UART_DAT(base) HWREG8(base + 0x00) +#define UART_IER(base) HWREG8(base + 0x01) +#define UART_IIR(base) HWREG8(base + 0x02) +#define UART_FCR(base) HWREG8(base + 0x02) +#define UART_LCR(base) HWREG8(base + 0x03) +#define UART_MCR(base) HWREG8(base + 0x04) +#define UART_LSR(base) HWREG8(base + 0x05) +#define UART_MSR(base) HWREG8(base + 0x06) + +#define UART_LSB(base) HWREG8(base + 0x00) +#define UART_MSB(base) HWREG8(base + 0x01) + +/* UART0 registers */ +#define UART0_DAT HWREG8(UART0_BASE + 0x00) +#define UART0_IER HWREG8(UART0_BASE + 0x01) +#define UART0_IIR HWREG8(UART0_BASE + 0x02) +#define UART0_FCR HWREG8(UART0_BASE + 0x02) +#define UART0_LCR HWREG8(UART0_BASE + 0x03) +#define UART0_MCR HWREG8(UART0_BASE + 0x04) +#define UART0_LSR HWREG8(UART0_BASE + 0x05) +#define UART0_MSR HWREG8(UART0_BASE + 0x06) + +#define UART0_LSB HWREG8(UART0_BASE + 0x00) +#define UART0_MSB HWREG8(UART0_BASE + 0x01) + +/* UART1 registers */ +#define UART1_DAT HWREG8(UART1_BASE + 0x00) +#define UART1_IER HWREG8(UART1_BASE + 0x01) +#define UART1_IIR HWREG8(UART1_BASE + 0x02) +#define UART1_FCR HWREG8(UART1_BASE + 0x02) +#define UART1_LCR HWREG8(UART1_BASE + 0x03) +#define UART1_MCR HWREG8(UART1_BASE + 0x04) +#define UART1_LSR HWREG8(UART1_BASE + 0x05) +#define UART1_MSR HWREG8(UART1_BASE + 0x06) + +#define UART1_LSB HWREG8(UART1_BASE + 0x00) +#define UART1_MSB HWREG8(UART1_BASE + 0x01) + +/* UART interrupt enable register value */ +#define UARTIER_IME (1 << 3) +#define UARTIER_ILE (1 << 2) +#define UARTIER_ITXE (1 << 1) +#define UARTIER_IRXE (1 << 0) + +/* UART line control register value */ +#define UARTLCR_DLAB (1 << 7) +#define UARTLCR_BCB (1 << 6) +#define UARTLCR_SPB (1 << 5) +#define UARTLCR_EPS (1 << 4) +#define UARTLCR_PE (1 << 3) +#define UARTLCR_SB (1 << 2) + +/* UART line status register value */ +#define UARTLSR_ERROR (1 << 7) +#define UARTLSR_TE (1 << 6) +#define UARTLSR_TFE (1 << 5) +#define UARTLSR_BI (1 << 4) +#define UARTLSR_FE (1 << 3) +#define UARTLSR_PE (1 << 2) +#define UARTLSR_OE (1 << 1) +#define UARTLSR_DR (1 << 0) + +void rt_hw_uart_init(void); + + +#endif diff --git a/bsp/ls1bdev/drivers/uart.c b/bsp/ls1bdev/drivers/uart.c deleted file mode 100644 index e920d33057796a37c24b86e9629725314642fbe8..0000000000000000000000000000000000000000 --- a/bsp/ls1bdev/drivers/uart.c +++ /dev/null @@ -1,280 +0,0 @@ -/* - * File : board.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006-2012, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-08-08 lgnq first version - */ - -#include -#include - -#include "uart.h" - -/** - * @addtogroup Loongson LS1B - */ - -/*@{*/ - -#if defined(RT_USING_DEVICE) - -struct rt_uart_ls1b -{ - struct rt_device parent; - - rt_uint32_t hw_base; - rt_uint32_t irq; - - /* buffer for reception */ - rt_uint8_t read_index, save_index; - rt_uint8_t rx_buffer[RT_UART_RX_BUFFER_SIZE]; -}uart_device; - -static void rt_uart_irqhandler(int irqno, void *param) -{ - rt_ubase_t level; - rt_uint8_t isr; - struct rt_uart_ls1b *uart = &uart_device; - - /* read interrupt status and clear it */ - isr = UART_IIR(uart->hw_base); - isr = (isr >> 1) & 0x3; - - /* receive data available */ - if (isr & 0x02) - { - /* Receive Data Available */ - while (UART_LSR(uart->hw_base) & UARTLSR_DR) - { - uart->rx_buffer[uart->save_index] = UART_DAT(uart->hw_base); - - level = rt_hw_interrupt_disable(); - uart->save_index ++; - if (uart->save_index >= RT_UART_RX_BUFFER_SIZE) - uart->save_index = 0; - rt_hw_interrupt_enable(level); - } - - /* invoke callback */ - if (uart->parent.rx_indicate != RT_NULL) - { - rt_size_t length; - if (uart->read_index > uart->save_index) - length = RT_UART_RX_BUFFER_SIZE - uart->read_index + uart->save_index; - else - length = uart->save_index - uart->read_index; - - uart->parent.rx_indicate(&uart->parent, length); - } - } - - return; -} - -static rt_err_t rt_uart_init(rt_device_t dev) -{ - rt_uint32_t baud_div; - struct rt_uart_ls1b *uart = (struct rt_uart_ls1b *)dev; - - RT_ASSERT(uart != RT_NULL); - -#if 0 - /* init UART Hardware */ - UART_IER(uart->hw_base) = 0; /* clear interrupt */ - UART_FCR(uart->hw_base) = 0x60; /* reset UART Rx/Tx */ - - /* enable UART clock */ - /* set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */ - UART_LCR(uart->hw_base) = 0x3; - - /* set baudrate */ - baud_div = DEV_CLK / 16 / UART_BAUDRATE; - UART_LCR(uart->hw_base) |= UARTLCR_DLAB; - - UART_MSB(uart->hw_base) = (baud_div >> 8) & 0xff; - UART_LSB(uart->hw_base) = baud_div & 0xff; - - UART_LCR(uart->hw_base) &= ~UARTLCR_DLAB; - - /* Enable UART unit, enable and clear FIFO */ - UART_FCR(uart->hw_base) = UARTFCR_UUE | UARTFCR_FE | UARTFCR_TFLS | UARTFCR_RFLS; -#endif - - return RT_EOK; -} - -static rt_err_t rt_uart_open(rt_device_t dev, rt_uint16_t oflag) -{ - struct rt_uart_ls1b *uart = (struct rt_uart_ls1b *)dev; - - RT_ASSERT(uart != RT_NULL); - if (dev->flag & RT_DEVICE_FLAG_INT_RX) - { - /* Enable the UART Interrupt */ - UART_IER(uart->hw_base) |= UARTIER_IRXE; - - /* install interrupt */ - rt_hw_interrupt_install(uart->irq, rt_uart_irqhandler, RT_NULL, "UART"); - rt_hw_interrupt_umask(uart->irq); - } - return RT_EOK; -} - -static rt_err_t rt_uart_close(rt_device_t dev) -{ - struct rt_uart_ls1b *uart = (struct rt_uart_ls1b *)dev; - - RT_ASSERT(uart != RT_NULL); - if (dev->flag & RT_DEVICE_FLAG_INT_RX) - { - /* Disable the UART Interrupt */ - UART_IER(uart->hw_base) &= ~(UARTIER_IRXE); - } - - return RT_EOK; -} - -static rt_size_t rt_uart_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) -{ - rt_uint8_t *ptr; - struct rt_uart_ls1b *uart = (struct rt_uart_ls1b *)dev; - - RT_ASSERT(uart != RT_NULL); - - /* point to buffer */ - ptr = (rt_uint8_t *)buffer; - if (dev->flag & RT_DEVICE_FLAG_INT_RX) - { - while (size) - { - /* interrupt receive */ - rt_base_t level; - - /* disable interrupt */ - level = rt_hw_interrupt_disable(); - if (uart->read_index != uart->save_index) - { - *ptr = uart->rx_buffer[uart->read_index]; - - uart->read_index ++; - if (uart->read_index >= RT_UART_RX_BUFFER_SIZE) - uart->read_index = 0; - } - else - { - /* no data in rx buffer */ - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - break; - } - - /* enable interrupt */ - rt_hw_interrupt_enable(level); - - ptr ++; - size --; - } - - return (rt_uint32_t)ptr - (rt_uint32_t)buffer; - } - - return 0; -} - -static rt_size_t rt_uart_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) -{ - char *ptr; - struct rt_uart_ls1b *uart = (struct rt_uart_ls1b *)dev; - - RT_ASSERT(uart != RT_NULL); - - ptr = (char *)buffer; - - if (dev->flag & RT_DEVICE_FLAG_STREAM) - { - /* stream mode */ - while (size) - { - if (*ptr == '\n') - { - /* FIFO status, contain valid data */ - while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); - /* write data */ - UART_DAT(uart->hw_base) = '\r'; - } - - /* FIFO status, contain valid data */ - while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); - /* write data */ - UART_DAT(uart->hw_base) = *ptr; - - ptr ++; - size --; - } - } - else - { - while (size != 0) - { - /* FIFO status, contain valid data */ - while (!(UART_LSR(uart->hw_base) & (UARTLSR_TE | UARTLSR_TFE))); - - /* write data */ - UART_DAT(uart->hw_base) = *ptr; - - ptr++; - size--; - } - } - - return (rt_size_t)ptr - (rt_size_t)buffer; -} - -void rt_hw_uart_init(void) -{ - struct rt_uart_ls1b *uart; - - /* get uart device */ - uart = &uart_device; - - /* device initialization */ - uart->parent.type = RT_Device_Class_Char; - rt_memset(uart->rx_buffer, 0, sizeof(uart->rx_buffer)); - uart->read_index = uart->save_index = 0; - -#if defined(RT_USING_UART0) - uart->hw_base = UART0_BASE; - uart->irq = LS1B_UART0_IRQ; -#elif defined(RT_USING_UART1) - uart->hw_base = UART1_BASE; - uart->irq = LS1B_UART1_IRQ; -#elif defined(RT_USING_UART3) - uart->hw_base = UART3_BASE; - uart->irq = LS1B_UART3_IRQ; -#endif - - /* device interface */ - uart->parent.init = rt_uart_init; - uart->parent.open = rt_uart_open; - uart->parent.close = rt_uart_close; - uart->parent.read = rt_uart_read; - uart->parent.write = rt_uart_write; - uart->parent.control = RT_NULL; - uart->parent.user_data = RT_NULL; - - rt_device_register(&uart->parent, "uart0", - RT_DEVICE_FLAG_RDWR | - RT_DEVICE_FLAG_STREAM | - RT_DEVICE_FLAG_INT_RX); -} -#endif /* end of UART */ - -/*@}*/ diff --git a/bsp/ls1bdev/drivers/uart.h b/bsp/ls1bdev/drivers/uart.h deleted file mode 100644 index bec660b74090d6481061368a78f53d1f68537d8d..0000000000000000000000000000000000000000 --- a/bsp/ls1bdev/drivers/uart.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * File : uart.h - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006-2012, RT-Thread Develop Team - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE - * - * Change Logs: - * Date Author Notes - * 2011-08-08 lgnq first version for LS1B - */ - -#ifndef __UART_H__ -#define __UART_H__ - -#include "ls1b.h" -#include - -#define UART0_BASE 0xBFE40000 -#define UART0_1_BASE 0xBFE41000 -#define UART0_2_BASE 0xBFE42000 -#define UART0_3_BASE 0xBFE43000 -#define UART1_BASE 0xBFE44000 -#define UART1_1_BASE 0xBFE45000 -#define UART1_2_BASE 0xBFE46000 -#define UART1_3_BASE 0xBFE47000 -#define UART2_BASE 0xBFE48000 -#define UART3_BASE 0xBFE4C000 -#define UART4_BASE 0xBFE6C000 -#define UART5_BASE 0xBFE7C000 - -/* UART registers */ -#define UART_DAT(base) HWREG8(base + 0x00) -#define UART_IER(base) HWREG8(base + 0x01) -#define UART_IIR(base) HWREG8(base + 0x02) -#define UART_FCR(base) HWREG8(base + 0x02) -#define UART_LCR(base) HWREG8(base + 0x03) -#define UART_MCR(base) HWREG8(base + 0x04) -#define UART_LSR(base) HWREG8(base + 0x05) -#define UART_MSR(base) HWREG8(base + 0x06) - -#define UART_LSB(base) HWREG8(base + 0x00) -#define UART_MSB(base) HWREG8(base + 0x01) - -/* UART0 registers */ -#define UART0_DAT HWREG8(UART0_BASE + 0x00) -#define UART0_IER HWREG8(UART0_BASE + 0x01) -#define UART0_IIR HWREG8(UART0_BASE + 0x02) -#define UART0_FCR HWREG8(UART0_BASE + 0x02) -#define UART0_LCR HWREG8(UART0_BASE + 0x03) -#define UART0_MCR HWREG8(UART0_BASE + 0x04) -#define UART0_LSR HWREG8(UART0_BASE + 0x05) -#define UART0_MSR HWREG8(UART0_BASE + 0x06) - -#define UART0_LSB HWREG8(UART0_BASE + 0x00) -#define UART0_MSB HWREG8(UART0_BASE + 0x01) - -/* UART1 registers */ -#define UART1_DAT HWREG8(UART1_BASE + 0x00) -#define UART1_IER HWREG8(UART1_BASE + 0x01) -#define UART1_IIR HWREG8(UART1_BASE + 0x02) -#define UART1_FCR HWREG8(UART1_BASE + 0x02) -#define UART1_LCR HWREG8(UART1_BASE + 0x03) -#define UART1_MCR HWREG8(UART1_BASE + 0x04) -#define UART1_LSR HWREG8(UART1_BASE + 0x05) -#define UART1_MSR HWREG8(UART1_BASE + 0x06) - -#define UART1_LSB HWREG8(UART1_BASE + 0x00) -#define UART1_MSB HWREG8(UART1_BASE + 0x01) - -/* UART interrupt enable register value */ -#define UARTIER_IME (1 << 3) -#define UARTIER_ILE (1 << 2) -#define UARTIER_ITXE (1 << 1) -#define UARTIER_IRXE (1 << 0) - -/* UART line control register value */ -#define UARTLCR_DLAB (1 << 7) -#define UARTLCR_BCB (1 << 6) -#define UARTLCR_SPB (1 << 5) -#define UARTLCR_EPS (1 << 4) -#define UARTLCR_PE (1 << 3) -#define UARTLCR_SB (1 << 2) - -/* UART line status register value */ -#define UARTLSR_ERROR (1 << 7) -#define UARTLSR_TE (1 << 6) -#define UARTLSR_TFE (1 << 5) -#define UARTLSR_BI (1 << 4) -#define UARTLSR_FE (1 << 3) -#define UARTLSR_PE (1 << 2) -#define UARTLSR_OE (1 << 1) -#define UARTLSR_DR (1 << 0) - -void rt_hw_uart_init(void); - -#endif diff --git a/bsp/ls1bdev/libraries/SConscript b/bsp/ls1bdev/libraries/SConscript new file mode 100644 index 0000000000000000000000000000000000000000..78797ef273ebce75972a9404757b0e627d817101 --- /dev/null +++ b/bsp/ls1bdev/libraries/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('Libraries', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/ls1bdev/libraries/ls1b_clock.c b/bsp/ls1bdev/libraries/ls1b_clock.c new file mode 100644 index 0000000000000000000000000000000000000000..05547a158c3a74d209dc57626d111edef84abfde --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_clock.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ + + +#include "rtconfig.h" +#include "ls1b_regs.h" +#include "ls1b_public.h" + + +// 晶振的频率 +#define AHB_CLK (RT_OSC_CLK) +#define APB_CLK (AHB_CLK) + +#define DIV_DC_EN (0x1 << 31) +#define DIV_DC (0x1f << 26) +#define DIV_CPU_EN (0x1 << 25) +#define DIV_CPU (0x1f << 20) +#define DIV_DDR_EN (0x1 << 19) +#define DIV_DDR (0x1f << 14) + +#define DIV_DC_SHIFT 26 +#define DIV_CPU_SHIFT 20 +#define DIV_DDR_SHIFT 14 + + +/* + * 获取PLL频率 + * @ret PLL频率 + */ +unsigned long clk_get_pll_rate(void) +{ + unsigned int ctrl; + unsigned long pll_rate = 0; + + ctrl = reg_read_32((volatile unsigned int *)LS1B_START_FREQ); + pll_rate = (12 + (ctrl & 0x3f)) * APB_CLK / 2 + + ((ctrl >> 8) & 0x3ff) * APB_CLK / 1024 / 2; + + return pll_rate; +} + + +/* + * 获取CPU频率 + * @ret CPU频率 + */ +unsigned long clk_get_cpu_rate(void) +{ + unsigned long pll_rate, cpu_rate; + unsigned int ctrl; + + pll_rate = clk_get_pll_rate(); + ctrl = reg_read_32((volatile unsigned int *)LS1B_CLK_DIV_PARAM); + cpu_rate = pll_rate / ((ctrl & DIV_CPU) >> DIV_CPU_SHIFT); + + return cpu_rate; +} + + +/* + * 获取DDR频率 + * @ret DDR频率 + */ +unsigned long clk_get_ddr_rate(void) +{ + unsigned long pll_rate, ddr_rate; + unsigned int ctrl; + + pll_rate = clk_get_pll_rate(); + ctrl = reg_read_32((volatile unsigned int *)LS1B_CLK_DIV_PARAM); + + ddr_rate = pll_rate / ((ctrl & DIV_DDR) >> DIV_DDR_SHIFT); + + return ddr_rate; +} + + +/* + * 获取APB频率 + * @ret APB频率 + */ +unsigned long clk_get_apb_rate(void) +{ + return clk_get_ddr_rate() / 2; +} + + +/* + * 获取DC频率 + * @ret DC频率 + */ +unsigned long clk_get_dc_rate(void) +{ + unsigned long pll_rate, dc_rate; + unsigned int ctrl; + + pll_rate = clk_get_pll_rate(); + ctrl = reg_read_32((volatile unsigned int *)LS1B_CLK_DIV_PARAM); + + dc_rate = pll_rate ; + + return dc_rate; +} + + + diff --git a/bsp/ls1bdev/libraries/ls1b_clock.h b/bsp/ls1bdev/libraries/ls1b_clock.h new file mode 100644 index 0000000000000000000000000000000000000000..bd22986e4c77dc5efcebabf2c693d578add7fecb --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_clock.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 Ϊ first version + */ + + +#ifndef __LOONGSON_CLOCK_H +#define __LOONGSON_CLOCK_H + + + +/* + * ȡPLLƵ + * @ret PLLƵ + */ +unsigned long clk_get_pll_rate(void); + + +/* + * ȡCPUƵ + * @ret CPUƵ + */ +unsigned long clk_get_cpu_rate(void); + + + +/* + * ȡDDRƵ + * @ret DDRƵ + */ +unsigned long clk_get_ddr_rate(void); + + +/* + * ȡAPBƵ + * @ret APBƵ + */ +unsigned long clk_get_apb_rate(void); + + +/* + * ȡDCƵ + * @ret DCƵ + */ +unsigned long clk_get_dc_rate(void); + + + +#endif + diff --git a/bsp/ls1bdev/libraries/ls1b_gpio.c b/bsp/ls1bdev/libraries/ls1b_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..2e100e712240e3ebba242c0af65989c0b13547f9 --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_gpio.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ + + +#include "ls1b_public.h" +#include "ls1b_regs.h" +#include "ls1b_gpio.h" +#include "ls1b_pin.h" + + +/* + * 获取指定gpio的CFG寄存器 + * @gpio gpio编号 + * @ret CFG寄存器 + */ +volatile unsigned int *gpio_get_cfg_reg(unsigned int gpio) +{ + volatile unsigned int *gpio_cfgx = NULL; // GPIO_CFGx寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + + switch (port) + { + case 0: + gpio_cfgx = (volatile unsigned int *)LS1B_GPIO_CFG0; + break; + + case 1: + gpio_cfgx = (volatile unsigned int *)LS1B_GPIO_CFG1; + break; + default: + gpio_cfgx = NULL; + break; + } + + return gpio_cfgx; +} + + +/* + * 获取指定gpio的EN寄存器 + * @gpio gpio编号 + * @ret EN寄存器 + */ +volatile unsigned int *gpio_get_en_reg(unsigned int gpio) +{ + volatile unsigned int *gpio_enx = NULL; // GPIO_ENx寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + + switch (port) + { + case 0: + gpio_enx = (volatile unsigned int *)LS1B_GPIO_EN0; + break; + + case 1: + gpio_enx = (volatile unsigned int *)LS1B_GPIO_EN1; + break; + default: + gpio_enx = NULL; + return gpio_enx; + } + + return gpio_enx; +} + +/* + * gpio初始化 + * @gpio gpio引脚,取值范围[0, 127] + * @mode gpio的工作模式(输入、输出) + * + * 例: 将gpio50初始化为输出 + * gpio_init(50, gpio_mode_output); + */ +void gpio_init(unsigned int gpio, gpio_mode_t mode) +{ + volatile unsigned int *gpio_enx = NULL; // GPIO_ENx寄存器 + unsigned int pin = GPIO_GET_PIN(gpio); + + // 将pin设为普通GPIO + pin_set_purpose(gpio, PIN_PURPOSE_GPIO); + + // 设置gpio工作模式(输入、输出) + gpio_enx = gpio_get_en_reg(gpio); + if (gpio_mode_output == mode) // 输出 + { + reg_clr_one_bit(gpio_enx, pin); + } + else // 输入 + { + reg_set_one_bit(gpio_enx, pin); + } + + return ; +} + + +/* + * 在指定gpio输出高电平或低电平 + * @gpio gpio引脚,取值范围[0, 127] + * @level 电平值 + * + * 例: 在gpio50上输出低电平 + * gpio_set(50, gpio_level_low); + */ +void gpio_set(unsigned int gpio, gpio_level_t level) +{ + volatile unsigned int *gpio_outx = NULL; // GPIO_OUTx寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + unsigned int pin = GPIO_GET_PIN(gpio); + + // 获取寄存器地址 + switch (port) + { + case 0: + gpio_outx = (volatile unsigned int *)LS1B_GPIO_OUT0; + break; + + case 1: + gpio_outx = (volatile unsigned int *)LS1B_GPIO_OUT1; + break; + default: // 正确的程序不应该走到这里,直接返回 + return ; + } + + // 输出 + if (gpio_level_low == level) + { + reg_clr_one_bit(gpio_outx, pin); + } + else + { + reg_set_one_bit(gpio_outx, pin); + } + + return ; +} + + +/* + * 读取指定gpio引脚的值 + * @gpio gpio引脚,取值范围[0,127] + * + * 例: 读取gpio50引脚上的值 + * gpio_level_t level; + * level = gpio_get(50); + */ +unsigned int gpio_get(unsigned int gpio) +{ + volatile unsigned int *gpio_inx = NULL; // GPIO_INx寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + unsigned int pin = GPIO_GET_PIN(gpio); + + // 获取寄存器地址 + switch (port) + { + case 0: + gpio_inx = (volatile unsigned int *)LS1B_GPIO_IN0; + break; + + case 1: + gpio_inx = (volatile unsigned int *)LS1B_GPIO_IN1; + break; + default: // 正常的流程不应该走到这里,直接返回 + return 0; + } + + // 读取 + return reg_get_bit(gpio_inx, pin); +} + + +/** + * 设置中断类型 + * @gpio gpio引脚 + * @type 触发中断的条件。高电平触发、低电平触发、上升沿触发 or 下降沿触发 + */ +void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type) +{ + volatile unsigned int *int_pol = NULL; // 中断极性选择寄存器 + volatile unsigned int *int_edge = NULL; // 中断边沿选择寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + unsigned int pin = GPIO_GET_PIN(gpio); + + // 获取寄存器地址 + switch (port) + { + case 0: // GPIO[31:0] + int_pol = (volatile unsigned int *)LS1B_INT2_POL; + int_edge = (volatile unsigned int *)LS1B_INT2_EDGE; + break; + + case 1: // GPIO[63:32] + int_pol = (volatile unsigned int *)LS1B_INT3_POL; + int_edge = (volatile unsigned int *)LS1B_INT3_EDGE; + break; + + } + + // 设置中断类型 + switch (type) + { + case IRQ_TYPE_EDGE_RISING: + *int_pol |= (1 << pin); + *int_edge |= (1 << pin); + break; + + case IRQ_TYPE_EDGE_FALLING: + *int_pol &= ~(1 << pin); + *int_edge |= (1 << pin); + break; + + case IRQ_TYPE_LEVEL_HIGH: + *int_pol |= (1 << pin); + *int_edge &= ~(1 << pin); + break; + + case IRQ_TYPE_LEVEL_LOW: + *int_pol &= ~(1 << pin); + *int_edge &= ~(1 << pin); + break; + + default: + break; + } + + return ; +} + + + diff --git a/bsp/ls1bdev/libraries/ls1b_gpio.h b/bsp/ls1bdev/libraries/ls1b_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..cfbe148020e699f830b6f6c1ce9c2fd4111cc4c1 --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_gpio.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + */ + + +#ifndef __LOONGSON_GPIO_H +#define __LOONGSON_GPIO_H + + + +// 龙芯1c的gpio是按照0,1,2,3,4...这样的顺序编号的, +// 但在操作寄存器的时候,又是按照每32个一组来分的 +// 这里利用这个特性,将每组的32个gpio叫做一个"port",每个gpio在每组中的索引叫"pin" +// port = gpio / 32 +// pin = gpio % 32 +// 例如GPIO50,port=1,pin=18 +#define GPIO_GET_PORT(gpio) ((gpio) / 32) +#define GPIO_GET_PIN(gpio) ((gpio) % 32) + + +// gpio的工作模式--输入、输出 +typedef enum{ + gpio_mode_output = 0, // 输出 + gpio_mode_input = 1 // 输入 +}gpio_mode_t; + + +// gpio高低电平值 +typedef enum{ + gpio_level_low = 0, // 低电平 + gpio_level_high = 1 // 高电平 +}gpio_level_t; + + +typedef enum { + // 上升沿触发 + IRQ_TYPE_EDGE_RISING = 0x00000001, + // 下降沿触发 + IRQ_TYPE_EDGE_FALLING = 0x00000002, + IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING), + // 高电平触发 + IRQ_TYPE_LEVEL_HIGH = 0x00000004, + // 低电平触发 + IRQ_TYPE_LEVEL_LOW = 0x00000008, + IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH), +}gpio_irq_type_t; + + + +/* + * 获取指定gpio的CFG寄存器 + * @gpio gpio编号 + * @ret CFG寄存器 + */ +volatile unsigned int *gpio_get_cfg_reg(unsigned int gpio); + +/* + * gpio初始化 + * @gpio gpio引脚,取值范围[0, 127] + * @mode gpio的工作模式(输入、输出) + * + * 例: 将gpio50初始化为输出 + * gpio_init(50, gpio_mode_output); + */ +void gpio_init(unsigned int gpio, gpio_mode_t mode); + + +/* + * 在指定gpio输出高电平或低电平 + * @gpio gpio引脚,取值范围[0, 127] + * @level 电平值 + * + * 例: 在gpio50上输出低电平 + * gpio_set(50, gpio_level_low); + */ +void gpio_set(unsigned int gpio, gpio_level_t level); + + + +/* + * 读取指定gpio引脚的值 + * @gpio gpio引脚,取值范围[0,127] + * + * 例: 读取gpio50引脚上的值 + * gpio_level_t level; + * level = gpio_get(50); + */ +unsigned int gpio_get(unsigned int gpio); + + + +/** + * 设置中断类型 + * @gpio gpio引脚 + * @type 触发中断的条件。高电平触发、低电平触发、上升沿触发 or 下降沿触发 + */ +void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type); + + + +#endif + diff --git a/bsp/ls1bdev/libraries/ls1b_pin.c b/bsp/ls1bdev/libraries/ls1b_pin.c new file mode 100644 index 0000000000000000000000000000000000000000..58d9e7e46caaf4fd686c36f2d1670e3f7a911069 --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_pin.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ + +// 引脚功能(普通gpio,pwm,复用等)相关接口 + + +#include "ls1b_public.h" +#include "ls1b_regs.h" +#include "ls1b_gpio.h" +#include "ls1b_pin.h" + + +/* + * 把指定pin设置为指定用途(普通gpio,非gpio) + * @gpio gpio引脚编号 + * @purpose 用途 + */ +void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose) +{ + volatile unsigned int *gpio_cfgx; // GPIO_CFGx寄存器 + unsigned int pin = GPIO_GET_PIN(gpio); + + gpio_cfgx = gpio_get_cfg_reg(gpio); + if (PIN_PURPOSE_GPIO == purpose) // 引脚用作普通gpio + { + reg_set_one_bit(gpio_cfgx, pin); + } + else // 引脚用作其它功能(非gpio) + { + reg_clr_one_bit(gpio_cfgx, pin); + } + + return ; +} + + + +/* + * 设置指定pin为第n复用 + * @gpio gpio编号 + * @remap 第n复用 + */ +void pin_set_remap(unsigned int gpio, pin_remap_t remap) +{ + volatile unsigned int *reg = NULL; // 复用寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + unsigned int pin = GPIO_GET_PIN(gpio); + int i; + + /*指定全部pin复用为0*/ + for (i = 0; i <= 4; i++) + { + reg = (volatile unsigned int *)((LS1B_CBUS_FIRST0) + ((port) * 0x04) + ((i) * 0x10)); + // 置0 + reg_clr_one_bit(reg, pin); + } + + if (remap == PIN_REMAP_DEFAULT) return; + + switch (port) + { + case 0: + switch (remap) + { + case PIN_REMAP_FIRST: + reg = (volatile unsigned int *)LS1B_CBUS_FIRST0; + break; + case PIN_REMAP_SECOND: + reg = (volatile unsigned int *)LS1B_CBUS_SECOND0; + break; + case PIN_REMAP_THIRD: + reg = (volatile unsigned int *)LS1B_CBUS_THIRD0; + break; + case PIN_REMAP_FOURTH: + reg = (volatile unsigned int *)LS1B_CBUS_FOURTH0; + break; + case PIN_REMAP_FIFTH: + reg = (volatile unsigned int *)LS1B_CBUS_FIFTH0; + break; + } + break; + + case 1: + switch (remap) + { + case PIN_REMAP_FIRST: + reg = (volatile unsigned int *)LS1B_CBUS_FIRST1; + break; + case PIN_REMAP_SECOND: + reg = (volatile unsigned int *)LS1B_CBUS_SECOND1; + break; + case PIN_REMAP_THIRD: + reg = (volatile unsigned int *)LS1B_CBUS_THIRD1; + break; + case PIN_REMAP_FOURTH: + reg = (volatile unsigned int *)LS1B_CBUS_FOURTH1; + break; + case PIN_REMAP_FIFTH: + reg = (volatile unsigned int *)LS1B_CBUS_FIFTH1; + break; + } + break; + + case 2: + switch (remap) + { + case PIN_REMAP_FIRST: + reg = (volatile unsigned int *)LS1B_CBUS_FIRST2; + break; + case PIN_REMAP_SECOND: + reg = (volatile unsigned int *)LS1B_CBUS_SECOND2; + break; + case PIN_REMAP_THIRD: + reg = (volatile unsigned int *)LS1B_CBUS_THIRD2; + break; + case PIN_REMAP_FOURTH: + reg = (volatile unsigned int *)LS1B_CBUS_FOURTH2; + break; + case PIN_REMAP_FIFTH: + reg = (volatile unsigned int *)LS1B_CBUS_FIFTH2; + break; + } + break; + + case 3: + switch (remap) + { + case PIN_REMAP_FIRST: + reg = (volatile unsigned int *)LS1B_CBUS_FIRST3; + break; + case PIN_REMAP_SECOND: + reg = (volatile unsigned int *)LS1B_CBUS_SECOND3; + break; + case PIN_REMAP_THIRD: + reg = (volatile unsigned int *)LS1B_CBUS_THIRD3; + break; + case PIN_REMAP_FOURTH: + reg = (volatile unsigned int *)LS1B_CBUS_FOURTH3; + break; + case PIN_REMAP_FIFTH: + reg = (volatile unsigned int *)LS1B_CBUS_FIFTH3; + break; + } + break; + + default: + return ; + } + + // 置1 + reg_set_one_bit(reg, pin); + + return ; +} + + + diff --git a/bsp/ls1bdev/libraries/ls1b_pin.h b/bsp/ls1bdev/libraries/ls1b_pin.h new file mode 100644 index 0000000000000000000000000000000000000000..af63ba41876dfd54a51a7a4363876f5251b648df --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_pin.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + */ + +// 引脚功能(普通gpio,pwm,复用等)相关接口 + +#ifndef __LOONGSON_PIN_H +#define __LOONGSON_PIN_H + + +// 引脚用途 +typedef enum +{ + PIN_PURPOSE_GPIO = 0, // 引脚用作普通gpio + PIN_PURPOSE_OTHER, // 引脚用作其它功能(非gpio) +}pin_purpose_t; + + +// 引脚复用 +typedef enum +{ + PIN_REMAP_FIRST = 0, // 第一复用 + PIN_REMAP_SECOND, // 第二复用 + PIN_REMAP_THIRD, // 第三复用 + PIN_REMAP_FOURTH, // 第四复用 + PIN_REMAP_FIFTH, // 第五复用 + PIN_REMAP_DEFAULT, //缺省复用 +}pin_remap_t; + + +/* + * 把指定pin设置为指定用途(普通gpio,非gpio) + * @gpio gpio引脚编号 + * @purpose 用途 + */ +void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose); + + +/* + * 设置指定pin为第n复用 + * @gpio gpio编号 + * @remap 第n复用 + */ +void pin_set_remap(unsigned int gpio, pin_remap_t remap); + + +#endif + diff --git a/bsp/ls1bdev/libraries/ls1b_public.c b/bsp/ls1bdev/libraries/ls1b_public.c new file mode 100644 index 0000000000000000000000000000000000000000..b48d59a851391853caca40ed9a3b5323d96d4baa --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_public.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ + +// 一些常用的、共用的接口 + +/* + * 将指定寄存器的指定位置1 + * @reg 寄存器地址 + * @bit 需要置1的那一bit + */ +void reg_set_one_bit(volatile unsigned int *reg, unsigned int bit) +{ + unsigned int temp, mask; + + mask = 1 << bit; + temp = *reg; + temp |= mask; + *reg = temp; + + return ; +} + + +/* + * 将指定寄存器的指定位清零 + * @reg 寄存器地址 + * @bit 需要清零的那一bit + */ +void reg_clr_one_bit(volatile unsigned int *reg, unsigned int bit) +{ + unsigned int temp, mask; + + mask = 1 << bit; + temp = *reg; + temp &= ~mask; + *reg = temp; + + return ; +} + + + +/* + * 获取指定寄存器的指定位的值 + * @reg 寄存器地址 + * @bit 需要读取值的那一bit + * @ret 指定位的值 + */ +unsigned int reg_get_bit(volatile unsigned int *reg, unsigned int bit) +{ + unsigned int temp; + + temp = *reg; + temp = (temp >> bit) & 1; + + return temp; +} + + +/* + * 向寄存器中写入8bit(一个字节)数据 + * @data 待写入的数据 + * @addr 寄存器地址 + */ +void reg_write_8(unsigned char data, volatile unsigned char *addr) +{ + *addr = data; +} + + +/* + * 从寄存器读出8bit(一个字节)数据 + * @addr 寄存器地址 + * @ret 读出的数据 + */ +unsigned char reg_read_8(volatile unsigned char *addr) +{ + return (*addr); +} + + +/* + * 向寄存器中写一个32bit的数据 + * @data 待写入的数据 + * @addr 寄存器地址 + */ +void reg_write_32(unsigned int data, volatile unsigned int *addr) +{ + *addr = data; +} + + +/* + * 从寄存器读出一个32bit数据 + * @addr 寄存器地址 + * @ret 读出的数据 + */ +unsigned int reg_read_32(volatile unsigned int *addr) +{ + return (*addr); +} + + + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +int ls1b_ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + + +/* + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +int ls1b_fls(int x) +{ + int r = 32; + + if (!x) + return 0; + if (!(x & 0xffff0000u)) + { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) + { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) + { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) + { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) + { + x <<= 1; + r -= 1; + } + + return r; +} + + diff --git a/bsp/ls1bdev/libraries/ls1b_public.h b/bsp/ls1bdev/libraries/ls1b_public.h new file mode 100644 index 0000000000000000000000000000000000000000..875f413062c91c3a21c0474a24aa6cbd3f7634cb --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_public.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + */ + +// 一些常用的、共用的接口 + +#ifndef __LOONGSON_PUBLIC_H +#define __LOONGSON_PUBLIC_H + + +#include + + +// pmon提供的打印函数,见main()函数 +struct callvectors { + int (*open) (char *, int, int); + int (*close) (int); + int (*read) (int, void *, int); + int (*write) (int, void *, int); + long long (*lseek) (int, long long, int); + int (*printf) (const char *, ...); + void (*cacheflush) (void); + char *(*gets) (char *); +}; +#define myprintf (*callvec->printf) +#define mygets (*callvec->gets) +extern struct callvectors *callvec; + + +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + +#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) + +typedef enum +{ + FALSE=0, + TRUE=1 +}BOOL; + +/* + * 将指定寄存器的指定位置1 + * @reg 寄存器地址 + * @bit 需要置1的那一bit + */ +void reg_set_one_bit(volatile unsigned int *reg, unsigned int bit); + + +/* + * 将指定寄存器的指定位清零 + * @reg 寄存器地址 + * @bit 需要清零的那一bit + */ +void reg_clr_one_bit(volatile unsigned int *reg, unsigned int bit); + + +/* + * 获取指定寄存器的指定位的值 + * @reg 寄存器地址 + * @bit 需要读取值的那一bit + * @ret 指定位的值 + */ +unsigned int reg_get_bit(volatile unsigned int *reg, unsigned int bit); + + +/* + * 向寄存器中写入8bit(一个字节)数据 + * @data 待写入的数据 + * @addr 寄存器地址 + */ +void reg_write_8(unsigned char data, volatile unsigned char *addr); + + +/* + * 从寄存器读出8bit(一个字节)数据 + * @addr 寄存器地址 + * @ret 读出的数据 + */ +unsigned char reg_read_8(volatile unsigned char *addr); + + +/* + * 向寄存器中写一个32bit的数据 + * @data 待写入的数据 + * @addr 寄存器地址 + */ +void reg_write_32(unsigned int data, volatile unsigned int *addr); + + +/* + * 从寄存器读出一个32bit数据 + * @addr 寄存器地址 + * @ret 读出的数据 + */ +unsigned int reg_read_32(volatile unsigned int *addr); + + +/** + * ffs - find first bit set + * @x: the word to search + */ +int ls1b_ffs(int x); + +/* + * fls - find last (most-significant) bit set + * @x: the word to search + * + * This is defined the same way as ffs. + * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. + */ +int ls1b_fls(int x); + + +#endif + diff --git a/bsp/ls1bdev/libraries/ls1b_regs.h b/bsp/ls1bdev/libraries/ls1b_regs.h new file mode 100644 index 0000000000000000000000000000000000000000..6dad9c29bb1ad2ad733ba4693a6982f94ba3e087 --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_regs.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-09-06 勤为本 first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ + +// 龙芯1b外设寄存器 + + +#ifndef __LOONGSON_LS1B_REGS_H +#define __LOONGSON_LS1B_REGS_H + + + + +// 时钟相关寄存器地址 +#define LS1B_START_FREQ (0xbfe78030) +#define LS1B_CLK_DIV_PARAM (0xbfe78034) + + +// gpio相关寄存器地址 +#define LS1B_GPIO_CFG0 (0xbfd010c0) +#define LS1B_GPIO_EN0 (0xbfd010d0) +#define LS1B_GPIO_IN0 (0xbfd010e0) +#define LS1B_GPIO_OUT0 (0xbfd010f0) + +#define LS1B_GPIO_CFG1 (0xbfd010c4) +#define LS1B_GPIO_EN1 (0xbfd010d4) +#define LS1B_GPIO_IN1 (0xbfd010e4) +#define LS1B_GPIO_OUT1 (0xbfd010f4) + + + +// 复用相关寄存器 +#define LS1B_CBUS_FIRST0 (0xbfd011c0) +#define LS1B_CBUS_SECOND0 (0xbfd011d0) +#define LS1B_CBUS_THIRD0 (0xbfd011e0) +#define LS1B_CBUS_FOURTH0 (0xbfd011f0) +#define LS1B_CBUS_FIFTH0 (0xbfd01200) + +#define LS1B_CBUS_FIRST1 (0xbfd011c4) +#define LS1B_CBUS_SECOND1 (0xbfd011d4) +#define LS1B_CBUS_THIRD1 (0xbfd011e4) +#define LS1B_CBUS_FOURTH1 (0xbfd011f4) +#define LS1B_CBUS_FIFTH1 (0xbfd01204) + +#define LS1B_CBUS_FIRST2 (0xbfd011c8) +#define LS1B_CBUS_SECOND2 (0xbfd011d8) +#define LS1B_CBUS_THIRD2 (0xbfd011e8) +#define LS1B_CBUS_FOURTH2 (0xbfd011f8) +#define LS1B_CBUS_FIFTH2 (0xbfd01208) + +#define LS1B_CBUS_FIRST3 (0xbfd011cc) +#define LS1B_CBUS_SECOND3 (0xbfd011dc) +#define LS1B_CBUS_THIRD3 (0xbfd011ec) +#define LS1B_CBUS_FOURTH3 (0xbfd011fc) +#define LS1B_CBUS_FIFTH3 (0xbfd0120c) + + +// PWM寄存器偏移 +#define LS1B_PWM_CNTR (0x0) +#define LS1B_PWM_HRC (0x4) +#define LS1B_PWM_LRC (0x8) +#define LS1B_PWM_CTRL (0xC) +// PWM基地址 +#define LS1B_REG_BASE_PWM0 (0xbfe5c000) +#define LS1B_REG_BASE_PWM1 (0xbfe5c010) +#define LS1B_REG_BASE_PWM2 (0xbfe5c020) +#define LS1B_REG_BASE_PWM3 (0xbfe5c030) + +//CAN基地址 +#define LS1B_REG_BASE_CAN0 (0xbfe50000) +#define LS1B_REG_BASE_CAN1 (0xbfe54000) + +// 中断配置寄存器 +#define LS1B_INT0_SR (0xbfd01040) +#define LS1B_INT0_EN (0xbfd01044) +#define LS1B_INT0_SET (0xbfd01048) +#define LS1B_INT0_CLR (0xbfd0104c) +#define LS1B_INT0_POL (0xbfd01050) +#define LS1B_INT0_EDGE (0xbfd01054) + +#define LS1B_INT1_SR (0xbfd01058) +#define LS1B_INT1_EN (0xbfd0105c) +#define LS1B_INT1_SET (0xbfd01060) +#define LS1B_INT1_CLR (0xbfd01064) +#define LS1B_INT1_POL (0xbfd01068) +#define LS1B_INT1_EDGE (0xbfd0106c) + +#define LS1B_INT2_SR (0xbfd01070) +#define LS1B_INT2_EN (0xbfd01074) +#define LS1B_INT2_SET (0xbfd01078) +#define LS1B_INT2_CLR (0xbfd0107c) +#define LS1B_INT2_POL (0xbfd01080) +#define LS1B_INT2_EDGE (0xbfd01084) + +#define LS1B_INT3_SR (0xbfd01088) +#define LS1B_INT3_EN (0xbfd0108c) +#define LS1B_INT3_SET (0xbfd01090) +#define LS1B_INT3_CLR (0xbfd01094) +#define LS1B_INT3_POL (0xbfd01098) +#define LS1B_INT3_EDGE (0xbfd0109c) + +#define LS1B_INT4_SR (0xbfd010a0) +#define LS1B_INT4_EN (0xbfd010a4) +#define LS1B_INT4_SET (0xbfd010a8) +#define LS1B_INT4_CLR (0xbfd010ac) +#define LS1B_INT4_POL (0xbfd010b0) +#define LS1B_INT4_EDGE (0xbfd010b4) + + +// I2C寄存器 +#define LS1B_I2C0_BASE (0xbfe58000) +#define LS1B_I2C1_BASE (0xbfe68000) +#define LS1B_I2C2_BASE (0xbfe70000) + + +// SPI寄存器 +#define LS1B_SPI0_BASE (0xbfe80000) +#define LS1B_SPI1_BASE (0xbfec0000) + + +// 串口寄存器 +#define LS1B_UART00_BASE (0xbfe40000) +#define LS1B_UART01_BASE (0xbfe41000) +#define LS1B_UART1_BASE (0xbfe44000) +#define LS1B_UART2_BASE (0xbfe48000) +#define LS1B_UART3_BASE (0xbfe4c000) +#define LS1B_UART4_BASE (0xbfe6c000) +#define LS1B_UART5_BASE (0xbfe7c000) +#define LS1B_UART6_BASE (0xbfe41000) +#define LS1B_UART7_BASE (0xbfe42000) +#define LS1B_UART8_BASE (0xbfe43000) +#define LS1B_UART9_BASE (0xbfe45000) +#define LS1B_UART10_BASE (0xbfe46000) +#define LS1B_UART11_BASE (0xbfe47000) + +//RTC寄存器 +#define LS1B_RTC_BASE (0xbfe64024) + + +#endif + diff --git a/bsp/ls1bdev/libraries/ls1b_uart.c b/bsp/ls1bdev/libraries/ls1b_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..73d88438f5cfa1debe189979977682e3682cfbf5 --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_uart.c @@ -0,0 +1,251 @@ + /* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ +// 串口相关源码 + +#include +#include +#include "ls1b_public.h" +#include "ls1b_regs.h" +#include "ls1b_pin.h" +#include "ls1b_uart.h" +#include "ls1b_clock.h" +#include "ls1b.h" + + +// 串口线路状态寄存器的位域 +#define LS1B_UART_LSR_TE (1 << 6) +#define LS1B_UART_LSR_TFE (1 << 5) + + +// 打印缓存的大小 +#define LS1B_UART_PRINT_BUF_SIZE (256) + + +// 调试串口信息 +ls1b_uart_info_t debug_uart_info = {0}; + + +/* + * 获取指定串口模块的基地址 + * @UARTx 串口编号 + * @ret 基地址 + */ +void *uart_get_base(ls1b_uart_t UARTx) +{ + void *base = NULL; + + switch (UARTx) + { + case LS1B_UART00: + base = (void *)LS1B_UART00_BASE; + break; + case LS1B_UART01: + base = (void *)LS1B_UART01_BASE; + break; + + case LS1B_UART1: + base = (void *)LS1B_UART1_BASE; + break; + + case LS1B_UART2: + base = (void *)LS1B_UART2_BASE; + break; + + case LS1B_UART3: + base = (void *)LS1B_UART3_BASE; + break; + + case LS1B_UART4: + base = (void *)LS1B_UART4_BASE; + break; + + case LS1B_UART5: + base = (void *)LS1B_UART5_BASE; + break; + + case LS1B_UART6: + base = (void *)LS1B_UART6_BASE; + break; + + case LS1B_UART7: + base = (void *)LS1B_UART7_BASE; + break; + + case LS1B_UART8: + base = (void *)LS1B_UART8_BASE; + break; + + case LS1B_UART9: + base = (void *)LS1B_UART9_BASE; + break; + + case LS1B_UART10: + base = (void *)LS1B_UART10_BASE; + break; + + case LS1B_UART11: + base = (void *)LS1B_UART11_BASE; + break; + + default: + break; + } + + return base; +} + + +/* + * 初始化指定的串口模块 + * @uart_info_p 串口模块信息 + */ +void uart_init(ls1b_uart_info_t *uart_info_p) +{ + void *uart_base = uart_get_base(uart_info_p->UARTx); + unsigned long baudrate_div = 0; + + // 禁止所有中断 + reg_write_8(0, uart_base + LS1B_UART_IER_OFFSET); + + // 接收FIFO的中断申请Trigger为14字节,清空发送和接收FIFO,并复位 + reg_write_8(0xc3, uart_base + LS1B_UART_FCR_OFFSET); + + // 设置波特率 + reg_write_8(0x80, uart_base + LS1B_UART_LCR_OFFSET); + baudrate_div = clk_get_apb_rate() / 16 / uart_info_p->baudrate; + reg_write_8((baudrate_div >> 8) & 0xff, uart_base + LS1B_UART_MSB_OFFSET); + reg_write_8(baudrate_div & 0xff, uart_base + LS1B_UART_LSB_OFFSET); + + // 8个数据位,1个停止位,无校验 + reg_write_8(0x03, uart_base + LS1B_UART_LCR_OFFSET); + + // 使能接收中断 + if (TRUE == uart_info_p->rx_enable) + { + reg_write_8(IER_IRxE|IER_ILE , uart_base + LS1B_UART_IER_OFFSET); + } + + return ; +} + + +/* + * 判断FIFO是否为空 + * @uartx 串口号 + * @ret TRUE or FALSE + */ +BOOL uart_is_transmit_empty(ls1b_uart_t uartx) +{ + void *uart_base = uart_get_base(uartx); + unsigned char status = reg_read_8(uart_base + LS1B_UART_LSR_OFFSET); + + if (status & (LS1B_UART_LSR_TE | LS1B_UART_LSR_TFE)) + { + return TRUE; + } + else + { + return FALSE; + } +} + + +/* + * 发送一个字节 + * @uartx 串口号 + * @ch 待发送的字符串 + */ +void uart_putc(ls1b_uart_t uartx, unsigned char ch) +{ + void *uart_base = uart_get_base(uartx); + + // 等待 + while (FALSE == uart_is_transmit_empty(uartx)) + ; + + // 发送 + reg_write_8(ch, uart_base + LS1B_UART_DAT_OFFSET); + + return ; +} + + +/* + * 打印一个字符串到指定串口 + * @uartx 串口号 + * @str 待打印的字符串 + */ +void uart_print(ls1b_uart_t uartx, const char *str) +{ + while ('\0' != *str) // 判断是否为字符串结束符 + { + uart_putc(uartx, *str); // 发送一个字符 + str++; + } + + return ; +} + + +/* + * 初始化串口2 + */ +void uart2_init(void) +{ + unsigned int tx_gpio = 37; + unsigned int rx_gpio = 36; + + // 设置复用 + pin_set_remap(tx_gpio, PIN_REMAP_SECOND); + pin_set_remap(rx_gpio, PIN_REMAP_SECOND); + + // 初始化相关寄存器 + debug_uart_info.UARTx = LS1B_UART2; + debug_uart_info.baudrate = 115200; + debug_uart_info.rx_enable = FALSE; // 调试串口只需要打印(发送)功能,不需要接收功能 + uart_init(&debug_uart_info); + + return ; +} + + +/* + * 在串口2上打印字符串 + * @str 待打印的字符串 + */ +void uart2_print(const char *str) +{ + uart_print(LS1B_UART2, str); + return ; +} + + +/* + * 在调试串口打印字符串 + * @str 待打印的字符串 + */ +void uart_debug_print(const char *str) +{ + uart_print(debug_uart_info.UARTx, str); + return ; +} + + +/* + * 在调试串口打印一个字符 + * @ch 待打印的字符 + */ +void uart_debug_putc(unsigned char ch) +{ + uart_putc(debug_uart_info.UARTx, ch); + return ; +} + + diff --git a/bsp/ls1bdev/libraries/ls1b_uart.h b/bsp/ls1bdev/libraries/ls1b_uart.h new file mode 100644 index 0000000000000000000000000000000000000000..88ee2793ad9cf752b7412cddd1479c7e1c6181fb --- /dev/null +++ b/bsp/ls1bdev/libraries/ls1b_uart.h @@ -0,0 +1,181 @@ + /* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ +// 串口相关头文件 + + +#ifndef __LOONGSON_UART_H +#define __LOONGSON_UART_H + + +#include "ls1b_public.h" + + +// 串口各寄存器相对基地址的偏移 +#define LS1B_UART_DAT_OFFSET (0) +#define LS1B_UART_IER_OFFSET (1) +#define LS1B_UART_IIR_OFFSET (2) +#define LS1B_UART_FCR_OFFSET (2) +#define LS1B_UART_LCR_OFFSET (3) +#define LS1B_UART_MCR_OFFSET (4) +#define LS1B_UART_LSR_OFFSET (5) +#define LS1B_UART_MSR_OFFSET (6) + +#define LS1B_UART_LSB_OFFSET (0) // 分频锁存器1 +#define LS1B_UART_MSB_OFFSET (1) // 分频锁存器2 + +/* interrupt enable register */ +#define IER_IRxE 0x1 /* 接收有效数据中断使能 */ +#define IER_ITxE 0x2 /* 传输保存寄存器为空中断使能 */ +#define IER_ILE 0x4 /* 接收器线路状态中断使能 */ +#define IER_IME 0x8 /* Modem状态中断使能 */ + +/* interrupt identification register */ +#define IIR_IMASK 0xf /* mask */ +#define IIR_RXTOUT 0xc /* receive timeout */ +#define IIR_RLS 0x6 /* receive line status */ +#define IIR_RXRDY 0x4 /* receive ready */ +#define IIR_TXRDY 0x2 /* transmit ready */ +#define IIR_NOPEND 0x1 /* nothing */ +#define IIR_MLSC 0x0 /* modem status */ +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ + +/* fifo control register */ +#define FIFO_ENABLE 0x01 /* enable fifo */ +#define FIFO_RCV_RST 0x02 /* reset receive fifo */ +#define FIFO_XMT_RST 0x04 /* reset transmit fifo */ +#define FIFO_DMA_MODE 0x08 /* enable dma mode */ +#define FIFO_TRIGGER_1 0x00 /* trigger at 1 char */ +#define FIFO_TRIGGER_4 0x40 /* trigger at 4 chars */ +#define FIFO_TRIGGER_8 0x80 /* trigger at 8 chars */ +#define FIFO_TRIGGER_14 0xc0 /* trigger at 14 chars */ + +// 线路控制寄存器 +/* character format control register */ +#define CFCR_DLAB 0x80 /* divisor latch */ +#define CFCR_SBREAK 0x40 /* send break */ +#define CFCR_PZERO 0x30 /* zero parity */ +#define CFCR_PONE 0x20 /* one parity */ +#define CFCR_PEVEN 0x10 /* even parity */ +#define CFCR_PODD 0x00 /* odd parity */ +#define CFCR_PENAB 0x08 /* parity enable */ +#define CFCR_STOPB 0x04 /* 2 stop bits */ +#define CFCR_8BITS 0x03 /* 8 data bits */ +#define CFCR_7BITS 0x02 /* 7 data bits */ +#define CFCR_6BITS 0x01 /* 6 data bits */ +#define CFCR_5BITS 0x00 /* 5 data bits */ + +/* modem control register */ +#define MCR_LOOPBACK 0x10 /* loopback */ +#define MCR_IENABLE 0x08 /* output 2 = int enable */ +#define MCR_DRS 0x04 /* output 1 = xxx */ +#define MCR_RTS 0x02 /* enable RTS */ +#define MCR_DTR 0x01 /* enable DTR */ + +/* line status register */ +#define LSR_RCV_FIFO 0x80 /* error in receive fifo */ +#define LSR_TSRE 0x40 /* transmitter empty */ +#define LSR_TXRDY 0x20 /* transmitter ready */ +#define LSR_BI 0x10 /* break detected */ +#define LSR_FE 0x08 /* framing error */ +#define LSR_PE 0x04 /* parity error */ +#define LSR_OE 0x02 /* overrun error */ +#define LSR_RXRDY 0x01 /* receiver ready */ +#define LSR_RCV_MASK 0x1f + + +// 串口模块编号 +typedef enum +{ + LS1B_UART00 = 0, // 全功能串口UART0可以分为两个四线串口UART00和UART01 + LS1B_UART01, + LS1B_UART1, + LS1B_UART2, + LS1B_UART3, + LS1B_UART4, + LS1B_UART5, + LS1B_UART6, + LS1B_UART7, + LS1B_UART8, + LS1B_UART9, + LS1B_UART10, + LS1B_UART11 +}ls1b_uart_t; + + +// 串口信息 +typedef struct +{ + ls1b_uart_t UARTx; // 串口模块编号 + unsigned int baudrate; // 波特率 + BOOL rx_enable; // 是否需要使用串口接收数据(使能接收中断),发送默认使能 +}ls1b_uart_info_t; + + + +/* + * 获取指定串口模块的基地址 + * @UARTx 串口编号 + * @ret 基地址 + */ +void *uart_get_base(ls1b_uart_t UARTx); + + +/* + * 初始化指定的串口模块 + * @uart_info_p 串口模块信息 + */ +void uart_init(ls1b_uart_info_t *uart_info_p); + + +/* + * 初始化串口2 + */ +void uart2_init(void); + + +/* + * 在串口2上打印字符串 + * @str 待打印的字符串 + */ +void uart2_print(const char *str); + + +/* + * 在调试串口打印字符串 + * @str 待打印的字符串 + */ +void uart_debug_print(const char *str); + + +/* + * 在调试串口打印一个字符 + * @ch 待打印的字符 + */ +void uart_debug_putc(unsigned char ch); + + +/* + * 发送一个字节 + * @uartx 串口号 + * @ch 待发送的字符串 + */ +void uart_putc(ls1b_uart_t uartx, unsigned char ch); + + +/* + * 打印一个字符串到指定串口 + * @uartx 串口号 + * @str 待打印的字符串 + */ +void uart_print(ls1b_uart_t uartx, const char *str); + + +#endif + diff --git a/bsp/ls1bdev/rtconfig.h b/bsp/ls1bdev/rtconfig.h index 882d74b4d7e73063d1ce4060836262602f5d148e..aede85d79513adc8112107d68cd3efdb7c8e3a06 100644 --- a/bsp/ls1bdev/rtconfig.h +++ b/bsp/ls1bdev/rtconfig.h @@ -10,15 +10,12 @@ #define RT_ALIGN_SIZE 4 #define RT_THREAD_PRIORITY_32 #define RT_THREAD_PRIORITY_MAX 32 -#define RT_TICK_PER_SECOND 100 +#define RT_TICK_PER_SECOND 1000 #define RT_USING_OVERFLOW_CHECK #define RT_USING_HOOK #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 -#define IDLE_THREAD_STACK_SIZE 256 -#define RT_USING_TIMER_SOFT -#define RT_TIMER_THREAD_PRIO 4 -#define RT_TIMER_THREAD_STACK_SIZE 512 +#define IDLE_THREAD_STACK_SIZE 1024 #define RT_DEBUG /* Inter-Thread communication */ @@ -40,8 +37,8 @@ #define RT_USING_DEVICE #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 128 -#define RT_CONSOLE_DEVICE_NAME "uart" -#define RT_VER_NUM 0x40002 +#define RT_CONSOLE_DEVICE_NAME "uart5" +#define RT_VER_NUM 0x40003 /* RT-Thread Components */ @@ -114,9 +111,6 @@ /* Utilities */ -/* RT-Thread MIPS CPU */ - - /* RT-Thread online packages */ /* IoT - internet of things */ @@ -157,7 +151,9 @@ /* samples: kernel and components samples */ #define SOC_LS1B -#define RT_USING_UART0 +#define RT_MEM_SIZE 256 +#define RT_OSC_CLK 25000000 +#define RT_USING_UART5 #define RT_UART_RX_BUFFER_SIZE 64 #endif diff --git a/bsp/ls1bdev/rtconfig.py b/bsp/ls1bdev/rtconfig.py index a2c78a926ab8723fe9825e36c7c95f8f9f203487..0d76e27348dddf30b9e4a2a82da67dbb556193ff 100644 --- a/bsp/ls1bdev/rtconfig.py +++ b/bsp/ls1bdev/rtconfig.py @@ -36,7 +36,7 @@ OBJDUMP = PREFIX + 'objdump' OBJCPY = PREFIX + 'objcopy' READELF = PREFIX + 'readelf' -DEVICE = ' -mips32r2' +DEVICE = ' -mips32 -msoft-float -mfp32' CFLAGS = DEVICE + ' -EL -G0 -mno-abicalls -fno-pic -fno-builtin -fno-exceptions -ffunction-sections -fomit-frame-pointer' AFLAGS = ' -c' + DEVICE + ' -EL -fno-pic -fno-builtin -mno-abicalls -x assembler-with-cpp' LFLAGS = DEVICE + ' -nostartfiles -EL -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,Reset_Handler -T ls1b_ram.lds' diff --git a/bsp/maxim/MAX32660_EVSYS/.config b/bsp/maxim/MAX32660_EVSYS/.config index 76a58dd3d9bbb3993ea8e61cd5f942463ea54841..82e0a0d279444472a47491997ef21e6226cf80cc 100644 --- a/bsp/maxim/MAX32660_EVSYS/.config +++ b/bsp/maxim/MAX32660_EVSYS/.config @@ -122,7 +122,7 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set # CONFIG_RT_USING_PHY is not set -# CONFIG_RT_USING_PIN is not set +CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set @@ -478,9 +478,10 @@ CONFIG_SOC_MAXIM=y # # On-chip Peripheral Drivers # -# CONFIG_BSP_USING_GPIO is not set +CONFIG_BSP_USING_GPIO=y CONFIG_BSP_USING_UART=y # CONFIG_BSP_USING_UART0 is not set CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set +# CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_ON_CHIP_FLASH is not set diff --git a/bsp/maxim/MAX32660_EVSYS/README.md b/bsp/maxim/MAX32660_EVSYS/README.md index 7123c5d4001751daf4ad3d7c338b482910bd65ba..90fea400422376e08754c4282bc5ebd39414af3f 100644 --- a/bsp/maxim/MAX32660_EVSYS/README.md +++ b/bsp/maxim/MAX32660_EVSYS/README.md @@ -72,10 +72,10 @@ MAX32660-EVSYS开发板常用 **板载资源** 如下: | **片上外设** | **支持情况** | **备注** | | :----------- | :----------: | :-------------------: | -| GPIO | | | +| GPIO | 支持 | | | UART | 支持 | UART0, UART1(console) | | PWM | | | -| SPI | | | +| SPI | 支持 | SPI0, SPI1 | | RTC | | | | I2S | | | | I2C | | | diff --git a/bsp/maxim/MAX32660_EVSYS/applications/application.c b/bsp/maxim/MAX32660_EVSYS/applications/application.c index 2ae592d99b7e7e411aa4ccf5450e21c398d3b786..d25f9a065eb6e7b71a94528b26a12f8f3fd9525c 100644 --- a/bsp/maxim/MAX32660_EVSYS/applications/application.c +++ b/bsp/maxim/MAX32660_EVSYS/applications/application.c @@ -11,22 +11,20 @@ #include #include -#include "gpio.h" -const gpio_cfg_t led_pin[] = -{ - {PORT_0, PIN_13, GPIO_FUNC_OUT, GPIO_PAD_NONE}, -}; +#define GPIO_LED_PIN 13 int main(void) { int count = 1; - GPIO_Config(&led_pin[0]); - GPIO_OutSet(&led_pin[0]); + rt_pin_mode(GPIO_LED_PIN, PIN_MODE_OUTPUT); while (count++) { + rt_pin_write(GPIO_LED_PIN, PIN_HIGH); + rt_thread_mdelay(500); + + rt_pin_write(GPIO_LED_PIN, PIN_LOW); rt_thread_mdelay(500); - GPIO_OutToggle(&led_pin[0]); } return RT_EOK; } diff --git a/bsp/maxim/MAX32660_EVSYS/board/Kconfig b/bsp/maxim/MAX32660_EVSYS/board/Kconfig index 924b74f04ccd7e57c5c3dc154a8be6fe845f301a..fa4ec1d0cd1e5fbe67c5d7a31c3a34b81be7566e 100644 --- a/bsp/maxim/MAX32660_EVSYS/board/Kconfig +++ b/bsp/maxim/MAX32660_EVSYS/board/Kconfig @@ -43,6 +43,25 @@ menu "On-chip Peripheral Drivers" depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA default n endif + config BSP_USING_SPI + bool "Enable SPI" + select RT_USING_SPI + default n + + if BSP_USING_SPI + config BSP_USING_SPI0 + bool "Enable SPI0 bus [MISO P0.4;MOSI P0.5;SCL P0.6;SS P0.7]" + default y + + config BSP_USING_SPI1 + bool "Enable SPI1 bus [MISO P0.0;MOSI P0.1;SCL P0.2;SS P0.3]" + default n + if BSP_USING_SPI1 + config BSP_USING_SPI1A + bool "Use SPI1A. [MISO P0.10;MOSI P0.11;SCL P0.12;SS P0.13]" + default n + endif + endif config BSP_USING_ON_CHIP_FLASH select PKG_USING_FAL bool "Enable on-chip FLASH" diff --git a/bsp/maxim/MAX32660_EVSYS/board/board.h b/bsp/maxim/MAX32660_EVSYS/board/board.h index 155749b002f65c618a60c56460533a5f9b304f32..490e91a95f20143f631c781d7939a9672184d5f1 100644 --- a/bsp/maxim/MAX32660_EVSYS/board/board.h +++ b/bsp/maxim/MAX32660_EVSYS/board/board.h @@ -14,6 +14,10 @@ #include #include +#include "mxc_config.h" +#include "mxc_assert.h" + + #define MCU_FLASH_START_ADRESS ((uint32_t)0x0) #define MCU_FLASH_SIZE_KB (256) #define MCU_FLASH_END_ADDRESS ((uint32_t)(MCU_FLASH_START_ADRESS + MCU_FLASH_SIZE*1024)) diff --git a/bsp/maxim/MAX32660_EVSYS/project.uvoptx b/bsp/maxim/MAX32660_EVSYS/project.uvoptx index 34eb015ca11c1ce9f0cdf551fa465b36c8272e11..ff7f9de14e4b0a168c421e2a53e60fa024bc8044 100644 --- a/bsp/maxim/MAX32660_EVSYS/project.uvoptx +++ b/bsp/maxim/MAX32660_EVSYS/project.uvoptx @@ -117,6 +117,26 @@ BIN\CMSIS_AGDI.dll + + 0 + ARMRTXEVENTFLAGS + -L70 -Z18 -C0 -M0 -T1 + + + 0 + DLGTARM + (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) + + + 0 + ARMDBGFLAGS + + + + 0 + DLGUARM + + 0 CMSIS_AGDI @@ -135,12 +155,12 @@ 0 0 - 0 + 1 0 0 0 0 - 0 + 1 0 0 0 @@ -203,7 +223,7 @@ CPU - 0 + 1 0 0 0 @@ -271,7 +291,7 @@ DeviceDrivers - 0 + 1 0 0 0 @@ -282,6 +302,18 @@ 0 0 0 + ..\..\..\components\drivers\misc\pin.c + pin.c + 0 + 0 + + + 3 + 8 + 1 + 0 + 0 + 0 ..\..\..\components\drivers\serial\serial.c serial.c 0 @@ -289,7 +321,7 @@ 3 - 8 + 9 1 0 0 @@ -301,7 +333,7 @@ 3 - 9 + 10 1 0 0 @@ -313,7 +345,7 @@ 3 - 10 + 11 1 0 0 @@ -325,7 +357,7 @@ 3 - 11 + 12 1 0 0 @@ -337,7 +369,7 @@ 3 - 12 + 13 1 0 0 @@ -349,7 +381,7 @@ 3 - 13 + 14 1 0 0 @@ -361,7 +393,7 @@ 3 - 14 + 15 1 0 0 @@ -381,7 +413,7 @@ 0 4 - 15 + 16 1 0 0 @@ -393,7 +425,7 @@ 4 - 16 + 17 2 0 0 @@ -405,7 +437,19 @@ 4 - 17 + 18 + 1 + 0 + 0 + 0 + ..\libraries\HAL_Drivers\drv_gpio.c + drv_gpio.c + 0 + 0 + + + 4 + 19 1 0 0 @@ -419,13 +463,13 @@ finsh - 0 + 1 0 0 0 5 - 18 + 20 1 0 0 @@ -437,7 +481,7 @@ 5 - 19 + 21 1 0 0 @@ -449,7 +493,7 @@ 5 - 20 + 22 1 0 0 @@ -469,7 +513,7 @@ 0 6 - 21 + 23 1 0 0 @@ -481,7 +525,7 @@ 6 - 22 + 24 1 0 0 @@ -493,7 +537,7 @@ 6 - 23 + 25 1 0 0 @@ -505,7 +549,7 @@ 6 - 24 + 26 1 0 0 @@ -517,7 +561,7 @@ 6 - 25 + 27 1 0 0 @@ -529,7 +573,7 @@ 6 - 26 + 28 1 0 0 @@ -541,7 +585,7 @@ 6 - 27 + 29 1 0 0 @@ -553,7 +597,7 @@ 6 - 28 + 30 1 0 0 @@ -565,7 +609,7 @@ 6 - 29 + 31 1 0 0 @@ -577,7 +621,7 @@ 6 - 30 + 32 1 0 0 @@ -589,7 +633,7 @@ 6 - 31 + 33 1 0 0 @@ -601,7 +645,7 @@ 6 - 32 + 34 1 0 0 @@ -613,7 +657,7 @@ 6 - 33 + 35 1 0 0 @@ -633,7 +677,7 @@ 0 7 - 34 + 36 1 0 0 @@ -645,7 +689,7 @@ 7 - 35 + 37 1 0 0 @@ -657,7 +701,7 @@ 7 - 36 + 38 1 0 0 @@ -669,7 +713,7 @@ 7 - 37 + 39 1 0 0 @@ -681,7 +725,7 @@ 7 - 38 + 40 1 0 0 @@ -693,7 +737,7 @@ 7 - 39 + 41 1 0 0 @@ -705,7 +749,7 @@ 7 - 40 + 42 1 0 0 @@ -717,7 +761,7 @@ 7 - 41 + 43 1 0 0 @@ -729,7 +773,7 @@ 7 - 42 + 44 1 0 0 @@ -741,7 +785,7 @@ 7 - 43 + 45 1 0 0 @@ -753,7 +797,7 @@ 7 - 44 + 46 1 0 0 @@ -765,7 +809,7 @@ 7 - 45 + 47 1 0 0 @@ -777,7 +821,7 @@ 7 - 46 + 48 1 0 0 @@ -789,7 +833,7 @@ 7 - 47 + 49 1 0 0 diff --git a/bsp/maxim/MAX32660_EVSYS/project.uvprojx b/bsp/maxim/MAX32660_EVSYS/project.uvprojx index e1b9454ea9e2f3c155c1614be7bcbd240544fc43..7b23a65cbc5f4053e3a2d4a9599465908cc833d6 100644 --- a/bsp/maxim/MAX32660_EVSYS/project.uvprojx +++ b/bsp/maxim/MAX32660_EVSYS/project.uvprojx @@ -338,7 +338,7 @@ TARGET=32660, TARGET_REV=0x4131, __RTTHREAD__ - applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\libraries\MAX32660PeriphDriver\CMSIS\Device\Maxim\MAX32660\Include;..\libraries\MAX32660PeriphDriver\CMSIS\Core\Include;..\libraries\MAX32660PeriphDriver\Include + applications;.;..\..\..\libcpu\arm\common;..\..\..\libcpu\arm\cortex-m4;..\..\..\components\drivers\include;..\..\..\components\drivers\include;..\..\..\components\drivers\include;board;..\libraries\HAL_Drivers;..\..\..\components\finsh;.;..\..\..\include;..\libraries\MAX32660PeriphDriver\CMSIS\Device\Maxim\MAX32660\Include;..\libraries\MAX32660PeriphDriver\CMSIS\Core\Include;..\libraries\MAX32660PeriphDriver\Include @@ -422,6 +422,11 @@ DeviceDrivers + + pin.c + 1 + ..\..\..\components\drivers\misc\pin.c + serial.c 1 @@ -477,6 +482,11 @@ 2 ..\libraries\MAX32660PeriphDriver\CMSIS\Device\Maxim\MAX32660\Source\ARM\startup_max32660.s + + drv_gpio.c + 1 + ..\libraries\HAL_Drivers\drv_gpio.c + drv_uart.c 1 diff --git a/bsp/maxim/MAX32660_EVSYS/rtconfig.h b/bsp/maxim/MAX32660_EVSYS/rtconfig.h index bd1b90652db9ec586d6245083aeaf22b79e91940..a15112c1b20d6e55722f3d27f0c2441503db31ce 100644 --- a/bsp/maxim/MAX32660_EVSYS/rtconfig.h +++ b/bsp/maxim/MAX32660_EVSYS/rtconfig.h @@ -79,6 +79,7 @@ #define RT_USING_SERIAL #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_PIN /* Using USB */ @@ -159,6 +160,7 @@ /* On-chip Peripheral Drivers */ +#define BSP_USING_GPIO #define BSP_USING_UART #define BSP_USING_UART1 diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_gpio.c b/bsp/maxim/libraries/HAL_Drivers/drv_gpio.c new file mode 100644 index 0000000000000000000000000000000000000000..e2001371d9f2116b0b00b55ad395ba6f30f390b4 --- /dev/null +++ b/bsp/maxim/libraries/HAL_Drivers/drv_gpio.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-11 supperthomas first version + * + */ + + +#include "drv_gpio.h" +#include +#include "gpio.h" + +#ifdef RT_USING_PIN + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "drv.gpio" + +#define PIN_PORT_OFFSET 4 + +#define PIN_NUM(port, no) ((((((port) & 0xFu) << PIN_PORT_OFFSET) | ((no) & 0xFu))) +#define PIN_PORT(pin) ((uint8_t)(((pin) >> PIN_PORT_OFFSET) & 0xFu)) +#define PIN_NO(pin) ((uint8_t)((pin) & 0xFu)) + + +#define PIN_MCU_PORT(pin) PIN_PORT(pin) +#define PIN_MCU_PIN(pin) ((uint32_t)(1u << PIN_NO(pin))) + +static void mcu_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value) +{ + gpio_cfg_t tmp_gpio_cfg; + tmp_gpio_cfg.port = PIN_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + if (value) + { + GPIO_OutSet(&tmp_gpio_cfg); + } + else + { + GPIO_OutClr(&tmp_gpio_cfg); + } + +} + +static int mcu_pin_read(rt_device_t dev, rt_base_t pin) +{ + int value; + gpio_cfg_t tmp_gpio_cfg; + tmp_gpio_cfg.port = PIN_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + + if (GPIO_InGet(&tmp_gpio_cfg)) + { + value = 1; + } + else + { + value = 0; + } + + return value; +} + +static void mcu_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode) +{ + gpio_cfg_t tmp_gpio_cfg; + int ret = 0; + tmp_gpio_cfg.port = PIN_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + + switch (mode) + { + case PIN_MODE_OUTPUT: + tmp_gpio_cfg.func = GPIO_FUNC_OUT; + tmp_gpio_cfg.pad = GPIO_PAD_NONE; + break; + case PIN_MODE_INPUT: + tmp_gpio_cfg.func = GPIO_FUNC_IN; + tmp_gpio_cfg.pad = GPIO_PAD_NONE; + break; + case PIN_MODE_INPUT_PULLUP: + tmp_gpio_cfg.func = GPIO_FUNC_IN; + tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; + break; + case PIN_MODE_INPUT_PULLDOWN: + tmp_gpio_cfg.func = GPIO_FUNC_IN; + tmp_gpio_cfg.pad = GPIO_PAD_PULL_DOWN; + break; + case PIN_MODE_OUTPUT_OD: + //not support + LOG_E("NOT SUPPORT"); + break; + } + ret = GPIO_Config(&tmp_gpio_cfg); + if (E_NO_ERROR != ret) + { + LOG_E("GPIO_Config error :%d", ret); + } +} + + +static rt_err_t mcu_pin_attach_irq(struct rt_device *device, rt_int32_t pin, + rt_uint32_t irq_mode, void (*hdr)(void *args), void *args) +{ + gpio_cfg_t tmp_gpio_cfg; + tmp_gpio_cfg.port = PIN_MCU_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + + + tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; + tmp_gpio_cfg.func = GPIO_FUNC_IN; + GPIO_Config(&tmp_gpio_cfg); + GPIO_RegisterCallback(&tmp_gpio_cfg, hdr, args); + + gpio_int_mode_t mcu_mode; + gpio_int_pol_t mcu_pol; + + switch (irq_mode) + { + case PIN_IRQ_MODE_RISING: + mcu_mode = GPIO_INT_EDGE; + mcu_pol = GPIO_INT_RISING; + break; + case PIN_IRQ_MODE_FALLING: + mcu_mode = GPIO_INT_EDGE; + mcu_pol = GPIO_INT_FALLING; + break; + case PIN_IRQ_MODE_RISING_FALLING: + mcu_mode = GPIO_INT_EDGE; + mcu_pol = GPIO_INT_BOTH; + break; + case PIN_IRQ_MODE_HIGH_LEVEL: + mcu_mode = GPIO_INT_LEVEL; + mcu_pol = GPIO_INT_HIGH; + break; + case PIN_IRQ_MODE_LOW_LEVEL: + mcu_mode = GPIO_INT_LEVEL; + mcu_pol = GPIO_INT_LOW; + break; + } + + GPIO_IntConfig(&tmp_gpio_cfg, mcu_mode, mcu_pol); + + + return RT_EOK; +} + +static rt_err_t mcu_pin_dettach_irq(struct rt_device *device, rt_int32_t pin) +{ + gpio_cfg_t tmp_gpio_cfg; + tmp_gpio_cfg.port = PIN_MCU_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + tmp_gpio_cfg.pad = GPIO_PAD_PULL_UP; + tmp_gpio_cfg.func = GPIO_FUNC_IN; + GPIO_Config(&tmp_gpio_cfg); + GPIO_IntDisable(&tmp_gpio_cfg); + GPIO_RegisterCallback(&tmp_gpio_cfg, NULL, NULL); + return RT_EOK; +} + +static rt_err_t mcu_pin_irq_enable(struct rt_device *device, rt_base_t pin, + rt_uint32_t enabled) +{ + gpio_cfg_t tmp_gpio_cfg; + tmp_gpio_cfg.port = PIN_MCU_PORT(pin); + tmp_gpio_cfg.mask = PIN_MCU_PIN(pin); + if (enabled) + { + GPIO_IntEnable(&tmp_gpio_cfg); + NVIC_EnableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(PIN_MCU_PORT(pin))); + } + else + { + GPIO_IntDisable(&tmp_gpio_cfg); + NVIC_DisableIRQ((IRQn_Type)MXC_GPIO_GET_IRQ(PIN_MCU_PORT(pin))); + } + return RT_EOK; +} + +const static struct rt_pin_ops _mcu_pin_ops = +{ + mcu_pin_mode, + mcu_pin_write, + mcu_pin_read, + mcu_pin_attach_irq, + mcu_pin_dettach_irq, + mcu_pin_irq_enable, + NULL, +}; + +int rt_hw_pin_init(void) +{ + GPIO_Init(); + return rt_device_pin_register("pin", &_mcu_pin_ops, RT_NULL); +} +INIT_BOARD_EXPORT(rt_hw_pin_init); + + +void GPIO0_IRQHandler(void) +{ + GPIO_Handler(PORT_0); +} + +#endif /* RT_USING_PIN */ diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_gpio.h b/bsp/maxim/libraries/HAL_Drivers/drv_gpio.h new file mode 100644 index 0000000000000000000000000000000000000000..dc81da0d4a2f0c539c441bff70d71bcecd5f1a46 --- /dev/null +++ b/bsp/maxim/libraries/HAL_Drivers/drv_gpio.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-11 supperthomas first version + * + */ + +#ifndef __DRV_GPIO_H__ +#define __DRV_GPIO_H__ + +#include +#include + +int rt_hw_pin_init(void); + +#endif /* __DRV_GPIO_H__ */ + diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_spi.c b/bsp/maxim/libraries/HAL_Drivers/drv_spi.c new file mode 100644 index 0000000000000000000000000000000000000000..03671652ef4683bfeefeec750b025d157aed1460 --- /dev/null +++ b/bsp/maxim/libraries/HAL_Drivers/drv_spi.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-14 supperthomas first version + */ + +#include +#include +#include "board.h" +#include "drv_spi.h" + +#define DBG_LEVEL DBG_LOG +#include +#define LOG_TAG "drv.spi" + +#ifdef BSP_USING_SPI + +#if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) +static struct mcu_drv_spi_config spi_config[] = +{ +#ifdef BSP_USING_SPI0 + MCU_SPI0_CONFIG, +#endif +#ifdef BSP_USING_SPI1 + MCU_SPI1_CONFIG, +#endif + +}; + +static struct mcu_drv_spi spi_bus_obj[sizeof(spi_config) / sizeof(spi_config[0])]; + + +/** + * @brief This function config spi bus + * @param device + * @param configuration + * @retval RT_EOK / RT_ERROR + */ +static rt_err_t spi_configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + struct mcu_drv_spi *tmp_spi; + tmp_spi = rt_container_of(device->bus, struct mcu_drv_spi, spi_bus); + int mode; + + ///init + + switch (configuration->mode & RT_SPI_MODE_3) + { + case RT_SPI_MODE_0/* RT_SPI_CPOL:0 , RT_SPI_CPHA:0 */: + case RT_SPI_MODE_1/* RT_SPI_CPOL:0 , RT_SPI_CPHA:1 */: + case RT_SPI_MODE_2/* RT_SPI_CPOL:1 , RT_SPI_CPHA:0 */: + case RT_SPI_MODE_3/* RT_SPI_CPOL:1 , RT_SPI_CPHA:1 */: + mode = configuration->mode & RT_SPI_MODE_3; + break; + default: + LOG_E("spi_configure mode error %x\n", configuration->mode); + return RT_ERROR; + } + + tmp_spi->spixfer_req.width = SPI17Y_WIDTH_1; + tmp_spi->spixfer_req.bits = configuration->data_width; + tmp_spi->spixfer_req.ssel = 0; + tmp_spi->spixfer_req.deass = 1; + tmp_spi->spixfer_req.tx_num = 0; + tmp_spi->spixfer_req.rx_num = 0; + tmp_spi->spixfer_req.callback = NULL; + LOG_D("spi init mode:%d, rate:%d", mode, configuration->max_hz); + if (SPI_Init(tmp_spi->spi_instance, mode, configuration->max_hz) != 0) + { + LOG_E("Error configuring SPI\n"); + while (1) {} + } + //init + return RT_EOK; +} + +static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + RT_ASSERT(device != RT_NULL); + RT_ASSERT(device->bus != RT_NULL); + RT_ASSERT(device->bus->parent.user_data != RT_NULL); + + int ret = 0; + struct mcu_drv_spi *tmp_spi; + tmp_spi = rt_container_of(device->bus, struct mcu_drv_spi, spi_bus); + + + tmp_spi->spixfer_req.tx_data = message->send_buf; + tmp_spi->spixfer_req.rx_data = message->recv_buf; + tmp_spi->spixfer_req.len = message->length; + ret = SPI_MasterTrans(tmp_spi->spi_instance, &tmp_spi->spixfer_req); + if (ret == E_NO_ERROR) + { + return message->length; + } + else + { + LOG_E("spixfer faild, ret %d", ret); + return 0; + } +} + +/* spi bus callback function */ +static const struct rt_spi_ops nrfx_spi_ops = +{ + .configure = spi_configure, + .xfer = spixfer, +}; + +/*spi bus init*/ +static int rt_hw_spi_bus_init(void) +{ + rt_err_t result = RT_ERROR; + for (int i = 0; i < sizeof(spi_config) / sizeof(spi_config[0]); i++) + { + spi_bus_obj[i].spi_instance = spi_config[i].spi_instance; + spi_bus_obj[i].spi_bus.parent.user_data = &spi_config[i]; //SPI INSTANCE + result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, spi_config[i].bus_name, &nrfx_spi_ops); + RT_ASSERT(result == RT_EOK); + } + return result; +} + +int rt_hw_spi_init(void) +{ + return rt_hw_spi_bus_init(); +} +INIT_BOARD_EXPORT(rt_hw_spi_init); + +/** + * Attach the spi device to SPI bus, this function must be used after initialization. + */ +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t cs_pin) +{ + RT_ASSERT(bus_name != RT_NULL); + RT_ASSERT(device_name != RT_NULL); + RT_ASSERT(cs_pin != RT_NULL); + + rt_err_t result; + struct rt_spi_device *spi_device; + /* attach the device to spi bus*/ + spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device)); + RT_ASSERT(spi_device != RT_NULL); + /* initialize the cs pin */ + result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin); + if (result != RT_EOK) + { + LOG_E("%s attach to %s faild, %d", device_name, bus_name, result); + result = RT_ERROR; + } + /* TODO: SET THE GPIO */ + + RT_ASSERT(result == RT_EOK); + return result; +} + +#endif /* BSP_USING_SPI0 || BSP_USING_SPI1 || BSP_USING_SPI2 */ +#endif /*BSP_USING_SPI*/ + + diff --git a/bsp/maxim/libraries/HAL_Drivers/drv_spi.h b/bsp/maxim/libraries/HAL_Drivers/drv_spi.h new file mode 100644 index 0000000000000000000000000000000000000000..c478850fa7f229af7995bac71b187ab86edac517 --- /dev/null +++ b/bsp/maxim/libraries/HAL_Drivers/drv_spi.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-14 supperthomas first version + */ + +#include +#include +#include + +#include "spi.h" + +#ifndef __DRV_SPI_H_ +#define __DRV_SPI_H_ + +/** + * @brief Attach the spi device to SPI bus, this function must be used after initialization. + * @param bus_name spi bus name "spi0"/"spi1"/"spi2" + * @param device_name spi device name "spi0x"/"spi1x"/"spi2x" + * @param ss_pin spi ss pin number + * @retval RT_ERROR / RT_EOK +*/ +rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t ss_pin); + +//SPI bus config +#ifdef BSP_USING_SPI0 +#define MCU_SPI0_CONFIG \ +{ \ + .bus_name = "spi0", \ + .spi_instance = SPI0A, \ +} +#endif +#ifdef BSP_USING_SPI1 +#ifdef BSP_USING_SPI1A //The SPI1A is conflit with UART1 TX RX P0.10 P0.11 +#define MCU_SPI1_CONFIG \ +{ \ + .bus_name = "spi1", \ + .spi_instance = SPI1A \ +} +#else +#define MCU_SPI1_CONFIG \ +{ \ + .bus_name = "spi1", \ + .spi_instance = SPI1B \ +} +#endif +#endif + +struct mcu_drv_spi_config +{ + char *bus_name; + spi_type spi_instance; +}; + +struct mcu_drv_spi +{ + spi_type spi_instance; + spi_req_t spixfer_req; + struct rt_spi_configuration *cfg; + struct rt_spi_bus spi_bus; +}; + +#endif /*__DRV_SPI_H_*/ diff --git a/bsp/maxim/libraries/MAX32660PeriphDriver/SConscript b/bsp/maxim/libraries/MAX32660PeriphDriver/SConscript index fa62f76fb707581bd4289b0b3eefd1bcb6fa7d2f..b0f2840147c94453c753ba90856db2a7313e78cd 100644 --- a/bsp/maxim/libraries/MAX32660PeriphDriver/SConscript +++ b/bsp/maxim/libraries/MAX32660PeriphDriver/SConscript @@ -30,6 +30,9 @@ if GetDepend(['RT_USING_I2C']): if GetDepend(['RT_USING_SPI']): src += ['Source/spi.c'] + src += ['Source/spi17y.c'] + src += ['Source/spimss.c'] + if GetDepend(['RT_USING_RTC']): src += ['Source/rtc.c'] diff --git a/bsp/nrf5x/README.md b/bsp/nrf5x/README.md index db1540a4d8275d4c331438e8723bc1670ac236ce..c29ba5647374b4563a7b0318c5554cb53a23e975 100644 --- a/bsp/nrf5x/README.md +++ b/bsp/nrf5x/README.md @@ -132,4 +132,54 @@ nrf5x 下面提供一种擦写softdevice的方法。在keil中选择softdevice Erase的FLASH算法,这个时候就烧写之前可以擦除之前的softdevice。 -![image-20201017194935643](docs/images/softdevice_erase.png) \ No newline at end of file +![image-20201017194935643](docs/images/softdevice_erase.png) + + + +### 2.如果在使用softdevice的时候,连上手机时候出现一些hardfault + +如下所示: + +``` +psr: 0x8100000f +r00: 0x00000000 +r01: 0x200034e6 +r02: 0x00000000 +r03: 0x200034dc +r04: 0x200034dc +r05: 0x00000000 +r06: 0x200034e6 +r07: 0xdeadbeef +r08: 0xdeadbeef +r09: 0xdeadbeef +r10: 0xdeadbeef +r11: 0xdeadbeef +r12: 0x00000000 + lr: 0x000369af + pc: 0x00036972 +hard fault on handler + +``` + +这个hardfault发生在SOFTDEVICE内部,由于代码不开源,这边尝试了修改如下函数,可以不触发hardfault。 + +``` +rt_hw_interrupt_disable PROC + EXPORT rt_hw_interrupt_disable + ;MRS r0, PRIMASK + ;CPSID I + BX LR + ENDP + +;/* +; * void rt_hw_interrupt_enable(rt_base_t level); +; */ +rt_hw_interrupt_enable PROC + EXPORT rt_hw_interrupt_enable + ;MSR PRIMASK, r0 + BX LR + ENDP +``` + + + diff --git a/bsp/nrf5x/nrf52832/board/board.h b/bsp/nrf5x/nrf52832/board/board.h index 5357cca29153010d4e5daedf5fed189daa4f4d9a..32acd6b56cfe8bbca66213b3f319e3ea00accc06 100644 --- a/bsp/nrf5x/nrf52832/board/board.h +++ b/bsp/nrf5x/nrf52832/board/board.h @@ -21,8 +21,7 @@ extern int __bss_end__; #define HEAP_BEGIN ((void *)&__bss_end__) #endif -#define HEAP_SIZE 16*1024 -#define HEAP_END (HEAP_BEGIN + HEAP_SIZE) +#define HEAP_END (MCU_SRAM_END_ADDRESS) void rt_hw_board_init(void); diff --git a/bsp/nrf5x/nrf52840/board/Kconfig b/bsp/nrf5x/nrf52840/board/Kconfig index c49ae1f44f79486913d6fb227a6f4585d86cac4c..71e7595048919036b08581b352f0d8ba261957c0 100644 --- a/bsp/nrf5x/nrf52840/board/Kconfig +++ b/bsp/nrf5x/nrf52840/board/Kconfig @@ -314,8 +314,8 @@ menu "On-chip Peripheral Drivers" endif config BSP_USING_SPI bool "Enable SPI" - select RT_USING_PIN - default y + select RT_USING_SPI + default n if BSP_USING_SPI config NRFX_SPI_ENABLED diff --git a/bsp/nrf5x/nrf52840/board/board.c b/bsp/nrf5x/nrf52840/board/board.c index 2ba3214bfa8ed84bf1ea8ca3cd7f52cb1c0c8690..5bd27ac8fc6fe890c7c1841bb53db967be5d8374 100644 --- a/bsp/nrf5x/nrf52840/board/board.c +++ b/bsp/nrf5x/nrf52840/board/board.c @@ -53,9 +53,6 @@ void SysTick_Configuration(void) void rt_hw_board_init(void) { rt_hw_interrupt_enable(0); - // sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE); - /* Activate deep sleep mode */ - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; SysTick_Configuration(); diff --git a/bsp/nrf5x/nrf52840/board/board.h b/bsp/nrf5x/nrf52840/board/board.h index 5357cca29153010d4e5daedf5fed189daa4f4d9a..a3ccadfa36fe95b44575f8c278f8154115defd59 100644 --- a/bsp/nrf5x/nrf52840/board/board.h +++ b/bsp/nrf5x/nrf52840/board/board.h @@ -21,8 +21,8 @@ extern int __bss_end__; #define HEAP_BEGIN ((void *)&__bss_end__) #endif -#define HEAP_SIZE 16*1024 -#define HEAP_END (HEAP_BEGIN + HEAP_SIZE) + +#define HEAP_END (MCU_SRAM_END_ADDRESS) void rt_hw_board_init(void); diff --git a/components/libc/compilers/armlibc/syscalls.c b/components/libc/compilers/armlibc/syscalls.c index 1e08ca1716f1ed23edde091e114b19f324f7f90b..37f296fc3a171e3d241fe689fc8c6f8fb1f9732f 100644 --- a/components/libc/compilers/armlibc/syscalls.c +++ b/components/libc/compilers/armlibc/syscalls.c @@ -258,23 +258,9 @@ void _ttywrch(int ch) RT_WEAK void _sys_exit(int return_code) { - rt_thread_t self = rt_thread_self(); - -#ifdef RT_USING_MODULE - if (dlmodule_self()) - { - dlmodule_exit(return_code); - } -#endif - - if (self != RT_NULL) - { - rt_kprintf("thread:%-8.*s exit:%d!\n", RT_NAME_MAX, self->name, return_code); - rt_thread_suspend(self); - rt_schedule(); - } - - while(1); /* noreturn */ + extern void __rt_libc_exit(int status); + __rt_libc_exit(return_code); + while(1); } /** @@ -320,8 +306,8 @@ int remove(const char *filename) #else int system(const char *string) { - RT_ASSERT(0); - for (;;); + extern int __rt_libc_system(const char *string); + return __rt_libc_system(string); } #endif diff --git a/components/libc/compilers/common/SConscript b/components/libc/compilers/common/SConscript index 8877f07f24000950b1b841957325967183b18e5a..ecdee2637e7ad891a92eeca981b39b6b7f2dcb1c 100644 --- a/components/libc/compilers/common/SConscript +++ b/components/libc/compilers/common/SConscript @@ -8,13 +8,13 @@ group = [] CPPPATH = [cwd] if GetDepend('RT_USING_LIBC'): - src += Glob('*.c') + src += Glob('*.c') else: - if GetDepend('RT_LIBC_USING_TIME') and not GetDepend('RT_USING_MINILIBC'): - src += ['time.c'] + if GetDepend('RT_LIBC_USING_TIME') and not GetDepend('RT_USING_MINILIBC'): + src += ['time.c'] if GetDepend('RT_USING_POSIX') == False: - SrcRemove(src, ['unistd.c']) + SrcRemove(src, ['unistd.c']) if rtconfig.CROSS_TOOL == 'keil': CPPDEFINES = ['__CLK_TCK=RT_TICK_PER_SECOND'] diff --git a/components/libc/compilers/common/stdlib.c b/components/libc/compilers/common/stdlib.c new file mode 100644 index 0000000000000000000000000000000000000000..b485bbd83608b59cd7bf08d6ad41c4de12ba9bc6 --- /dev/null +++ b/components/libc/compilers/common/stdlib.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-02-15 Meco Man first version + */ + +#include +#include + +void __rt_libc_exit(int status) +{ + rt_thread_t self = rt_thread_self(); + +#ifdef RT_USING_MODULE + if (dlmodule_self()) + { + dlmodule_exit(status); + } +#endif + + if (self != RT_NULL) + { + if(status == EXIT_FAILURE) /* abort() */ + { + rt_kprintf("thread:%s abort!\n", self->name); + } + else /* exit() */ + { + rt_kprintf("thread:%s exit:%d!\n", self->name, status); + } + rt_thread_suspend(self); + rt_schedule(); + } +} + +void __rt_libc_abort(void) +{ + __rt_libc_exit(EXIT_FAILURE); +} + +int __rt_libc_system(const char *string) +{ + /* TODO */ + return 0; +} diff --git a/components/libc/compilers/dlib/syscalls.c b/components/libc/compilers/dlib/syscalls.c index 0d5f02f9523158e7571ebfe58c59d45d7618d8fc..10155948ba7a9619728a79636f18ae5973a81e9a 100644 --- a/components/libc/compilers/dlib/syscalls.c +++ b/components/libc/compilers/dlib/syscalls.c @@ -11,42 +11,14 @@ void exit (int status) { - rt_thread_t self = rt_thread_self(); - -#ifdef RT_USING_MODULE - if (dlmodule_self()) - { - dlmodule_exit(status); - } -#endif - - if (self != RT_NULL) - { - rt_kprintf("thread:%-8.*s exit:%d!\n", RT_NAME_MAX, self->name, status); - rt_thread_suspend(self); - rt_schedule(); - } - - while(1); /* noreturn */ + extern void __rt_libc_exit(int status); + __rt_libc_exit(status); + while(1); } void abort(void) { - rt_thread_t self = rt_thread_self(); - -#ifdef RT_USING_MODULE - if (dlmodule_self()) - { - dlmodule_exit(-1); - } -#endif - - if (self != RT_NULL) - { - rt_kprintf("thread:%-8.*s abort!\n", RT_NAME_MAX, self->name); - rt_thread_suspend(self); - rt_schedule(); - } - - while(1); /* noreturn */ + extern void __rt_libc_abort(void); + __rt_libc_abort(); + while(1); } diff --git a/components/libc/compilers/newlib/machine/time.h b/components/libc/compilers/newlib/machine/time.h new file mode 100644 index 0000000000000000000000000000000000000000..d46533eb394b53723a5fe81f87c4e3c414f0a523 --- /dev/null +++ b/components/libc/compilers/newlib/machine/time.h @@ -0,0 +1,12 @@ +#ifndef _MACHTIME_H_ +#define _MACHTIME_H_ + +#include +#define _CLOCKS_PER_SEC_ RT_TICK_PER_SECOND + +#ifdef __SPU__ +#include +int nanosleep (const struct timespec *, struct timespec *); +#endif + +#endif /* _MACHTIME_H_ */ diff --git a/components/libc/compilers/newlib/syscalls.c b/components/libc/compilers/newlib/syscalls.c index cf98e0c3ece661ee8459c26eba847b8cfe284eda..76300f76b2aca2c40eb070dc2b8b778eeb60e3c5 100644 --- a/components/libc/compilers/newlib/syscalls.c +++ b/components/libc/compilers/newlib/syscalls.c @@ -286,30 +286,16 @@ _free_r (struct _reent *ptr, void *addr) void exit (int status) { - rt_thread_t self = rt_thread_self(); - -#ifdef RT_USING_MODULE - if (dlmodule_self()) - { - dlmodule_exit(status); - } -#endif - - if (self != RT_NULL) - { - rt_kprintf("thread:%-8.*s exit:%d!\n", RT_NAME_MAX, self->name, status); - rt_thread_suspend(self); - rt_schedule(); - } - - while(1); /* noreturn */ + extern void __rt_libc_exit(int status); + __rt_libc_exit(status); + while(1); } void _system(const char *s) { - /* not support this call */ - return; + extern int __rt_libc_system(const char *string); + __rt_libc_system(s); } void __libc_init_array(void) @@ -319,23 +305,9 @@ void __libc_init_array(void) void abort(void) { - rt_thread_t self = rt_thread_self(); - -#ifdef RT_USING_MODULE - if (dlmodule_self()) - { - dlmodule_exit(-1); - } -#endif - - if (self != RT_NULL) - { - rt_kprintf("thread:%-8.*s abort!\n", RT_NAME_MAX, self->name); - rt_thread_suspend(self); - rt_schedule(); - } - - while(1); /* noreturn */ + extern void __rt_libc_abort(void); + __rt_libc_abort(); + while(1); } uid_t getuid(void)