mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
cpu/lm4f120: GPIO support
This commit is contained in:
parent
e0732a5a81
commit
8f0a9ddf6f
@ -1,5 +1,6 @@
|
||||
# Put defined MCU peripherals here (in alphabetical order)
|
||||
FEATURES_PROVIDED += periph_cpuid
|
||||
FEATURES_PROVIDED += periph_gpio
|
||||
FEATURES_PROVIDED += periph_timer
|
||||
FEATURES_PROVIDED += periph_uart
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define PERIPH_CPU_H_
|
||||
|
||||
#include "periph/dev_enums.h"
|
||||
#include "cpu_conf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,6 +31,62 @@ extern "C" {
|
||||
*/
|
||||
#define CPUID_LEN (12U)
|
||||
|
||||
/**
|
||||
* @brief Overwrite the default gpio_t type definition
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_T
|
||||
typedef uint32_t gpio_t;
|
||||
#define GPIO_PIN(x,y) ((gpio_t)((x<<4) | y))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Override values for pull register configuration
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_PP_T
|
||||
typedef enum {
|
||||
GPIO_NOPULL = GPIO_PIN_TYPE_STD, /**< do not use internal pull resistors */
|
||||
GPIO_PULLUP = GPIO_PIN_TYPE_STD_WPU, /**< enable internal pull-up resistor */
|
||||
GPIO_PULLDOWN = GPIO_PIN_TYPE_STD_WPD /**< enable internal pull-down resistor */
|
||||
} gpio_pp_t;
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Override values for pin direction configuration
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_DIR_T
|
||||
typedef enum {
|
||||
GPIO_DIR_IN = GPIO_DIR_MODE_IN, /**< configure pin as input */
|
||||
GPIO_DIR_OUT = GPIO_DIR_MODE_OUT /**< configure pin as output */
|
||||
} gpio_dir_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Override active flank configuration values
|
||||
* @{
|
||||
*/
|
||||
#define HAVE_GPIO_FLANK_T
|
||||
typedef enum {
|
||||
GPIO_FALLING = GPIO_FALLING_EDGE, /**< emit interrupt on falling flank */
|
||||
GPIO_RISING = GPIO_RISING_EDGE, /**< emit interrupt on rising flank */
|
||||
GPIO_BOTH = GPIO_BOTH_EDGES /**< emit interrupt on both flanks */
|
||||
} gpio_flank_t;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Available ports on the LM4F120
|
||||
*/
|
||||
enum {
|
||||
PORT_A = 0, /**< port A */
|
||||
PORT_B = 1, /**< port B */
|
||||
PORT_C = 2, /**< port C */
|
||||
PORT_D = 3, /**< port D */
|
||||
PORT_E = 4, /**< port E */
|
||||
PORT_F = 5, /**< port F */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
269
cpu/lm4f120/periph/gpio.c
Normal file
269
cpu/lm4f120/periph/gpio.c
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Marc Poulhiès
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser General
|
||||
* Public License v2.1. See the file LICENSE in the top level directory for more
|
||||
* details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup cpu_lm4f120
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Low-level GPIO driver implementation
|
||||
*
|
||||
* @author Marc Poulhiès <dkm@kataplop.net>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "cpu_conf.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph_conf.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @brief Extract the pin number of the given pin
|
||||
*/
|
||||
static inline uint8_t _pin_num(gpio_t pin)
|
||||
{
|
||||
return (pin & 0x0f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Extract the port number of the given pin
|
||||
*/
|
||||
static inline uint8_t _port_num(gpio_t pin)
|
||||
{
|
||||
return (pin >> 4);
|
||||
}
|
||||
|
||||
static const uint32_t _sysctl_port_base[] = {
|
||||
SYSCTL_PERIPH_GPIOA,
|
||||
SYSCTL_PERIPH_GPIOB,
|
||||
SYSCTL_PERIPH_GPIOC,
|
||||
SYSCTL_PERIPH_GPIOD,
|
||||
SYSCTL_PERIPH_GPIOE,
|
||||
SYSCTL_PERIPH_GPIOF,
|
||||
};
|
||||
|
||||
static const uint32_t _port_base[] = {
|
||||
GPIO_PORTA_BASE,
|
||||
GPIO_PORTB_BASE,
|
||||
GPIO_PORTC_BASE,
|
||||
GPIO_PORTD_BASE,
|
||||
GPIO_PORTE_BASE,
|
||||
GPIO_PORTF_BASE,
|
||||
};
|
||||
|
||||
static const uint32_t _int_assign[] = {
|
||||
INT_GPIOA,
|
||||
INT_GPIOB,
|
||||
INT_GPIOC,
|
||||
INT_GPIOD,
|
||||
INT_GPIOE,
|
||||
INT_GPIOF,
|
||||
};
|
||||
|
||||
#define NUM_OF_PORT 6
|
||||
#define NUM_OF_PINS 8
|
||||
|
||||
typedef struct {
|
||||
gpio_cb_t cb; /**< callback called from GPIO interrupt */
|
||||
void *arg; /**< argument passed to the callback */
|
||||
} gpio_state_t;
|
||||
|
||||
static gpio_state_t gpio_config[NUM_OF_PORT][NUM_OF_PINS];
|
||||
|
||||
static inline uint16_t _port_addr(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
|
||||
return port_addr;
|
||||
}
|
||||
|
||||
int gpio_init(gpio_t pin, gpio_dir_t dir, gpio_pp_t pullup)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
const uint32_t sysctl_port_base = _sysctl_port_base[port_num];
|
||||
const unsigned long pin_bit = 1 << pin_num;
|
||||
|
||||
DEBUG("Init GPIO: port %c, %d\n", 'A' + port_num, pin_num);
|
||||
DEBUG("Sysctl %" PRIx32 "\n", sysctl_port_base);
|
||||
|
||||
ROM_SysCtlPeripheralEnable(sysctl_port_base);
|
||||
|
||||
HWREG(port_addr+GPIO_LOCK_R_OFF) = GPIO_LOCK_KEY;
|
||||
HWREG(port_addr+GPIO_CR_R_OFF) |= pin_bit;
|
||||
HWREG(port_addr+GPIO_DEN_R_OFF) |= pin_bit;
|
||||
HWREG(port_addr+GPIO_LOCK_R_OFF) = 0;
|
||||
|
||||
ROM_GPIOPadConfigSet(port_addr, pin_bit,
|
||||
GPIO_STRENGTH_2MA, pullup);
|
||||
ROM_GPIODirModeSet(port_addr, pin_bit, dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _isr_gpio(uint32_t port_num){
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
uint32_t isr = ROM_GPIOPinIntStatus(port_addr, true);
|
||||
uint8_t i;
|
||||
|
||||
ROM_GPIOPinIntClear(port_addr, isr);
|
||||
|
||||
for (i=0; i<8; i++, isr>>=1) {
|
||||
if ((isr & 0x1) == 0){
|
||||
continue;
|
||||
}
|
||||
if (gpio_config[port_num][i].cb){
|
||||
gpio_config[port_num][i].cb(gpio_config[port_num][i].arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void isr_gpio_porta(void){
|
||||
_isr_gpio(0);
|
||||
}
|
||||
|
||||
void isr_gpio_portb(void){
|
||||
_isr_gpio(1);
|
||||
}
|
||||
|
||||
void isr_gpio_portc(void){
|
||||
_isr_gpio(2);
|
||||
}
|
||||
|
||||
void isr_gpio_portd(void){
|
||||
_isr_gpio(3);
|
||||
}
|
||||
|
||||
void isr_gpio_porte(void){
|
||||
_isr_gpio(4);
|
||||
}
|
||||
|
||||
void isr_gpio_portf(void){
|
||||
_isr_gpio(5);
|
||||
}
|
||||
|
||||
int gpio_init_int(gpio_t pin, gpio_pp_t pullup, gpio_flank_t flank,
|
||||
gpio_cb_t cb, void *arg)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint32_t icr_reg_addr = port_addr + GPIO_ICR_R_OFF;
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
const uint8_t pin_bit = 1<<pin_num;
|
||||
const unsigned int int_num = _int_assign[port_num];
|
||||
const uint32_t sysctl_port_base = _sysctl_port_base[port_num];
|
||||
|
||||
ROM_SysCtlPeripheralEnable(sysctl_port_base);
|
||||
gpio_config[port_num][pin_num].cb = cb;
|
||||
gpio_config[port_num][pin_num].arg = arg;
|
||||
|
||||
DEBUG("init int pin:%d, int num %d, port addr %" PRIx32 "\n",
|
||||
pin_num, int_num, port_addr);
|
||||
|
||||
ROM_GPIODirModeSet(port_addr, 1<<pin_num, GPIO_DIR_MODE_IN);
|
||||
ROM_GPIOPadConfigSet(port_addr, 1<<pin_num,
|
||||
GPIO_STRENGTH_2MA, pullup);
|
||||
|
||||
ROM_IntMasterDisable();
|
||||
|
||||
HWREG(icr_reg_addr) = pin_bit;
|
||||
|
||||
ROM_GPIOIntTypeSet(port_addr, pin_bit, flank);
|
||||
|
||||
HWREG(port_addr+GPIO_LOCK_R_OFF) = GPIO_LOCK_KEY;
|
||||
HWREG(port_addr+GPIO_CR_R_OFF) |= pin_bit;
|
||||
HWREG(port_addr+GPIO_DEN_R_OFF) |= pin_bit;
|
||||
HWREG(port_addr+GPIO_LOCK_R_OFF) = 0;
|
||||
|
||||
gpio_irq_enable(pin);
|
||||
ROM_IntEnable(int_num);
|
||||
|
||||
ROM_IntMasterEnable();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint32_t im_reg_addr = port_addr + GPIO_IM_R_OFF;
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
const uint8_t pin_bit = 1<<pin_num;
|
||||
|
||||
HWREG(im_reg_addr) |= pin_bit;
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint32_t im_reg_addr = port_addr + GPIO_IM_R_OFF;
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
const uint8_t pin_bit = 1<<pin_num;
|
||||
|
||||
HWREG(im_reg_addr) &= ~(pin_bit);
|
||||
}
|
||||
|
||||
|
||||
int gpio_read(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
|
||||
return HWREG(port_addr + ((1<<pin_num) << 2)) != 0;
|
||||
}
|
||||
|
||||
void gpio_set(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
DEBUG("Setting bit %d of port %c\n", pin_num, 'A' + port_num);
|
||||
DEBUG("Port addr %" PRIx32 ", vs %x\n", port_addr, GPIO_PORTF_BASE);
|
||||
ROM_GPIOPinWrite(port_addr, 1<<pin_num, 1<<pin_num);
|
||||
}
|
||||
|
||||
void gpio_clear(gpio_t pin)
|
||||
{
|
||||
const uint8_t port_num = _port_num(pin);
|
||||
const uint32_t port_addr = _port_base[port_num];
|
||||
const uint8_t pin_num = _pin_num(pin);
|
||||
|
||||
HWREG(port_addr + ((1<<pin_num) << 2)) = 0;
|
||||
}
|
||||
|
||||
void gpio_toggle(gpio_t pin)
|
||||
{
|
||||
if (gpio_read(pin)) {
|
||||
gpio_clear(pin);
|
||||
}
|
||||
else {
|
||||
gpio_set(pin);
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_write(gpio_t pin, int value)
|
||||
{
|
||||
if (value) {
|
||||
gpio_set(pin);
|
||||
}
|
||||
else {
|
||||
gpio_clear(pin);
|
||||
}
|
||||
}
|
@ -73,6 +73,37 @@ extern "C" {
|
||||
#define WATCHDOG1_TEST_R (*((volatile unsigned long *)0x40001418))
|
||||
#define WATCHDOG1_LOCK_R (*((volatile unsigned long *)0x40001C00))
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// GPIO registers offset
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define GPIO_DATA_R_OFF (0x3FCUL)
|
||||
#define GPIO_DIR_R_OFF (0x400UL)
|
||||
#define GPIO_IS_R_OFF (0x404UL)
|
||||
#define GPIO_IBE_R_OFF (0x408UL)
|
||||
#define GPIO_IEV_R_OFF (0x40CUL)
|
||||
#define GPIO_IM_R_OFF (0x410UL)
|
||||
#define GPIO_RIS_R_OFF (0x414UL)
|
||||
#define GPIO_MIS_R_OFF (0x418UL)
|
||||
#define GPIO_ICR_R_OFF (0x41CUL)
|
||||
#define GPIO_AFSEL_R_OFF (0x420UL)
|
||||
#define GPIO_DR2R_R_OFF (0x500UL)
|
||||
#define GPIO_DR4R_R_OFF (0x504UL)
|
||||
#define GPIO_DR8R_R_OFF (0x508UL)
|
||||
#define GPIO_ODR_R_OFF (0x50CUL)
|
||||
#define GPIO_PUR_R_OFF (0x510UL)
|
||||
#define GPIO_PDR_R_OFF (0x514UL)
|
||||
#define GPIO_SLR_R_OFF (0x518UL)
|
||||
#define GPIO_DEN_R_OFF (0x51CUL)
|
||||
#define GPIO_LOCK_R_OFF (0x520UL)
|
||||
#define GPIO_CR_R_OFF (0x524UL)
|
||||
#define GPIO_AMSEL_R_OFF (0x528UL)
|
||||
#define GPIO_PCTL_R_OFF (0x52CUL)
|
||||
#define GPIO_ADCCTL_R_OFF (0x530UL)
|
||||
#define GPIO_DMACTL_R_OFF (0x534UL)
|
||||
#define GPIO_SI_R_OFF (0x538UL)
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// GPIO registers (PORTA)
|
||||
|
Loading…
Reference in New Issue
Block a user