From 7507e17677956429860c20f1b55cd539626c4253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kuba=20Szczodrzy=C5=84ski?= Date: Sat, 23 Apr 2022 22:18:32 +0200 Subject: [PATCH] [realtek-ambz] Rework wiring_digital and WInterrupts --- .../realtek-ambz/cores/arduino/WInterrupts.c | 99 ++++-- arduino/realtek-ambz/cores/arduino/WVariant.h | 54 +-- .../cores/arduino/wiring_digital.c | 327 ++++++------------ boards/wr3/variant.cpp | 2 +- 4 files changed, 181 insertions(+), 301 deletions(-) diff --git a/arduino/realtek-ambz/cores/arduino/WInterrupts.c b/arduino/realtek-ambz/cores/arduino/WInterrupts.c index 44db20e..934a380 100644 --- a/arduino/realtek-ambz/cores/arduino/WInterrupts.c +++ b/arduino/realtek-ambz/cores/arduino/WInterrupts.c @@ -1,39 +1,84 @@ #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) { - if ( g_APinDescription[interruptNumber].ulPinType != PIO_GPIO_IRQ ) { - pinRemoveMode(interruptNumber); - } + if (pinInvalid(interruptNumber)) + return; - switch(mode) { - case LOW: - pinMode(interruptNumber, INPUT_IRQ_LOW); - digitalSetIrqHandler(interruptNumber, (void *)callback); - break; + gpio_irq_handler_list[interruptNumber] = callback; - case HIGH: - pinMode(interruptNumber, INPUT_IRQ_HIGH); - digitalSetIrqHandler(interruptNumber, (void *)callback); - break; + if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ && + g_APinDescription[interruptNumber].ulPinMode == mode) + // Nothing changes in pin mode + return; - case FALLING: - pinMode(interruptNumber, INPUT_IRQ_FALL); - digitalSetIrqHandler(interruptNumber, (void *)callback); - break; + if (g_APinDescription[interruptNumber].ulPinType != PIO_GPIO_IRQ) + // pin mode changes; deinit gpio and free memory + pinRemoveMode(interruptNumber); - case RISING: - pinMode(interruptNumber, INPUT_IRQ_RISE); - digitalSetIrqHandler(interruptNumber, (void *)callback); - break; + gpio_irq_t *gpio; - case CHANGE: - // TODO - break; - } + if (g_APinDescription[interruptNumber].ulPinType == NOT_INITIAL) { + // allocate memory if pin not used before + 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) { - if ( g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ ) { - pinRemoveMode(interruptNumber); - } + if (pinInvalid(interruptNumber)) + return; + + if (g_APinDescription[interruptNumber].ulPinType == PIO_GPIO_IRQ) { + pinRemoveMode(interruptNumber); + } + gpio_irq_handler_list[interruptNumber] = NULL; } + +#ifdef __cplusplus +} +#endif diff --git a/arduino/realtek-ambz/cores/arduino/WVariant.h b/arduino/realtek-ambz/cores/arduino/WVariant.h index 1ebc651..98e4a1e 100644 --- a/arduino/realtek-ambz/cores/arduino/WVariant.h +++ b/arduino/realtek-ambz/cores/arduino/WVariant.h @@ -40,30 +40,6 @@ extern void yield(void); #define sprintf rtl_sprintf #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 PIO_GPIO (1UL<<1) #define PIO_PWM (1UL<<2) @@ -78,32 +54,26 @@ extern int tcm_heap_freeSpace(void); /* Types used for the tables below */ typedef struct _PinDescription { - // HW PinNames uint32_t pinname; - // Current Pin Type uint32_t ulPinType; - // Supported Pin Function uint32_t ulPinAttribute; - // Current Pin Mode uint32_t ulPinMode; - } PinDescription ; /* Pins table to be instanciated into variant.cpp */ extern PinDescription g_APinDescription[]; +extern bool pinInvalid(pin_size_t pinNumber); +extern void pinRemoveMode(pin_size_t pinNumber); + /* moved from wiring_digital.h */ -extern void digitalChangeDir( uint32_t ulPin, uint8_t direction); /**************************** Extend API by RTK ***********************************/ -extern uint32_t digitalPinToPort( uint32_t ulPin ); -extern uint32_t digitalPinToBitMask( uint32_t ulPin ); -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); +extern uint32_t digitalPinToPort( uint32_t pinNumber ); +extern uint32_t digitalPinToBitMask( uint32_t pinNumber ); /* moved from wiring_analog.h */ /* @@ -122,23 +92,9 @@ extern void analogOutputInit( void ) ; extern void analogWritePeriod(int us); /* 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 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)) extern uint32_t ulPortSetInterruptMask( void ); diff --git a/arduino/realtek-ambz/cores/arduino/wiring_digital.c b/arduino/realtek-ambz/cores/arduino/wiring_digital.c index c411df3..9a1f4f8 100644 --- a/arduino/realtek-ambz/cores/arduino/wiring_digital.c +++ b/arduino/realtek-ambz/cores/arduino/wiring_digital.c @@ -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" #ifdef __cplusplus @@ -30,234 +12,131 @@ extern "C" { 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 ); - } +bool pinInvalid(pin_size_t pinNumber) { + return pinNumber < 0 || pinNumber > PINS_COUNT || g_APinDescription[pinNumber].pinname == NC; } -void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) -{ - void *pGpio_t; - - if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) ) - { - // Invalid pin - return; - } - - if ( (g_APinDescription[pinNumber].ulPinType == PIO_GPIO || g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) - && g_APinDescription[pinNumber].ulPinMode == pinMode) - { - // Nothing changes in pin mode - return; - } - - if ( g_APinDescription[pinNumber].ulPinType == PIO_PWM ) { - // If this pin has been configured as PWM, then it cannot change to another mode - return; - } - - 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 pinRemoveMode(pin_size_t pinNumber) { + if (pinInvalid(pinNumber)) + return; + if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) { + pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber]; + pwmout_free(obj); + } + if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO) { + gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber]; + gpio_deinit(obj, g_APinDescription[pinNumber].pinname); + free(obj); + } + if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO_IRQ) { + gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber]; + gpio_irq_deinit(obj); + free(obj); + } + gpio_pin_struct[pinNumber] = NULL; + g_APinDescription[pinNumber].ulPinType = NOT_INITIAL; + g_APinDescription[pinNumber].ulPinMode = NOT_INITIAL; } -void digitalWrite(pin_size_t pinNumber, PinStatus status) -{ - gpio_t *pGpio_t; +void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) { + if (pinInvalid(pinNumber)) + return; - if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) ) - { - return; - } + if (g_APinDescription[pinNumber].ulPinType == PIO_GPIO && g_APinDescription[pinNumber].ulPinMode == pinMode) + // Nothing changes in pin mode + return; - if ( g_APinDescription[pinNumber].ulPinType != PIO_GPIO ) - { - return; - } + /* if (g_APinDescription[pinNumber].ulPinType == PIO_PWM) { + // If this pin has been configured as PWM, then it cannot change to another mode + 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) -{ - gpio_t *pGpio_t; - int pin_status; - - if ( pinNumber < 0 || pinNumber > PINS_COUNT || (g_APinDescription[pinNumber].pinname == NC) ) - { - return -1; - } +void digitalWrite(pin_size_t pinNumber, PinStatus status) { + if (pinInvalid(pinNumber)) + return; + if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO) + return; - if ( g_APinDescription[pinNumber].ulPinType != PIO_GPIO ) - { - return -1; - } - - pGpio_t = (gpio_t *)gpio_pin_struct[pinNumber]; - - pin_status = gpio_read( pGpio_t ); - - return pin_status; + gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber]; + gpio_write(gpio, status); } -void digitalChangeDir( uint32_t ulPin, uint8_t direction) -{ - gpio_t *pGpio_t; - u32 RegValue; +PinStatus digitalRead(pin_size_t pinNumber) { + if (pinInvalid(pinNumber)) + return; + if (g_APinDescription[pinNumber].ulPinType != PIO_GPIO) + return; - if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) - { - return; - } - - if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO ) - { - return; - } - - pGpio_t = (gpio_t *)gpio_pin_struct[ulPin]; - - gpio_dir( pGpio_t, direction ); + gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber]; + return gpio_read(gpio); } /**************************** Extend API by RTK ***********************************/ -uint32_t digitalPinToPort( uint32_t ulPin ) -{ - uint32_t pin_name; +uint32_t digitalPinToPort(uint32_t pinNumber) { + if (pinInvalid(pinNumber)) + return 0xFFFFFFFF; - if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) - { - return 0xFFFFFFFF; - } - - pin_name = HAL_GPIO_GetPinName(g_APinDescription[ulPin].pinname); - return HAL_GPIO_GET_PORT_BY_NAME(pin_name); + uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname); + return HAL_GPIO_GET_PORT_BY_NAME(pin_name); } -uint32_t digitalPinToBitMask( uint32_t ulPin ) -{ - uint32_t pin_name; +uint32_t digitalPinToBitMask(uint32_t pinNumber) { + if (pinInvalid(pinNumber)) + return 0xFFFFFFFF; - if ( ulPin < 0 || ulPin > PINS_COUNT || (g_APinDescription[ulPin].pinname == NC) ) - { - 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; - } + uint32_t pin_name = HAL_GPIO_GetPinName(g_APinDescription[pinNumber].pinname); + return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name)); } #ifdef __cplusplus diff --git a/boards/wr3/variant.cpp b/boards/wr3/variant.cpp index 797512b..4a9558a 100644 --- a/boards/wr3/variant.cpp +++ b/boards/wr3/variant.cpp @@ -15,8 +15,8 @@ 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 "variant.h" #include "Arduino.h" +#include "variant.h" #include "gpio_api.h" #ifdef __cplusplus