[realtek-ambz] Rework wiring_digital and WInterrupts

This commit is contained in:
Kuba Szczodrzyński
2022-04-23 22:18:32 +02:00
parent 1165218c0c
commit 7507e17677
4 changed files with 181 additions and 301 deletions

View File

@@ -1,39 +1,84 @@
#include "Arduino.h" #include "Arduino.h"
#ifdef __cplusplus
extern "C" {
#endif
#include "gpio_api.h"
#include "gpio_irq_api.h"
#include "gpio_irq_ex_api.h"
extern void *gpio_pin_struct[PINS_COUNT];
extern void *gpio_irq_handler_list[PINS_COUNT];
void gpioIrqHandler(uint32_t id, gpio_irq_event event) {
if (gpio_irq_handler_list[id] != NULL) {
((void (*)(uint32_t, uint32_t))gpio_irq_handler_list[id])(id, (uint32_t)event);
}
}
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) { void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
if ( g_APinDescription[interruptNumber].ulPinType != PIO_GPIO_IRQ ) { if (pinInvalid(interruptNumber))
pinRemoveMode(interruptNumber); return;
}
switch(mode) { gpio_irq_handler_list[interruptNumber] = callback;
case LOW:
pinMode(interruptNumber, INPUT_IRQ_LOW);
digitalSetIrqHandler(interruptNumber, (void *)callback);
break;
case HIGH: if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ &&
pinMode(interruptNumber, INPUT_IRQ_HIGH); g_APinDescription[interruptNumber].ulPinMode == mode)
digitalSetIrqHandler(interruptNumber, (void *)callback); // Nothing changes in pin mode
break; return;
case FALLING: if (g_APinDescription[interruptNumber].ulPinType != PIO_GPIO_IRQ)
pinMode(interruptNumber, INPUT_IRQ_FALL); // pin mode changes; deinit gpio and free memory
digitalSetIrqHandler(interruptNumber, (void *)callback); pinRemoveMode(interruptNumber);
break;
case RISING: gpio_irq_t *gpio;
pinMode(interruptNumber, INPUT_IRQ_RISE);
digitalSetIrqHandler(interruptNumber, (void *)callback);
break;
case CHANGE: if (g_APinDescription[interruptNumber].ulPinType == NOT_INITIAL) {
// TODO // allocate memory if pin not used before
break; gpio = malloc(sizeof(gpio_irq_t));
} gpio_pin_struct[interruptNumber] = gpio;
gpio_irq_init(gpio, g_APinDescription[interruptNumber].pinname, gpioIrqHandler, interruptNumber);
g_APinDescription[interruptNumber].ulPinType = PIO_GPIO_IRQ;
} else {
// pin already used as irq
gpio = (gpio_irq_t *)gpio_pin_struct[interruptNumber];
}
g_APinDescription[interruptNumber].ulPinMode = mode;
gpio_irq_event event;
switch (mode) {
case LOW:
event = IRQ_LOW;
break;
case HIGH:
event = IRQ_HIGH;
break;
case FALLING:
event = IRQ_FALL;
break;
case RISING:
event = IRQ_RISE;
break;
default:
return;
}
gpio_irq_set(gpio, event, 1);
gpio_irq_enable(gpio);
} }
void detachInterrupt(pin_size_t interruptNumber) { void detachInterrupt(pin_size_t interruptNumber) {
if ( g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ ) { if (pinInvalid(interruptNumber))
pinRemoveMode(interruptNumber); return;
}
if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ) {
pinRemoveMode(interruptNumber);
}
gpio_irq_handler_list[interruptNumber] = NULL;
} }
#ifdef __cplusplus
}
#endif

View File

@@ -40,30 +40,6 @@ extern void yield(void);
#define sprintf rtl_sprintf #define sprintf rtl_sprintf
#endif #endif
/*
extern void *pvPortMalloc( size_t xWantedSize );
extern void vPortFree( void *pv );
extern void *pvPortReAlloc( void *pv, size_t xWantedSize );
extern size_t xPortGetFreeHeapSize( void );
extern size_t xPortGetMinimumEverFreeHeapSize( void );
extern void *tcm_heap_malloc(int size);
extern void *tcm_heap_calloc(int size);
extern void tcm_heap_free(void * mem);
extern void tcm_heap_dump(void);
extern int tcm_heap_freeSpace(void);
#ifndef malloc
#define malloc pvPortMalloc
#endif
#ifndef free
#define free vPortFree
#endif
#ifndef realloc
#define realloc pvPortReAlloc
#endif
*/
#define NOT_INITIAL (1UL<<0) #define NOT_INITIAL (1UL<<0)
#define PIO_GPIO (1UL<<1) #define PIO_GPIO (1UL<<1)
#define PIO_PWM (1UL<<2) #define PIO_PWM (1UL<<2)
@@ -78,32 +54,26 @@ extern int tcm_heap_freeSpace(void);
/* Types used for the tables below */ /* Types used for the tables below */
typedef struct _PinDescription typedef struct _PinDescription
{ {
// HW PinNames // HW PinNames
uint32_t pinname; uint32_t pinname;
// Current Pin Type // Current Pin Type
uint32_t ulPinType; uint32_t ulPinType;
// Supported Pin Function // Supported Pin Function
uint32_t ulPinAttribute; uint32_t ulPinAttribute;
// Current Pin Mode // Current Pin Mode
uint32_t ulPinMode; uint32_t ulPinMode;
} PinDescription ; } PinDescription ;
/* Pins table to be instanciated into variant.cpp */ /* Pins table to be instanciated into variant.cpp */
extern PinDescription g_APinDescription[]; extern PinDescription g_APinDescription[];
extern bool pinInvalid(pin_size_t pinNumber);
extern void pinRemoveMode(pin_size_t pinNumber);
/* moved from wiring_digital.h */ /* moved from wiring_digital.h */
extern void digitalChangeDir( uint32_t ulPin, uint8_t direction);
/**************************** Extend API by RTK ***********************************/ /**************************** Extend API by RTK ***********************************/
extern uint32_t digitalPinToPort( uint32_t ulPin ); extern uint32_t digitalPinToPort( uint32_t pinNumber );
extern uint32_t digitalPinToBitMask( uint32_t ulPin ); extern uint32_t digitalPinToBitMask( uint32_t pinNumber );
extern uint32_t digitalSetIrqHandler( uint32_t ulPin, void (*handler)(uint32_t id, uint32_t event) );
extern uint32_t digitalClearIrqHandler( uint32_t ulPin );
extern void pinRemoveMode(uint32_t ulPin);
/* moved from wiring_analog.h */ /* moved from wiring_analog.h */
/* /*
@@ -122,23 +92,9 @@ extern void analogOutputInit( void ) ;
extern void analogWritePeriod(int us); extern void analogWritePeriod(int us);
/* moved from wiring_constants.h */ /* moved from wiring_constants.h */
// TODO use these correctly in wiring
// #define INPUT_PULLDOWN INPUT
// #define INPUT_PULLNONE 0x03
#define INPUT_IRQ_FALL 0x05
#define INPUT_IRQ_RISE 0x06
#define INPUT_IRQ_LOW 0x07
#define INPUT_IRQ_HIGH 0x08
#define DEFAULT 1 #define DEFAULT 1
#define EXTERNAL 0 #define EXTERNAL 0
// undefine stdlib's abs if encountered
/* #ifdef abs
#undef abs
#endif // abs
#define abs(x) ((x)>0?(x):-(x)) */
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );

View File

@@ -1,21 +1,3 @@
/*
Copyright (c) 2011 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "Arduino.h" #include "Arduino.h"
#ifdef __cplusplus #ifdef __cplusplus
@@ -30,234 +12,131 @@ extern "C" {
extern void *gpio_pin_struct[PINS_COUNT]; extern void *gpio_pin_struct[PINS_COUNT];
extern void *gpio_irq_handler_list[PINS_COUNT]; extern void *gpio_irq_handler_list[PINS_COUNT];
void gpioIrqHandler(uint32_t id, gpio_irq_event event) { bool pinInvalid(pin_size_t pinNumber) {
if ( gpio_irq_handler_list[id] != NULL ) { return pinNumber < 0 || pinNumber > PINS_COUNT || g_APinDescription[pinNumber].pinname == NC;
( (void (*)(uint32_t,uint32_t) )gpio_irq_handler_list[id] ) ( id, (uint32_t)event );
}
} }
void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) void pinRemoveMode(pin_size_t pinNumber) {
{ if (pinInvalid(pinNumber))
void *pGpio_t; return;
if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) {
if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) ) pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
{ pwmout_free(obj);
// Invalid pin }
return; if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO) {
} gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_deinit(obj, g_APinDescription[pinNumber].pinname);
if ( (g_APinDescription[pinNumber].ulPinType == PIO_GPIO || g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) free(obj);
&& g_APinDescription[pinNumber].ulPinMode == pinMode) }
{ if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) {
// Nothing changes in pin mode gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber];
return; gpio_irq_deinit(obj);
} free(obj);
}
if ( g_APinDescription[pinNumber].ulPinType == PIO_PWM ) { gpio_pin_struct[pinNumber] = NULL;
// If this pin has been configured as PWM, then it cannot change to another mode g_APinDescription[pinNumber].ulPinType = NOT_INITIAL;
return; g_APinDescription[pinNumber].ulPinMode = NOT_INITIAL;
}
if ( g_APinDescription[pinNumber].ulPinType == PIO_GPIO &&
(pinMode == INPUT_IRQ_FALL || pinMode == INPUT_IRQ_RISE) ) {
// Pin mode changes from gpio_t to gpio_irq_t
pinRemoveMode(pinNumber);
}
if ( g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ &&
(pinMode == INPUT || pinMode == OUTPUT || pinMode == INPUT_PULLUP || pinMode == INPUT_PULLDOWN || pinMode == OUTPUT_OPENDRAIN) ) {
// Pin mode changes from gpio_irq_t to gpio_t
pinRemoveMode(pinNumber);
}
if ( g_APinDescription[pinNumber].ulPinType == NOT_INITIAL ) {
if (pinMode == INPUT_IRQ_FALL || pinMode == INPUT_IRQ_RISE || pinMode == INPUT_IRQ_LOW || pinMode == INPUT_IRQ_HIGH) {
gpio_pin_struct[pinNumber] = malloc ( sizeof(gpio_irq_t) );
pGpio_t = gpio_pin_struct[pinNumber];
gpio_irq_init( pGpio_t, g_APinDescription[pinNumber].pinname, gpioIrqHandler, pinNumber);
g_APinDescription[pinNumber].ulPinType = PIO_GPIO_IRQ;
} else {
gpio_pin_struct[pinNumber] = malloc ( sizeof(gpio_t) );
pGpio_t = gpio_pin_struct[pinNumber];
gpio_init( pGpio_t, g_APinDescription[pinNumber].pinname );
g_APinDescription[pinNumber].ulPinType = PIO_GPIO;
}
g_APinDescription[pinNumber].ulPinMode = pinMode;
} else {
pGpio_t = gpio_pin_struct[pinNumber];
}
switch ( pinMode )
{
case INPUT:
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
gpio_mode( (gpio_t *)pGpio_t, PullNone );
break;
case INPUT_PULLDOWN:
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
gpio_mode( (gpio_t *)pGpio_t, PullDown );
break;
case INPUT_PULLUP:
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
gpio_mode( (gpio_t *)pGpio_t, PullUp );
break;
case OUTPUT:
gpio_dir( (gpio_t *)pGpio_t, PIN_OUTPUT );
gpio_mode( (gpio_t *)pGpio_t, PullNone );
break;
case OUTPUT_OPENDRAIN:
gpio_dir( (gpio_t *)pGpio_t, PIN_OUTPUT );
gpio_mode( (gpio_t *)pGpio_t, OpenDrain );
break;
case INPUT_IRQ_FALL:
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_FALL, 1 );
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
break;
case INPUT_IRQ_RISE:
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_RISE, 1 );
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
break;
case INPUT_IRQ_LOW:
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_LOW, 1 );
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
break;
case INPUT_IRQ_HIGH:
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_HIGH, 1 );
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
break;
default:
break ;
}
} }
void digitalWrite(pin_size_t pinNumber, PinStatus status) void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) {
{ if (pinInvalid(pinNumber))
gpio_t *pGpio_t; return;
if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) ) if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO && g_APinDescription[pinNumber].ulPinMode == pinMode)
{ // Nothing changes in pin mode
return; return;
}
if ( g_APinDescription[pinNumber].ulPinType != PIO_GPIO ) /* if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) {
{ // If this pin has been configured as PWM, then it cannot change to another mode
return; return;
} } */
pGpio_t = (gpio_t *)gpio_pin_struct[pinNumber]; if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(pinNumber);
gpio_write( pGpio_t, status ); gpio_t *gpio;
if (g_APinDescription[pinNumber].ulPinType == NOT_INITIAL) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_t));
gpio_pin_struct[pinNumber] = gpio;
gpio_init(gpio, g_APinDescription[pinNumber].pinname);
g_APinDescription[pinNumber].ulPinType = PIO_GPIO;
} else {
// pin already used as gpio
gpio = (gpio_t *)gpio_pin_struct[pinNumber];
}
g_APinDescription[pinNumber].ulPinMode = pinMode;
PinDirection dir;
PinMode mode;
switch (pinMode) {
case INPUT:
dir = PIN_INPUT;
mode = PullNone;
break;
case INPUT_PULLDOWN:
dir = PIN_INPUT;
mode = PullDown;
break;
case INPUT_PULLUP:
dir = PIN_INPUT;
mode = PullUp;
break;
case OUTPUT:
dir = PIN_OUTPUT;
mode = PullNone;
break;
case OUTPUT_OPENDRAIN:
dir = PIN_OUTPUT;
mode = OpenDrain;
break;
default:
return;
}
gpio_dir(gpio, dir);
gpio_mode(gpio, mode);
} }
PinStatus digitalRead(pin_size_t pinNumber) void digitalWrite(pin_size_t pinNumber, PinStatus status) {
{ if (pinInvalid(pinNumber))
gpio_t *pGpio_t; return;
int pin_status; if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
return;
if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) )
{
return -1;
}
if ( g_APinDescription[pinNumber].ulPinType != PIO_GPIO ) gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
{ gpio_write(gpio, status);
return -1;
}
pGpio_t = (gpio_t *)gpio_pin_struct[pinNumber];
pin_status = gpio_read( pGpio_t );
return pin_status;
} }
void digitalChangeDir( uint32_t ulPin, uint8_t direction) PinStatus digitalRead(pin_size_t pinNumber) {
{ if (pinInvalid(pinNumber))
gpio_t *pGpio_t; return;
u32 RegValue; if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO)
return;
if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
{ return gpio_read(gpio);
return;
}
if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO )
{
return;
}
pGpio_t = (gpio_t *)gpio_pin_struct[ulPin];
gpio_dir( pGpio_t, direction );
} }
/**************************** Extend API by RTK ***********************************/ /**************************** Extend API by RTK ***********************************/
uint32_t digitalPinToPort( uint32_t ulPin ) uint32_t digitalPinToPort(uint32_t pinNumber) {
{ if (pinInvalid(pinNumber))
uint32_t pin_name; return 0xFFFFFFFF;
if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname);
{ return HAL_GPIO_GET_PORT_BY_NAME(pin_name);
return 0xFFFFFFFF;
}
pin_name = HAL_GPIO_GetPinName(g_APinDescription[ulPin].pinname);
return HAL_GPIO_GET_PORT_BY_NAME(pin_name);
} }
uint32_t digitalPinToBitMask( uint32_t ulPin ) uint32_t digitalPinToBitMask(uint32_t pinNumber) {
{ if (pinInvalid(pinNumber))
uint32_t pin_name; return 0xFFFFFFFF;
if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname);
{ return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name));
return 0xFFFFFFFF;
}
pin_name = HAL_GPIO_GetPinName(g_APinDescription[ulPin].pinname);
return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name));
}
uint32_t digitalSetIrqHandler( uint32_t ulPin, void (*handler)(uint32_t id, uint32_t event) ) {
gpio_irq_handler_list[ulPin] = (void *) handler;
}
uint32_t digitalClearIrqHandler( uint32_t ulPin ) {
gpio_irq_handler_list[ulPin] = NULL;
}
void pinRemoveMode(uint32_t ulPin) {
if ( g_APinDescription[ulPin].ulPinType == PIO_PWM ) {
// The PWM pin can only be disabled
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
// HAL_Pwm_Disable( &obj->pwm_hal_adp );
g_APinDescription[ulPin].ulPinMode = PWM_MODE_DISABLED;
}
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO ) {
gpio_deinit( (gpio_t *)gpio_pin_struct[ulPin], g_APinDescription[ulPin].pinname );
free ( (gpio_t *)gpio_pin_struct[ulPin] );
gpio_pin_struct[ulPin] = NULL;
g_APinDescription[ulPin].ulPinType = NOT_INITIAL;
g_APinDescription[ulPin].ulPinMode = NOT_INITIAL;
}
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ ) {
gpio_irq_deinit( (gpio_irq_t *)gpio_pin_struct[ulPin] );
free ( (gpio_irq_t *)gpio_pin_struct[ulPin] );
gpio_pin_struct[ulPin] = NULL;
g_APinDescription[ulPin].ulPinType = NOT_INITIAL;
g_APinDescription[ulPin].ulPinMode = NOT_INITIAL;
}
} }
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -15,8 +15,8 @@
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "variant.h"
#include "Arduino.h" #include "Arduino.h"
#include "variant.h"
#include "gpio_api.h" #include "gpio_api.h"
#ifdef __cplusplus #ifdef __cplusplus