support gpio on k210 on nuttx

This commit is contained in:
wgzAIIT 2022-10-21 18:13:41 +08:00
parent df32ed24ed
commit c815bb3b6e
2 changed files with 206 additions and 103 deletions

View File

@ -39,82 +39,110 @@
#include "k210_memorymap.h"
#include "k210_gpio.h"
#include "k210_fpioa.h"
#include "k210_sysctl.h"
#define GPIO_MAX_PINNO 8
/****************************************************************************
* Pre-processor Definitions
* Private Function declaration
****************************************************************************/
#define GPIO_INPUT_VAL_OFFSET 0x00
#define GPIO_INPUT_EN_OFFSET 0x04
#define GPIO_OUTPUT_EN_OFFSET 0x08
#define GPIO_OUTPUT_VAL_OFFSET 0x0c
#define GPIO_PULLUP_EN_OFFSET 0x10
#define GPIO_DRIVE_OFFSET 0x14
#define GPIO_INPUT (K210_GPIO_BASE + GPIO_INPUT_VAL_OFFSET)
#define GPIO_INPUT_EN (K210_GPIO_BASE + GPIO_INPUT_EN_OFFSET)
#define GPIO_OUTPUT (K210_GPIO_BASE + GPIO_OUTPUT_VAL_OFFSET)
#define GPIO_OUTPUT_EN (K210_GPIO_BASE + GPIO_OUTPUT_EN_OFFSET)
static void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value);
static void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value);
static void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value);
static uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset);
static uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset);
/****************************************************************************
* Public Functions
* Private Data
****************************************************************************/
void k210_gpio_set_direction(uint32_t io, gpio_drive_mode_t mode)
volatile gpio_t *const gpio = (volatile gpio_t *)K210_GPIO_BASE;
/****************************************************************************
* Private Function definition
****************************************************************************/
static void set_bit(volatile uint32_t *bits, uint32_t mask, uint32_t value)
{
DEBUGASSERT(io < K210_GPIO_MAX_PINNO);
int io_number = k210_fpioa_get_io_by_function(K210_IO_FUNC_GPIO0 + io);
DEBUGASSERT(io_number >= 0);
fpioa_pull_t pull = FPIOA_PULL_NONE;
uint32_t dir = 0;
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:
DEBUGASSERT(!"GPIO drive mode is not supported.");
break;
}
fpioa_set_io_pull(io_number, pull);
uint32_t outbit = dir << io;
uint32_t inbit = (!dir) << io;
modifyreg32(GPIO_OUTPUT_EN, inbit, outbit);
modifyreg32(GPIO_INPUT_EN, outbit, inbit);
uint32_t org = (*bits) & ~mask;
*bits = org | (value & mask);
}
void k210_gpio_set_value(uint32_t io, bool val)
static void set_bit_offset(volatile uint32_t *bits, uint32_t mask, size_t offset, uint32_t value)
{
uint32_t setbit = val << io;
uint32_t clrbit = (!val) << io;
modifyreg32(GPIO_OUTPUT, clrbit, setbit);
set_bit(bits, mask << offset, value << offset);
}
bool k210_gpio_get_value(uint32_t io)
static void set_gpio_bit(volatile uint32_t *bits, size_t offset, uint32_t value)
{
uint32_t reg = getreg32(GPIO_INPUT);
set_bit_offset(bits, 1, offset, value);
}
if (reg & (1 << io))
static uint32_t get_bit(volatile uint32_t *bits, uint32_t mask, size_t offset)
{
return ((*bits) & (mask << offset)) >> offset;
}
static uint32_t get_gpio_bit(volatile uint32_t *bits, size_t offset)
{
return get_bit(bits, 1, offset);
}
/****************************************************************************
* Public Function definition
****************************************************************************/
int gpio_init(void)
{
return sysctl_clock_enable(SYSCTL_CLOCK_GPIO);
}
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode)
{
DEBUGASSERT(pin < GPIO_MAX_PINNO);
int io_number = fpioa_get_io_by_function(K210_IO_FUNC_GPIO0 + pin);
DEBUGASSERT(io_number >= 0);
fpioa_pull_t pull;
uint32_t dir;
switch(mode)
{
return true;
}
else
{
return false;
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:
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)
{
DEBUGASSERT(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)
{
DEBUGASSERT(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;
DEBUGASSERT(dir == 1);
set_gpio_bit(reg, pin, value);
}

View File

@ -38,52 +38,127 @@
#include <stdbool.h>
#include "k210_gpio_common.h"
typedef struct _gpio_bits
{
uint32_t b0 : 1;
uint32_t b1 : 1;
uint32_t b2 : 1;
uint32_t b3 : 1;
uint32_t b4 : 1;
uint32_t b5 : 1;
uint32_t b6 : 1;
uint32_t b7 : 1;
uint32_t b8 : 1;
uint32_t b9 : 1;
uint32_t b10 : 1;
uint32_t b11 : 1;
uint32_t b12 : 1;
uint32_t b13 : 1;
uint32_t b14 : 1;
uint32_t b15 : 1;
uint32_t b16 : 1;
uint32_t b17 : 1;
uint32_t b18 : 1;
uint32_t b19 : 1;
uint32_t b20 : 1;
uint32_t b21 : 1;
uint32_t b22 : 1;
uint32_t b23 : 1;
uint32_t b24 : 1;
uint32_t b25 : 1;
uint32_t b26 : 1;
uint32_t b27 : 1;
uint32_t b28 : 1;
uint32_t b29 : 1;
uint32_t b30 : 1;
uint32_t b31 : 1;
} __attribute__((packed, aligned(4))) gpio_bits_t;
/* Structure of templates for accessing GPIO registers */
typedef union _gpio_access_tp
{
/* 32x1 bit mode */
uint32_t u32[1];
/* 16x2 bit mode */
uint16_t u16[2];
/* 8x4 bit mode */
uint8_t u8[4];
/* 1 bit mode */
gpio_bits_t bits;
} __attribute__((packed, aligned(4))) gpio_access_tp_t;
/* The GPIO address map */
typedef struct _gpio
{
/* Offset 0x00: Data (output) registers */
gpio_access_tp_t data_output;
/* Offset 0x04: Data direction registers */
gpio_access_tp_t direction;
/* Offset 0x08: Data source registers */
gpio_access_tp_t source;
/* Offset 0x10 - 0x2f: Unused registers, 9x4 bytes */
uint32_t unused_0[9];
/* Offset 0x30: Interrupt enable/disable registers */
gpio_access_tp_t interrupt_enable;
/* Offset 0x34: Interrupt mask registers */
gpio_access_tp_t interrupt_mask;
/* Offset 0x38: Interrupt level registers */
gpio_access_tp_t interrupt_level;
/* Offset 0x3c: Interrupt polarity registers */
gpio_access_tp_t interrupt_polarity;
/* Offset 0x40: Interrupt status registers */
gpio_access_tp_t interrupt_status;
/* Offset 0x44: Raw interrupt status registers */
gpio_access_tp_t interrupt_status_raw;
/* Offset 0x48: Interrupt debounce registers */
gpio_access_tp_t interrupt_debounce;
/* Offset 0x4c: Registers for clearing interrupts */
gpio_access_tp_t interrupt_clear;
/* Offset 0x50: External port (data input) registers */
gpio_access_tp_t data_input;
/* Offset 0x54 - 0x5f: Unused registers, 3x4 bytes */
uint32_t unused_1[3];
/* Offset 0x60: Sync level registers */
gpio_access_tp_t sync_level;
/* Offset 0x64: ID code */
gpio_access_tp_t id_code;
/* Offset 0x68: Interrupt both edge type */
gpio_access_tp_t interrupt_bothedge;
} __attribute__((packed, aligned(4))) gpio_t;
/* Bus GPIO object instance */
extern volatile gpio_t *const gpio;
/****************************************************************************
* Public Functions Prototypes
****************************************************************************/
/**
* @brief Gpio initialize
* @return - 0:Success,Other:Fail
*/
int gpio_init(void);
/****************************************************************************
* Name: k210_gpio_set_direction
*
* Description:
* Set gpiohs direction
*
* Input Parameters:
* io - IO number
* dir - true for output, false for input
*
****************************************************************************/
/**
* @brief Set Gpio drive mode
* @param[in] pin Gpio pin
* @param[in] mode Gpio pin drive mode
*/
void gpio_set_drive_mode(uint8_t pin, gpio_drive_mode_t mode);
void k210_gpio_set_direction(uint32_t io, gpio_drive_mode_t mode);
/**
* @brief Get Gpio pin value
* @param[in] pin Gpio pin
* @return Pin value
* GPIO_PV_Low Gpio pin low
* GPIO_PV_High Gpio pin high
*/
gpio_pin_value_t gpio_get_pin(uint8_t pin);
/****************************************************************************
* Name: k210_gpio_set_value
*
* Description:
* Set gpiohs direction
*
* Input Parameters:
* io - IO number
* dir - true for high level, false for low level
*
****************************************************************************/
void k210_gpio_set_value(uint32_t io, bool val);
/****************************************************************************
* Name: k210_gpio_get_value
*
* Description:
* Get gpiohs level
*
* Input Parameters:
* io - IO number
*
* Returned Value:
* true for high level, false for low level
*
****************************************************************************/
bool k210_gpio_get_value(uint32_t io);
/**
* @brief Set Gpio pin value
* @param[in] pin Gpio pin
* @param[in] value Gpio pin value
*/
void gpio_set_pin(uint8_t pin, gpio_pin_value_t value);
#endif /* __ARCH_RISCV_SRC_K210_K210_GPIO_H */