Add board k210-emulator

This commit is contained in:
Zhao_Jiasheng
2021-05-10 21:08:25 +08:00
parent 0602e09627
commit 6f7cf059ec
106 changed files with 28284 additions and 3 deletions
@@ -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);
}