-
Home
-
doc
-
support
-
driver
-
gpio
gpio_pic32.c
View on Github
/**
* @file gpio_pic32.c
* @author Sebastien CAUX (sebcaux)
* @copyright Robotips 2016-2017
* @copyright UniSwarm 2018-2023
*
* @date June 6, 2017, 11:02 AM
*
* @brief GPIO support driver for PIC32MM, PIC32MK, PIC32MX,
* PIC32MZDA, PIC32MZEC and PIC32MZEF
*
* Implementation based on Microchip document DS60001120F :
* http://ww1.microchip.com/downloads/en/DeviceDoc/60001120F.pdf
*/
#include "gpio.h"
#include <archi.h>
#include <driver/int.h>
struct gpio_dev
{
void (*handler)(uint32_t);
};
#ifdef UDEVKIT_HAVE_CONFIG
# include "udevkit_config.h"
#endif
#ifndef INT_MODE
# define INT_MODE INT_DEFAULT_MODE
#endif
#ifndef GPIO_INTERRUPT_PRIORITY
# define GPIO_INTERRUPT_PRIORITY 5
#endif
#ifndef GPIOA_INT_PRIORITY
# define GPIOA_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOB_INT_PRIORITY
# define GPIOB_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOC_INT_PRIORITY
# define GPIOC_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOD_INT_PRIORITY
# define GPIOD_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOE_INT_PRIORITY
# define GPIOE_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOF_INT_PRIORITY
# define GPIOF_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOG_INT_PRIORITY
# define GPIOG_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOH_INT_PRIORITY
# define GPIOH_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOI_INT_PRIORITY
# define GPIOI_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOJ_INT_PRIORITY
# define GPIOJ_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
#ifndef GPIOK_INT_PRIORITY
# define GPIOK_INT_PRIORITY GPIO_INTERRUPT_PRIORITY
#endif
static struct gpio_dev _gpios[] = {
#if GPIO_PORT_MAX >= 1
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 2
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 3
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 4
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 5
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 6
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 7
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 8
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 9
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 10
{.handler = NULL},
#endif
#if GPIO_PORT_MAX >= 11
{.handler = NULL},
#endif
};
#if defined(GPIO_HAVE_PORTA) && !defined(GPIOA_DISABLE)
void CNAInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTB) && !defined(GPIOB_DISABLE)
void CNBInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTC) && !defined(GPIOC_DISABLE)
void CNCInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTD) && !defined(GPIOD_DISABLE)
void CNDInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTE) && !defined(GPIOE_DISABLE)
void CNEInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTF) && !defined(GPIOF_DISABLE)
void CNFInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTG) && !defined(GPIOG_DISABLE)
void CNGInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTH) && !defined(GPIOH_DISABLE)
void CNHInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTI) && !defined(GPIOI_DISABLE)
void CNIInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTJ) && !defined(GPIOJ_DISABLE)
void CNJInterrupt(void);
#endif
#if defined(GPIO_HAVE_PORTK) && !defined(GPIOK_DISABLE)
void CNKInterrupt(void);
#endif
/**
* @brief Set a bit of a GPIO to 1 (HIGH)
* @param device GPIO pin
*/
void gpio_setBit(rt_dev_t device)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t bit = 1 << (device & GPIO_MAX_PORTWIDTHMASK);
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
LATASET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
LATBSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
LATCSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
LATDSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
LATESET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
LATFSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
LATGSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
LATHSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
LATISET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
LATJSET = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
LATKSET = bit;
break;
#endif
}
}
/**
* @brief Set a bit of a GPIO to 0 (LOW)
* @param device GPIO pin
*/
void gpio_clearBit(rt_dev_t device)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t bit = 1 << (device & GPIO_MAX_PORTWIDTHMASK);
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
LATACLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
LATBCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
LATCCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
LATDCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
LATECLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
LATFCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
LATGCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
LATHCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
LATICLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
LATJCLR = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
LATKCLR = bit;
break;
#endif
}
}
/**
* @brief Toggle (invert) a bit of a GPIO from 1 to 0 or from 0 to 1
* @param device GPIO pin
*/
void gpio_toggleBit(rt_dev_t device)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t bit = 1 << (device & GPIO_MAX_PORTWIDTHMASK);
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
LATAINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
LATBINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
LATCINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
LATDINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
LATEINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
LATFINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
LATGINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
LATHINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
LATIINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
LATJINV = bit;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
LATKINV = bit;
break;
#endif
}
}
/**
* @brief Write a specific value of a bit of a GPIO
* @param device GPIO pin
* @param value value to set (GPIO_LOW / GPIO_HIGH / GPIO_TOGGLE)
*/
void gpio_writeBit(rt_dev_t device, GPIO_VALUE value)
{
switch (value)
{
case GPIO_LOW:
gpio_clearBit(device);
break;
case GPIO_HIGH:
gpio_setBit(device);
break;
case GPIO_TOGGLE:
gpio_toggleBit(device);
break;
}
}
/**
* @brief Read a bit of a GPIO
* @param device GPIO pin
* @return current value of the bit(GPIO_LOW / GPIO_HIGH)
*/
GPIO_VALUE gpio_readBit(rt_dev_t device)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t mbit = 1 << (device & GPIO_MAX_PORTWIDTHMASK);
uint16_t value = 0;
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
value = PORTA;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
value = PORTB;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
value = PORTC;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
value = PORTD;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
value = PORTE;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
value = PORTF;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
value = PORTG;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
value = PORTH;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
value = PORTI;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
value = PORTJ;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
value = PORTK;
break;
#endif
}
if ((value & mbit) == 0)
{
return GPIO_LOW;
}
return GPIO_HIGH;
}
/**
* @brief Set GPIO bit configuration (input / output / open-drain / pull-up / pull-down)
* @param device GPIO pin
* @param config pin configuration to set (GPIO_OUTPUT / GPIO_INPUT / GPIO_OPENDRAIN
* / GPIO_PULLUP / GPIO_PULLDOWN)
* @return 0 if ok, -1 in case of error
*/
int gpio_setBitConfig(rt_dev_t device, uint16_t config)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t bit = 1 << (device & GPIO_MAX_PORTWIDTHMASK);
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
if (config & GPIO_OUTPUT)
{
TRISACLR = bit; // set as output
}
else
{
TRISASET = bit; // set as input
}
if (config & GPIO_OPENDRAIN)
{
ODCASET = bit; // enable open drain
}
else
{
ODCACLR = bit; // disable open drain
}
# ifdef CNPUA
if (config & GPIO_PULLUP)
{
CNPUASET = bit; // enable pull-up
}
else
{
CNPUACLR = bit; // disable pull-up
}
# endif
# ifdef CNPDA
if (config & GPIO_PULLDOWN)
{
CNPDASET = bit; // enable pull-down
}
else
{
CNPDACLR = bit; // disable pull-down
}
# endif
# ifdef CNENA
if (config & GPIO_CNPOSITIVE)
{
CNENASET = bit; // enable positive edge detection
}
else
{
CNENACLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEA
if (config & GPIO_CNNEGATIVE)
{
CNNEASET = bit; // enable negative edge detection
}
else
{
CNNEACLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
if (config & GPIO_OUTPUT)
{
TRISBCLR = bit; // set as output
}
else
{
TRISBSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCBSET = bit; // enable open drain
}
else
{
ODCBCLR = bit; // disable open drain
}
# ifdef CNPUB
if (config & GPIO_PULLUP)
{
CNPUBSET = bit; // enable pull-up
}
else
{
CNPUBCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDB
if (config & GPIO_PULLDOWN)
{
CNPDBSET = bit; // enable pull-down
}
else
{
CNPDBCLR = bit; // disable pull-down
}
# endif
# ifdef CNENB
if (config & GPIO_CNPOSITIVE)
{
CNENBSET = bit; // enable positive edge detection
}
else
{
CNENBCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEB
if (config & GPIO_CNNEGATIVE)
{
CNNEBSET = bit; // enable negative edge detection
}
else
{
CNNEBCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
if (config & GPIO_OUTPUT)
{
TRISCCLR = bit; // set as output
}
else
{
TRISCSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCCSET = bit; // enable open drain
}
else
{
ODCCCLR = bit; // disable open drain
}
# ifdef CNPUC
if (config & GPIO_PULLUP)
{
CNPUCSET = bit; // enable pull-up
}
else
{
CNPUCCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDC
if (config & GPIO_PULLDOWN)
{
CNPDCSET = bit; // enable pull-down
}
else
{
CNPDCCLR = bit; // disable pull-down
}
# endif
# ifdef CNENC
if (config & GPIO_CNPOSITIVE)
{
CNENCSET = bit; // enable positive edge detection
}
else
{
CNENCCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEC
if (config & GPIO_CNNEGATIVE)
{
CNNECSET = bit; // enable negative edge detection
}
else
{
CNNECCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
if (config & GPIO_OUTPUT)
{
TRISDCLR = bit; // set as output
}
else
{
TRISDSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCDSET = bit; // enable open drain
}
else
{
ODCDCLR = bit; // disable open drain
}
# ifdef CNPUD
if (config & GPIO_PULLUP)
{
CNPUDSET = bit; // enable pull-up
}
else
{
CNPUDCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDD
if (config & GPIO_PULLDOWN)
{
CNPDDSET = bit; // enable pull-down
}
else
{
CNPDDCLR = bit; // disable pull-down
}
# endif
# ifdef CNEND
if (config & GPIO_CNPOSITIVE)
{
CNENDSET = bit; // enable positive edge detection
}
else
{
CNENDCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNED
if (config & GPIO_CNNEGATIVE)
{
CNNEDSET = bit; // enable negative edge detection
}
else
{
CNNEDCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
if (config & GPIO_OUTPUT)
{
TRISECLR = bit; // set as output
}
else
{
TRISESET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCESET = bit; // enable open drain
}
else
{
ODCECLR = bit; // disable open drain
}
# ifdef CNPUE
if (config & GPIO_PULLUP)
{
CNPUESET = bit; // enable pull-up
}
else
{
CNPUECLR = bit; // disable pull-up
}
# endif
# ifdef CNPDE
if (config & GPIO_PULLDOWN)
{
CNPDESET = bit; // enable pull-down
}
else
{
CNPDECLR = bit; // disable pull-down
}
# endif
# ifdef CNENE
if (config & GPIO_CNPOSITIVE)
{
CNENESET = bit; // enable positive edge detection
}
else
{
CNENECLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEE
if (config & GPIO_CNNEGATIVE)
{
CNNEESET = bit; // enable negative edge detection
}
else
{
CNNEECLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
if (config & GPIO_OUTPUT)
{
TRISFCLR = bit; // set as output
}
else
{
TRISFSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCFSET = bit; // enable open drain
}
else
{
ODCFCLR = bit; // disable open drain
}
# ifdef CNPUF
if (config & GPIO_PULLUP)
{
CNPUFSET = bit; // enable pull-up
}
else
{
CNPUFCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDF
if (config & GPIO_PULLDOWN)
{
CNPDFSET = bit; // enable pull-down
}
else
{
CNPDFCLR = bit; // disable pull-down
}
# endif
# ifdef CNENF
if (config & GPIO_CNPOSITIVE)
{
CNENFSET = bit; // enable positive edge detection
}
else
{
CNENFCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEF
if (config & GPIO_CNNEGATIVE)
{
CNNEFSET = bit; // enable negative edge detection
}
else
{
CNNEFCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
if (config & GPIO_OUTPUT)
{
TRISGCLR = bit; // set as output
}
else
{
TRISGSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCGSET = bit; // enable open drain
}
else
{
ODCGCLR = bit; // disable open drain
}
# ifdef CNPUG
if (config & GPIO_PULLUP)
{
CNPUGSET = bit; // enable pull-up
}
else
{
CNPUGCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDG
if (config & GPIO_PULLDOWN)
{
CNPDGSET = bit; // enable pull-down
}
else
{
CNPDGCLR = bit; // disable pull-down
}
# endif
# ifdef CNENG
if (config & GPIO_CNPOSITIVE)
{
CNENGSET = bit; // enable positive edge detection
}
else
{
CNENGCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEG
if (config & GPIO_CNNEGATIVE)
{
CNNEGSET = bit; // enable negative edge detection
}
else
{
CNNEGCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
if (config & GPIO_OUTPUT)
{
TRISHCLR = bit; // set as output
}
else
{
TRISHSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCHSET = bit; // enable open drain
}
else
{
ODCHCLR = bit; // disable open drain
}
# ifdef CNPUH
if (config & GPIO_PULLUP)
{
CNPUHSET = bit; // enable pull-up
}
else
{
CNPUHCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDH
if (config & GPIO_PULLDOWN)
{
CNPDHSET = bit; // enable pull-down
}
else
{
CNPDHCLR = bit; // disable pull-down
}
# endif
# ifdef CNENH
if (config & GPIO_CNPOSITIVE)
{
CNENHSET = bit; // enable positive edge detection
}
else
{
CNENHCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEH
if (config & GPIO_CNNEGATIVE)
{
CNNEHSET = bit; // enable negative edge detection
}
else
{
CNNEHCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
if (config & GPIO_OUTPUT)
{
TRISICLR = bit; // set as output
}
else
{
TRISISET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCISET = bit; // enable open drain
}
else
{
ODCICLR = bit; // disable open drain
}
# ifdef CNPUI
if (config & GPIO_PULLUP)
{
CNPUISET = bit; // enable pull-up
}
else
{
CNPUICLR = bit; // disable pull-up
}
# endif
# ifdef CNPDI
if (config & GPIO_PULLDOWN)
{
CNPDISET = bit; // enable pull-down
}
else
{
CNPDICLR = bit; // disable pull-down
}
# endif
# ifdef CNENI
if (config & GPIO_CNPOSITIVE)
{
CNENISET = bit; // enable positive edge detection
}
else
{
CNENICLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEI
if (config & GPIO_CNNEGATIVE)
{
CNNEISET = bit; // enable negative edge detection
}
else
{
CNNEICLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
if (config & GPIO_OUTPUT)
{
TRISJCLR = bit; // set as output
}
else
{
TRISJSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCJSET = bit; // enable open drain
}
else
{
ODCJCLR = bit; // disable open drain
}
# ifdef CNPUJ
if (config & GPIO_PULLUP)
{
CNPUJSET = bit; // enable pull-up
}
else
{
CNPUJCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDJ
if (config & GPIO_PULLDOWN)
{
CNPDJSET = bit; // enable pull-down
}
else
{
CNPDJCLR = bit; // disable pull-down
}
# endif
# ifdef CNENJ
if (config & GPIO_CNPOSITIVE)
{
CNENJSET = bit; // enable positive edge detection
}
else
{
CNENJCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEJ
if (config & GPIO_CNNEGATIVE)
{
CNNEJSET = bit; // enable negative edge detection
}
else
{
CNNEJCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
if (config & GPIO_OUTPUT)
{
TRISKCLR = bit; // set as output
}
else
{
TRISKSET = bit; // set as input;
}
if (config & GPIO_OPENDRAIN)
{
ODCKSET = bit; // enable open drain
}
else
{
ODCKCLR = bit; // disable open drain
}
# ifdef CNPUK
if (config & GPIO_PULLUP)
{
CNPUKSET = bit; // enable pull-up
}
else
{
CNPUKCLR = bit; // disable pull-up
}
# endif
# ifdef CNPDK
if (config & GPIO_PULLDOWN)
{
CNPDKSET = bit; // enable pull-down
}
else
{
CNPDKCLR = bit; // disable pull-down
}
# endif
# ifdef CNENK
if (config & GPIO_CNPOSITIVE)
{
CNENKSET = bit; // enable positive edge detection
}
else
{
CNENKCLR = bit; // disable positive edge detection
}
# endif
# ifdef CNNEK
if (config & GPIO_CNNEGATIVE)
{
CNNEKSET = bit; // enable negative edge detection
}
else
{
CNNEKCLR = bit; // disable negative edge detection
}
# endif
break;
#endif
default:
return -1;
}
return 0;
}
/**
* @brief Set GPIO port value (complete port)
* @param device GPIO port
* @param value to set
*/
void gpio_writePort(rt_dev_t device, port_type value)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
LATA = value;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
LATB = value;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
LATC = value;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
LATD = value;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
LATE = value;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
LATF = value;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
LATG = value;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
LATH = value;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
LATI = value;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
LATJ = value;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
LATK = value;
break;
#endif
}
}
/**
* @brief Read GPIO port value (complete port)
* @param device GPIO port
* @return current value of port
*/
port_type gpio_readPort(rt_dev_t device)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
return PORTA;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
return PORTB;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
return PORTC;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
return PORTD;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
return PORTE;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
return PORTF;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
return PORTG;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
return PORTH;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
return PORTI;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
return PORTJ;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
return PORTK;
#endif
}
return 0;
}
/**
* @brief Set GPIO port configuration (input / output)
* @param device GPIO port
* @param config port configuration to set (GPIO_OUTPUT / GPIO_INPUT)
* @return 0 if ok, -1 in case of error
*/
int gpio_setPortConfig(rt_dev_t device, uint16_t config)
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
uint16_t trisValue;
if (config & GPIO_OUTPUT)
{
trisValue = 0x0000;
}
else
{
trisValue = 0xFFFF;
}
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
TRISA = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
TRISB = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
TRISC = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
TRISD = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
TRISE = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
TRISF = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
TRISG = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
TRISH = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
TRISI = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
TRISJ = trisValue;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
TRISK = trisValue;
break;
#endif
default:
return -1;
}
return 0;
}
int gpio_setChangeHandler(rt_dev_t device, void (*handler)(GPIO_VALUE))
{
uint8_t port = MINOR(device) >> GPIO_MAX_PORTWIDTHU;
_gpios[port].handler = handler;
int on = 0;
if (handler != NULL)
{
on = 1;
}
switch (port)
{
#ifdef GPIO_HAVE_PORTA
case 0:
CNCONAbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONAbits.EDGEDETECT = 1;
CNFA = 0;
# endif
_CNAIF = 0;
_CNAIP = GPIOA_INT_PRIORITY;
_CNAIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTB
case 1:
CNCONBbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONBbits.EDGEDETECT = 1;
CNFB = 0;
# endif
_CNBIF = 0;
_CNBIP = GPIOB_INT_PRIORITY;
_CNBIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTC
case 2:
CNCONCbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONCbits.EDGEDETECT = 1;
CNFC = 0;
# endif
_CNCIF = 0;
_CNCIP = GPIOC_INT_PRIORITY;
_CNCIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTD
case 3:
CNCONDbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONDbits.EDGEDETECT = 1;
CNFD = 0;
# endif
_CNDIF = 0;
_CNDIP = GPIOD_INT_PRIORITY;
_CNDIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTE
case 4:
CNCONEbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONEbits.EDGEDETECT = 1;
CNFE = 0;
# endif
_CNEIF = 0;
_CNEIP = GPIOE_INT_PRIORITY;
_CNEIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTF
case 5:
CNCONFbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONFbits.EDGEDETECT = 1;
CNFF = 0;
# endif
_CNFIF = 0;
_CNFIP = GPIOF_INT_PRIORITY;
_CNFIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTG
case 6:
CNCONGbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONGbits.EDGEDETECT = 1;
CNFG = 0;
# endif
_CNGIF = 0;
_CNGIP = GPIOG_INT_PRIORITY;
_CNGIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTH
case 7:
CNCONHbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONHbits.EDGEDETECT = 1;
CNFH = 0;
# endif
_CNHIF = 0;
_CNHIP = GPIOH_INT_PRIORITY;
_CNHIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTI
case 8:
CNCONIbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONIbits.EDGEDETECT = 1;
CNFI = 0;
# endif
_CNIIF = 0;
_CNIIP = GPIOI_INT_PRIORITY;
_CNIIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTJ
case 9:
CNCONJbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONJbits.EDGEDETECT = 1;
CNFJ = 0;
# endif
_CNJIF = 0;
_CNJIP = GPIOJ_INT_PRIORITY;
_CNJIE = on;
break;
#endif
#ifdef GPIO_HAVE_PORTK
case 10:
CNCONKbits.ON = on;
# ifndef GPIO_CN_NOEDGEDETECT
CNCONKbits.EDGEDETECT = 1;
CNFK = 0;
# endif
_CNKIF = 0;
_CNKIP = GPIOK_INT_PRIORITY;
_CNKIE = on;
break;
#endif
default:
return -1;
}
return 0;
}
#if defined(GPIO_HAVE_PORTA) && !defined(GPIOA_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_A_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNAInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATA;
# else
uint32_t change_mask = CNFA;
# endif
if (_gpios[GPIO_PORTA].handler != NULL)
{
(*_gpios[GPIO_PORTA].handler)(change_mask);
}
PORTA;
# ifndef GPIO_CN_NOEDGEDETECT
CNFA = 0;
# endif
_CNAIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTB) && !defined(GPIOB_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_B_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNBInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATB;
# else
uint32_t change_mask = CNFB;
# endif
if (_gpios[GPIO_PORTB].handler != NULL)
{
(*_gpios[GPIO_PORTB].handler)(change_mask);
}
PORTB;
# ifndef GPIO_CN_NOEDGEDETECT
CNFB = 0;
# endif
_CNBIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTC) && !defined(GPIOC_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_C_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNCInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATC;
# else
uint32_t change_mask = CNFC;
# endif
if (_gpios[GPIO_PORTC].handler != NULL)
{
(*_gpios[GPIO_PORTC].handler)(change_mask);
}
PORTC;
# ifndef GPIO_CN_NOEDGEDETECT
CNFC = 0;
# endif
_CNCIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTD) && !defined(GPIOD_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_D_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNDInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATD;
# else
uint32_t change_mask = CNFD;
# endif
if (_gpios[GPIO_PORTD].handler != NULL)
{
(*_gpios[GPIO_PORTD].handler)(change_mask);
}
PORTD;
# ifndef GPIO_CN_NOEDGEDETECT
CNFD = 0;
# endif
_CNDIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTE) && !defined(GPIOE_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_E_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNEInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATE;
# else
uint32_t change_mask = CNFE;
# endif
if (_gpios[GPIO_PORTE].handler != NULL)
{
(*_gpios[GPIO_PORTE].handler)(change_mask);
}
PORTE;
# ifndef GPIO_CN_NOEDGEDETECT
CNFE = 0;
# endif
_CNEIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTF) && !defined(GPIOF_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_F_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNFInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATF;
# else
uint32_t change_mask = CNFF;
# endif
if (_gpios[GPIO_PORTF].handler != NULL)
{
(*_gpios[GPIO_PORTF].handler)(change_mask);
}
PORTF;
# ifndef GPIO_CN_NOEDGEDETECT
CNFF = 0;
# endif
_CNFIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTG) && !defined(GPIOG_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_G_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNGInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATG;
# else
uint32_t change_mask = CNFG;
# endif
if (_gpios[GPIO_PORTG].handler != NULL)
{
(*_gpios[GPIO_PORTG].handler)(change_mask);
}
PORTG;
# ifndef GPIO_CN_NOEDGEDETECT
CNFG = 0;
# endif
_CNGIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTH) && !defined(GPIOH_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_H_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNHInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATH;
# else
uint32_t change_mask = CNFH;
# endif
if (_gpios[GPIO_PORTH].handler != NULL)
{
(*_gpios[GPIO_PORTH].handler)(change_mask);
}
PORTH;
# ifndef GPIO_CN_NOEDGEDETECT
CNFH = 0;
# endif
_CNHIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTI) && !defined(GPIOI_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_I_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNIInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATI;
# else
uint32_t change_mask = CNFI;
# endif
if (_gpios[GPIO_PORTI].handler != NULL)
{
(*_gpios[GPIO_PORTI].handler)(change_mask);
}
PORTI;
# ifndef GPIO_CN_NOEDGEDETECT
CNFI = 0;
# endif
_CNIIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTJ) && !defined(GPIOJ_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_J_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNJInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATJ;
# else
uint32_t change_mask = CNFJ;
# endif
if (_gpios[GPIO_PORTJ].handler != NULL)
{
(*_gpios[GPIO_PORTJ].handler)(change_mask);
}
PORTJ;
# ifndef GPIO_CN_NOEDGEDETECT
CNFJ = 0;
# endif
_CNJIF = 0;
}
#endif
#if defined(GPIO_HAVE_PORTK) && !defined(GPIOK_DISABLE) && !defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_K_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNKInterrupt(void)
{
# ifdef GPIO_CN_NOEDGEDETECT
uint32_t change_mask = CNSTATK;
# else
uint32_t change_mask = CNFK;
# endif
if (_gpios[GPIO_PORTK].handler != NULL)
{
(*_gpios[GPIO_PORTK].handler)(change_mask);
}
PORTK;
# ifndef GPIO_CN_NOEDGEDETECT
CNFK = 0;
# endif
_CNKIF = 0;
}
#endif
#if defined(GPIO_CN_SINGLEINTERRUPT)
void INT_ISR(_CHANGE_NOTICE_VECTOR, GPIOI_INT_PRIORITY, INT_MODE) __attribute__((weak)) CNInterrupt(void)
{
// TODO
}
#endif