forked from xuos/xiuos
Add board k210-emulator
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
config PIN_BUS_NAME
|
||||
string "pin bus name"
|
||||
default "pin"
|
||||
|
||||
config PIN_DRIVER_NAME
|
||||
string "pin driver name"
|
||||
default "pin_drv"
|
||||
|
||||
config PIN_DEVICE_NAME
|
||||
string "pin device name"
|
||||
default "pin_dev"
|
||||
@@ -0,0 +1,8 @@
|
||||
SRC_FILES := connect_gpio.c drv_io_config.c fpioa.c gpio.c gpiohs.c utils.c
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
include $(KERNEL_ROOT)/compiler.mk
|
||||
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-19 ZYH first version
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file connect_gpio.c
|
||||
* @brief support gpio function using bus driver framework
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: connect_gpio.c
|
||||
Description: support gpio configure and register to bus framework
|
||||
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_gpio.c for references
|
||||
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: add bus driver framework support for gpio
|
||||
*************************************************/
|
||||
|
||||
#include <xiuos.h>
|
||||
#include <device.h>
|
||||
#include <fpioa.h>
|
||||
#include <gpiohs.h>
|
||||
#include "drv_io_config.h"
|
||||
#include <plic.h>
|
||||
#include <utils.h>
|
||||
#include "connect_gpio.h"
|
||||
|
||||
#define FUNC_GPIOHS(n) (FUNC_GPIOHS0 + n)
|
||||
|
||||
static int pin_alloc_table[FPIOA_NUM_IO];
|
||||
static uint32_t free_pin = 0;
|
||||
|
||||
static int AllocPinChannel(x_base pin_index)
|
||||
{
|
||||
if (free_pin == 31) {
|
||||
SYS_ERR("no free gpiohs channel to alloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pin_alloc_table[pin_index] != -1) {
|
||||
SYS_WARN("already alloc gpiohs channel for pin %d", pin_index);
|
||||
return pin_alloc_table[pin_index];
|
||||
}
|
||||
|
||||
pin_alloc_table[pin_index] = free_pin;
|
||||
free_pin++;
|
||||
|
||||
FpioaSetFunction(pin_index, FUNC_GPIOHS(pin_alloc_table[pin_index]));
|
||||
return pin_alloc_table[pin_index];
|
||||
}
|
||||
|
||||
static int GetPinChannel(x_base pin_index)
|
||||
{
|
||||
return pin_alloc_table[pin_index];
|
||||
}
|
||||
|
||||
static uint32 GpioConfigMode(int mode, uint8_t pin_channel)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_CFG_OUTPUT:
|
||||
gpiohs_set_drive_mode(pin_channel, GPIO_DM_OUTPUT);
|
||||
break;
|
||||
case GPIO_CFG_INPUT:
|
||||
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT);
|
||||
break;
|
||||
case GPIO_CFG_INPUT_PULLUP:
|
||||
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_UP);
|
||||
break;
|
||||
case GPIO_CFG_INPUT_PULLDOWN:
|
||||
gpiohs_set_drive_mode(pin_channel, GPIO_DM_INPUT_PULL_DOWN);
|
||||
break;
|
||||
case GPIO_CFG_OUTPUT_OD:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return EOK;
|
||||
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
void (*hdr)(void *args);
|
||||
void *args;
|
||||
GpioPinEdgeT edge;
|
||||
} IrqTable[32];
|
||||
|
||||
static void pin_irq(int vector, void *param)
|
||||
{
|
||||
int pin_channel = vector - IRQN_GPIOHS0_INTERRUPT;
|
||||
if (IrqTable[pin_channel].edge & GPIO_PE_FALLING) {
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin_channel, 1);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin_channel, 1);
|
||||
}
|
||||
|
||||
if (IrqTable[pin_channel].edge & GPIO_PE_RISING) {
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin_channel, 1);
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin_channel, 1);
|
||||
}
|
||||
|
||||
if (IrqTable[pin_channel].edge & GPIO_PE_LOW) {
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin_channel, 1);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin_channel, 1);
|
||||
}
|
||||
|
||||
if (IrqTable[pin_channel].edge & GPIO_PE_HIGH) {
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin_channel, 1);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin_channel, 1);
|
||||
}
|
||||
|
||||
if (IrqTable[pin_channel].hdr) {
|
||||
IrqTable[pin_channel].hdr(IrqTable[pin_channel].args);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 GpioIrqRegister(int32 pin_channel, int32 mode, void (*hdr)(void *args), void *args)
|
||||
{
|
||||
IrqTable[pin_channel].hdr = hdr;
|
||||
IrqTable[pin_channel].args = args;
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_IRQ_EDGE_RISING:
|
||||
IrqTable[pin_channel].edge = GPIO_PE_RISING;
|
||||
break;
|
||||
case GPIO_IRQ_EDGE_FALLING:
|
||||
IrqTable[pin_channel].edge = GPIO_PE_FALLING;
|
||||
break;
|
||||
case GPIO_IRQ_EDGE_BOTH:
|
||||
IrqTable[pin_channel].edge = GPIO_PE_BOTH;
|
||||
break;
|
||||
case GPIO_IRQ_LEVEL_HIGH:
|
||||
IrqTable[pin_channel].edge = GPIO_PE_LOW;
|
||||
break;
|
||||
case GPIO_IRQ_LEVEL_LOW:
|
||||
IrqTable[pin_channel].edge = GPIO_PE_HIGH;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gpiohs_set_pin_edge(pin_channel, IrqTable[pin_channel].edge);
|
||||
|
||||
isrManager.done->registerIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel, pin_irq, NONE);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 GpioIrqFree(int32 pin_channel)
|
||||
{
|
||||
IrqTable[pin_channel].hdr = NONE;
|
||||
IrqTable[pin_channel].args = NONE;
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 GpioIrqEnable(int32 pin_channel)
|
||||
{
|
||||
isrManager.done->enableIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel);
|
||||
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 GpioIrqDisable(int32 pin_channel)
|
||||
{
|
||||
isrManager.done->disableIrq(IRQN_GPIOHS0_INTERRUPT + pin_channel);
|
||||
return EOK;
|
||||
}
|
||||
|
||||
static uint32 PinConfigure(struct PinParam *param)
|
||||
{
|
||||
NULL_PARAM_CHECK(param);
|
||||
int ret = EOK;
|
||||
|
||||
int pin_channel = GetPinChannel(param->pin);
|
||||
if (pin_channel == -1) {
|
||||
pin_channel = AllocPinChannel(param->pin);
|
||||
if (pin_channel == -1) {
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
switch (param->cmd)
|
||||
{
|
||||
case GPIO_CONFIG_MODE:
|
||||
GpioConfigMode(param->mode, pin_channel);
|
||||
break;
|
||||
case GPIO_IRQ_REGISTER:
|
||||
ret = GpioIrqRegister(pin_channel,param->irq_set.irq_mode,param->irq_set.hdr,param->irq_set.args);
|
||||
break;
|
||||
case GPIO_IRQ_FREE:
|
||||
ret = GpioIrqFree(pin_channel);
|
||||
break;
|
||||
case GPIO_IRQ_ENABLE:
|
||||
ret = GpioIrqEnable(pin_channel);
|
||||
break;
|
||||
case GPIO_IRQ_DISABLE:
|
||||
ret = GpioIrqDisable(pin_channel);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVALED;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32 GpioDrvConfigure(void *drv, struct BusConfigureInfo *configure_info)
|
||||
{
|
||||
NULL_PARAM_CHECK(drv);
|
||||
NULL_PARAM_CHECK(configure_info);
|
||||
|
||||
x_err_t ret = EOK;
|
||||
struct PinParam *param;
|
||||
|
||||
switch (configure_info->configure_cmd)
|
||||
{
|
||||
case OPE_CFG:
|
||||
param = (struct PinParam *)configure_info->private_data;
|
||||
ret = PinConfigure(param);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32 PinWrite(void *dev, struct BusBlockWriteParam *write_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
NULL_PARAM_CHECK(write_param);
|
||||
struct PinStat *pinstat = (struct PinStat *)write_param->buffer;
|
||||
|
||||
int pin_channel = GetPinChannel(pinstat->pin);
|
||||
if (pin_channel == -1) {
|
||||
SYS_ERR("pin %d not set mode", pinstat->pin);
|
||||
return ERROR;
|
||||
}
|
||||
gpiohs_set_pin(pin_channel, pinstat->val == GPIO_HIGH ? GPIO_PV_HIGH : GPIO_PV_LOW);
|
||||
}
|
||||
|
||||
uint32 PinRead(void *dev, struct BusBlockReadParam *read_param)
|
||||
{
|
||||
NULL_PARAM_CHECK(dev);
|
||||
NULL_PARAM_CHECK(read_param);
|
||||
struct PinStat *pinstat = (struct PinStat *)read_param->buffer;
|
||||
|
||||
int pin_channel = GetPinChannel(pinstat->pin);
|
||||
if (pin_channel == -1) {
|
||||
SYS_ERR("pin %d not set mode", pinstat->pin);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
if (gpiohs_get_pin(pin_channel) == GPIO_PV_HIGH){
|
||||
pinstat->val = GPIO_HIGH;
|
||||
return GPIO_HIGH;
|
||||
} else {
|
||||
pinstat->val = GPIO_LOW;
|
||||
return GPIO_LOW;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct PinDevDone dev_done =
|
||||
{
|
||||
.open = NONE,
|
||||
.close = NONE,
|
||||
.write = PinWrite,
|
||||
.read = PinRead,
|
||||
};
|
||||
|
||||
int HwGpioInit(void)
|
||||
{
|
||||
x_err_t ret = EOK;
|
||||
|
||||
static struct PinBus pin;
|
||||
|
||||
memset(pin_alloc_table, -1, sizeof pin_alloc_table);
|
||||
free_pin = GPIO_ALLOC_START;
|
||||
|
||||
ret = PinBusInit(&pin, PIN_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("gpio bus init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct PinDriver drv;
|
||||
drv.configure = &GpioDrvConfigure;
|
||||
|
||||
ret = PinDriverInit(&drv, PIN_DRIVER_NAME, NONE);
|
||||
if (ret != EOK) {
|
||||
KPrintf("pin driver init error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = PinDriverAttachToBus(PIN_DRIVER_NAME, PIN_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("pin driver attach error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
static struct PinHardwareDevice dev;
|
||||
dev.dev_done = &dev_done;
|
||||
|
||||
ret = PinDeviceRegister(&dev, NONE, PIN_DEVICE_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("pin device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
ret = PinDeviceAttachToBus(PIN_DEVICE_NAME, PIN_BUS_NAME);
|
||||
if (ret != EOK) {
|
||||
KPrintf("pin device register error %d\n", ret);
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2019-03-19 ZYH first version
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drv_io_config.c
|
||||
* @brief support kd233-board io configure
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
/*************************************************
|
||||
File name: drv_io_config.c
|
||||
Description: support kd233-board io configure
|
||||
Others: take RT-Thread v4.0.2/bsp/k210/driver/drv_io_config.c for references
|
||||
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
|
||||
History:
|
||||
1. Date: 2021-04-25
|
||||
Author: AIIT XUOS Lab
|
||||
Modification: support kd233-board io configure
|
||||
*************************************************/
|
||||
|
||||
#include <xiuos.h>
|
||||
#include <fpioa.h>
|
||||
#include "drv_io_config.h"
|
||||
#include <sysctl.h>
|
||||
|
||||
|
||||
//#define LED_TEST
|
||||
|
||||
#define HS_GPIO(n) (FUNC_GPIOHS0 + n)
|
||||
|
||||
#define IOCONFIG(pin,func) {pin, func, #func}
|
||||
|
||||
static struct io_config
|
||||
{
|
||||
int io_num;
|
||||
fpioa_function_t func;
|
||||
const char * FuncName;
|
||||
} io_config[] =
|
||||
{
|
||||
#ifdef BSP_USING_LCD
|
||||
IOCONFIG(BSP_LCD_CS_PIN, FUNC_SPI0_SS0),
|
||||
IOCONFIG(BSP_LCD_WR_PIN, FUNC_SPI0_SCLK),
|
||||
IOCONFIG(BSP_LCD_DC_PIN, HS_GPIO(LCD_DC_PIN)),
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_CAMERA
|
||||
IOCONFIG(BSP_CAMERA_SCCB_SDA_PIN, FUNC_SCCB_SDA),
|
||||
IOCONFIG(BSP_CAMERA_SCCB_SCLK_PIN, FUNC_SCCB_SCLK),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_RST_PIN, FUNC_CMOS_RST),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_VSYNC_PIN, FUNC_CMOS_VSYNC),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_PWDN_PIN, FUNC_CMOS_PWDN),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_XCLK_PIN, FUNC_CMOS_XCLK),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_PCLK_PIN, FUNC_CMOS_PCLK),
|
||||
IOCONFIG(BSP_CAMERA_CMOS_HREF_PIN, FUNC_CMOS_HREF),
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_SPI1
|
||||
IOCONFIG(BSP_SPI1_CLK_PIN, FUNC_SPI1_SCLK),
|
||||
IOCONFIG(BSP_SPI1_D0_PIN, FUNC_SPI1_D0),
|
||||
IOCONFIG(BSP_SPI1_D1_PIN, FUNC_SPI1_D1),
|
||||
#ifdef BSP_USING_SPI1_AS_QSPI
|
||||
IOCONFIG(BSP_SPI1_D2_PIN, FUNC_SPI1_D2),
|
||||
IOCONFIG(BSP_SPI1_D3_PIN, FUNC_SPI1_D3),
|
||||
#endif
|
||||
#ifdef BSP_SPI1_USING_SS0
|
||||
IOCONFIG(BSP_SPI1_SS0_PIN, HS_GPIO(SPI1_CS0_PIN)),
|
||||
#endif
|
||||
#ifdef BSP_SPI1_USING_SS1
|
||||
IOCONFIG(BSP_SPI1_SS1_PIN, HS_GPIO(SPI1_CS1_PIN)),
|
||||
#endif
|
||||
#ifdef BSP_SPI1_USING_SS2
|
||||
IOCONFIG(BSP_SPI1_SS2_PIN, HS_GPIO(SPI1_CS2_PIN)),
|
||||
#endif
|
||||
#ifdef BSP_SPI1_USING_SS3
|
||||
IOCONFIG(BSP_SPI1_SS3_PIN, HS_GPIO(SPI1_CS3_PIN)),
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BSP_USING_UART1
|
||||
IOCONFIG(BSP_UART1_TXD_PIN, FUNC_UART1_TX),
|
||||
IOCONFIG(BSP_UART1_RXD_PIN, FUNC_UART1_RX),
|
||||
#endif
|
||||
#ifdef BSP_USING_UART2
|
||||
IOCONFIG(BSP_UART2_TXD_PIN, FUNC_UART2_TX),
|
||||
IOCONFIG(BSP_UART2_RXD_PIN, FUNC_UART2_RX),
|
||||
#endif
|
||||
#ifdef BSP_USING_UART3
|
||||
IOCONFIG(BSP_UART3_TXD_PIN, FUNC_UART3_TX),
|
||||
IOCONFIG(BSP_UART3_RXD_PIN, FUNC_UART3_RX),
|
||||
#endif
|
||||
|
||||
// #ifdef LED_TEST
|
||||
// IOCONFIG(LED0, FUNC_GPIOHS0),
|
||||
// #endif
|
||||
IOCONFIG(18, FUNC_GPIOHS18),
|
||||
IOCONFIG(19, FUNC_GPIOHS19),
|
||||
};
|
||||
|
||||
static int PrintIoConfig()
|
||||
{
|
||||
int i;
|
||||
KPrintf("IO Configuration Table\n");
|
||||
KPrintf("┌───────┬────────────────────────┐\n");
|
||||
KPrintf("│Pin │Function │\n");
|
||||
KPrintf("├───────┼────────────────────────┤\n");
|
||||
for(i = 0; i < sizeof io_config / sizeof io_config[0]; i++)
|
||||
{
|
||||
KPrintf("│%-2d │%-24.24s│\n", io_config[i].io_num, io_config[i].FuncName);
|
||||
}
|
||||
KPrintf("└───────┴────────────────────────┘\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_FUNC)|SHELL_CMD_PARAM_NUM(0),
|
||||
io,PrintIoConfig,print io config);
|
||||
|
||||
|
||||
int IoConfigInit(void)
|
||||
{
|
||||
int count = sizeof(io_config) / sizeof(io_config[0]);
|
||||
int i;
|
||||
int ret = 0;
|
||||
|
||||
sysctl_set_power_mode(SYSCTL_POWER_BANK0, SYSCTL_POWER_V18);
|
||||
sysctl_set_power_mode(SYSCTL_POWER_BANK1, SYSCTL_POWER_V18);
|
||||
sysctl_set_power_mode(SYSCTL_POWER_BANK2, SYSCTL_POWER_V18);
|
||||
#ifdef BSP_USING_UART2
|
||||
// for IO-27/28
|
||||
sysctl_set_power_mode(SYSCTL_POWER_BANK4, SYSCTL_POWER_V33);
|
||||
#endif
|
||||
#if defined(BSP_USING_UART1) || defined(BSP_USING_UART3)
|
||||
// for IO-20~23
|
||||
sysctl_set_power_mode(SYSCTL_POWER_BANK3, SYSCTL_POWER_V33);
|
||||
#endif
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
ret = FpioaSetFunction(io_config[i].io_num, io_config[i].func);
|
||||
if(ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(BSP_USING_CAMERA) || defined(BSP_USING_LCD)
|
||||
sysctl_set_spi0_dvp_data(1);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,89 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"},
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpio.c
|
||||
* @brief add from Canaan K210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
#include "gpio.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#define GPIO_MAX_PINNO 8
|
||||
|
||||
volatile gpio_t* const gpio = (volatile gpio_t*)GPIO_BASE_ADDR;
|
||||
|
||||
int gpio_init(void)
|
||||
{
|
||||
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
|
||||
}
|
||||
|
||||
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIO0 + pin);
|
||||
configASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"GPIO drive mode is not supported.") break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
set_gpio_bit(gpio->direction.u32, pin, dir);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpio_get_pin(uint8_t pin)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
return get_gpio_bit(reg, pin);
|
||||
}
|
||||
|
||||
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
configASSERT(pin < GPIO_MAX_PINNO);
|
||||
uint32_t dir = get_gpio_bit(gpio->direction.u32, pin);
|
||||
volatile uint32_t *reg = dir ? gpio->data_output.u32 : gpio->data_input.u32;
|
||||
configASSERT(dir == 1);
|
||||
set_gpio_bit(reg, pin, value);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"},
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file gpiohs.c
|
||||
* @brief add from Canaan K210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
#include "gpiohs.h"
|
||||
#include "utils.h"
|
||||
#include "fpioa.h"
|
||||
#include "sysctl.h"
|
||||
#define GPIOHS_MAX_PINNO 32
|
||||
|
||||
volatile gpiohs_t* const gpiohs = (volatile gpiohs_t*)GPIOHS_BASE_ADDR;
|
||||
|
||||
typedef struct _gpiohs_pin_instance
|
||||
{
|
||||
size_t pin;
|
||||
GpioPinEdgeT edge;
|
||||
void (*callback)();
|
||||
plic_irq_callback_t gpiohs_callback;
|
||||
void *context;
|
||||
} gpiohs_pin_instance_t;
|
||||
|
||||
static gpiohs_pin_instance_t pin_instance[32];
|
||||
|
||||
void gpiohs_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
int io_number = fpioa_get_io_by_function(FUNC_GPIOHS0 + pin);
|
||||
configASSERT(io_number >= 0);
|
||||
|
||||
fpioa_pull_t pull;
|
||||
uint32_t dir;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case GPIO_DM_INPUT:
|
||||
pull = FPIOA_PULL_NONE;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_DOWN:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_INPUT_PULL_UP:
|
||||
pull = FPIOA_PULL_UP;
|
||||
dir = 0;
|
||||
break;
|
||||
case GPIO_DM_OUTPUT:
|
||||
pull = FPIOA_PULL_DOWN;
|
||||
dir = 1;
|
||||
break;
|
||||
default:
|
||||
configASSERT(!"GPIO drive mode is not supported.") break;
|
||||
}
|
||||
|
||||
fpioa_set_io_pull(io_number, pull);
|
||||
volatile uint32_t *reg = dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
volatile uint32_t *reg_d = !dir ? gpiohs->output_en.u32 : gpiohs->input_en.u32;
|
||||
set_gpio_bit(reg_d, pin, 0);
|
||||
set_gpio_bit(reg, pin, 1);
|
||||
}
|
||||
|
||||
gpio_pin_value_t gpiohs_get_pin(uint8_t pin)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
return get_gpio_bit(gpiohs->input_val.u32, pin);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin(uint8_t pin, gpio_pin_value_t value)
|
||||
{
|
||||
configASSERT(pin < GPIOHS_MAX_PINNO);
|
||||
set_gpio_bit(gpiohs->output_val.u32, pin, value);
|
||||
}
|
||||
|
||||
void gpiohs_set_pin_edge(uint8_t pin, GpioPinEdgeT edge)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
|
||||
if(edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
if(edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
}
|
||||
|
||||
pin_instance[pin].edge = edge;
|
||||
}
|
||||
|
||||
int gpiohs_pin_onchange_isr(void *userdata)
|
||||
{
|
||||
gpiohs_pin_instance_t *ctx = (gpiohs_pin_instance_t *)userdata;
|
||||
size_t pin = ctx->pin;
|
||||
|
||||
if(ctx->edge & GPIO_PE_FALLING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_RISING)
|
||||
{
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->rise_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_LOW)
|
||||
{
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if(ctx->edge & GPIO_PE_HIGH)
|
||||
{
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ip.u32, pin, 1);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 1);
|
||||
}
|
||||
|
||||
if (ctx->callback)
|
||||
ctx->callback();
|
||||
if(ctx->gpiohs_callback)
|
||||
ctx->gpiohs_callback(ctx->context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpiohs_set_irq(uint8_t pin, uint32_t priority, void (*func)())
|
||||
{
|
||||
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].callback = func;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_register(uint8_t pin, uint32_t priority, plic_irq_callback_t callback, void *ctx)
|
||||
{
|
||||
pin_instance[pin].pin = pin;
|
||||
pin_instance[pin].gpiohs_callback = callback;
|
||||
pin_instance[pin].context = ctx;
|
||||
|
||||
plic_set_priority(IRQN_GPIOHS0_INTERRUPT + pin, priority);
|
||||
plic_irq_register(IRQN_GPIOHS0_INTERRUPT + pin, gpiohs_pin_onchange_isr, &(pin_instance[pin]));
|
||||
plic_irq_enable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_unregister(uint8_t pin)
|
||||
{
|
||||
pin_instance[pin] = (gpiohs_pin_instance_t){
|
||||
.callback = NULL,
|
||||
.gpiohs_callback = NULL,
|
||||
.context = NULL,
|
||||
};
|
||||
set_gpio_bit(gpiohs->rise_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->fall_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->low_ie.u32, pin, 0);
|
||||
set_gpio_bit(gpiohs->high_ie.u32, pin, 0);
|
||||
plic_irq_unregister(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
void gpiohs_irq_disable(size_t pin)
|
||||
{
|
||||
plic_irq_disable(IRQN_GPIOHS0_INTERRUPT + pin);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Copyright 2018 Canaan Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"},
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file utils.c
|
||||
* @brief add from Canaan K210 SDK
|
||||
* https://canaan-creative.com/developer
|
||||
* @version 1.0
|
||||
* @author AIIT XUOS Lab
|
||||
* @date 2021-04-25
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "encoding.h"
|
||||
#include "utils.h"
|
||||
|
||||
void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
|
||||
{
|
||||
uint32_t org = (*bits) & ~mask;
|
||||
*bits = org | (value & mask);
|
||||
}
|
||||
|
||||
void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit(bits, mask << offset, value << offset);
|
||||
}
|
||||
|
||||
void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
|
||||
{
|
||||
set_bit_offset(bits, 1, offset, value);
|
||||
}
|
||||
|
||||
uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
|
||||
{
|
||||
return ((*bits) & (mask << offset)) >> offset;
|
||||
}
|
||||
|
||||
uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
|
||||
{
|
||||
return get_bit(bits, 1, offset);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user