diff --git a/cores/beken-72xx/arduino/src/wiring.c b/cores/beken-72xx/arduino/src/wiring.c index a1f5d48..f6d7873 100644 --- a/cores/beken-72xx/arduino/src/wiring.c +++ b/cores/beken-72xx/arduino/src/wiring.c @@ -1,22 +1,11 @@ /* Copyright (c) Kuba Szczodrzyński 2022-06-19. */ -#include -#include - -#include -#include -#include -#include -#include +#include "wiring_private.h" #define TICKS_PER_US (CFG_XTAL_FREQUENCE / 1000 / 1000) #define US_PER_OVERFLOW (portTICK_PERIOD_MS * 1000) #define TICKS_PER_OVERFLOW (TICKS_PER_US * US_PER_OVERFLOW) -void delayMilliseconds(unsigned long ms) { - rtos_delay_milliseconds(ms); -} - static uint32_t getTicksCount() { // copied from bk_timer_ctrl(), for speeds uint32_t timeout = 0; @@ -104,8 +93,22 @@ unsigned long micros() { #endif } -void yield() { - runPeriodicTasks(); - vTaskDelay(1); - taskYIELD(); +void pinRemoveMode(PinInfo *pin, uint32_t mask) { + PinData *data = pinData(pin); + if ((mask & PIN_GPIO) && (pin->enabled & PIN_GPIO)) { + gpio_config(pin->gpio, GMODE_INPUT_PULLDOWN); + pinDisable(pin, PIN_GPIO); + } + if ((mask & PIN_IRQ) && (pin->enabled & PIN_IRQ)) { + data->irqHandler = NULL; + gpio_int_disable(pin->gpio); + pinDisable(pin, PIN_IRQ); + } + if ((mask & PIN_PWM) && (pin->enabled & PIN_PWM)) { + data->pwm->cfg.bits.en = PWM_DISABLE; + __wrap_bk_printf_disable(); + sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, data->pwm); + __wrap_bk_printf_enable(); + pinDisable(pin, PIN_PWM); + } } diff --git a/cores/beken-72xx/arduino/src/wiring_analog.c b/cores/beken-72xx/arduino/src/wiring_analog.c index 71971df..5808b99 100644 --- a/cores/beken-72xx/arduino/src/wiring_analog.c +++ b/cores/beken-72xx/arduino/src/wiring_analog.c @@ -1,10 +1,6 @@ /* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ -#include - -#include -#include -#include +#include "wiring_private.h" static GPIO_INDEX pwmToGpio[] = { GPIO6, // PWM0 @@ -59,11 +55,7 @@ static pwm_param_t pwm; static uint16_t adcData[1]; uint16_t analogReadVoltage(pin_size_t pinNumber) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return 0; - if (!pinSupported(pin, PIN_ADC)) - return 0; + pinCheckGetInfo(pinNumber, PIN_ADC, 0); UINT32 status; saradc_desc_t adc; @@ -90,11 +82,10 @@ uint16_t analogReadMaxVoltage(pin_size_t pinNumber) { } void analogWrite(pin_size_t pinNumber, int value) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - if (!pinSupported(pin, PIN_PWM)) - return; + pinCheckGetData(pinNumber, PIN_PWM, ); + + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_GPIO | PIN_IRQ); float percent = value * 1.0 / ((1 << _analogWriteResolution) - 1); uint32_t frequency = 26 * _analogWritePeriod - 1; @@ -122,8 +113,9 @@ void analogWrite(pin_size_t pinNumber, int value) { sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_LEVL_SET_HIGH, &pwm.channel); sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_ENABLE, &pwm.channel); __wrap_bk_printf_enable(); - pin->enabled &= ~PIN_GPIO; - pin->enabled |= PIN_PWM; + // pass global PWM object pointer + data->pwm = &pwm; + pinEnable(pin, PIN_PWM); } else { // update duty cycle sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, &pwm); @@ -131,11 +123,7 @@ void analogWrite(pin_size_t pinNumber, int value) { } else { if (pinEnabled(pin, PIN_PWM)) { // disable PWM - pwm.cfg.bits.en = PWM_DISABLE; - __wrap_bk_printf_disable(); - sddev_control(PWM_DEV_NAME, CMD_PWM_DEINIT_PARAM, &pwm); - __wrap_bk_printf_enable(); - pin->enabled &= ~PIN_PWM; + pinRemoveMode(pin, PIN_PWM); } // force level as LOW pinMode(pinNumber, OUTPUT); diff --git a/cores/beken-72xx/arduino/src/wiring_data.h b/cores/beken-72xx/arduino/src/wiring_data.h new file mode 100644 index 0000000..c6d5210 --- /dev/null +++ b/cores/beken-72xx/arduino/src/wiring_data.h @@ -0,0 +1,23 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct PinData_s { + pwm_param_t *pwm; + PinMode gpioMode; + PinStatus irqMode; + void *irqHandler; + void *irqParam; + bool irqChange; +}; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/beken-72xx/arduino/src/wiring_digital.c b/cores/beken-72xx/arduino/src/wiring_digital.c index 27f0016..ab7dcff 100644 --- a/cores/beken-72xx/arduino/src/wiring_digital.c +++ b/cores/beken-72xx/arduino/src/wiring_digital.c @@ -1,20 +1,16 @@ /* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ -#include - -#include +#include "wiring_private.h" void pinMode(pin_size_t pinNumber, PinMode pinMode) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - if (!pinSupported(pin, PIN_GPIO)) - return; - if (pinEnabled(pin, PIN_PWM)) - // disable PWM before using the pin - analogWrite(pinNumber, 0); - if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode) + pinCheckGetData(pinNumber, PIN_GPIO, ); + + if (pinEnabled(pin, PIN_GPIO) && data->gpioMode == pinMode) return; + + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_PWM); + switch (pinMode) { case INPUT: gpio_config(pin->gpio, GMODE_INPUT); @@ -31,34 +27,21 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) { case OUTPUT_OPENDRAIN: gpio_config(pin->gpio, GMODE_SET_HIGH_IMPENDANCE); break; + default: + return; } - pin->enabled |= PIN_GPIO; - pin->mode = pinMode; + pinEnable(pin, PIN_GPIO); + data->gpioMode = pinMode; } void digitalWrite(pin_size_t pinNumber, PinStatus status) { - // verify level is 0 or 1 - if (status > HIGH) - return; - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - // pin is not GPIO yet or not OUTPUT; enable or disable input pullup - if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) { - pinMode(pinNumber, status * INPUT_PULLUP); - return; - } - // write the new state - gpio_output(pin->gpio, status); + pinCheckGetData(pinNumber, PIN_GPIO, ); + pinSetOutputPull(pin, data, pinNumber, status); + gpio_output(pin->gpio, !!status); } PinStatus digitalRead(pin_size_t pinNumber) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return 0; - // pin is not GPIO yet or not INPUT; change the mode - if (!pinEnabled(pin, PIN_GPIO) || !pinIsInput(pin)) - pinMode(pinNumber, INPUT); - // read the value + pinCheckGetData(pinNumber, PIN_GPIO, LOW); + pinSetInputMode(pin, data, pinNumber); return gpio_input(pin->gpio); } diff --git a/cores/beken-72xx/arduino/src/wiring_irq.c b/cores/beken-72xx/arduino/src/wiring_irq.c index d014b42..884bc03 100644 --- a/cores/beken-72xx/arduino/src/wiring_irq.c +++ b/cores/beken-72xx/arduino/src/wiring_irq.c @@ -1,98 +1,70 @@ /* Copyright (c) Kuba Szczodrzyński 2022-07-31. */ -#include - -#include - -static void *irqHandlerList[PINS_COUNT] = {NULL}; -static void *irqHandlerArgs[PINS_COUNT] = {NULL}; -static bool irqChangeList[PINS_COUNT]; +#include "wiring_private.h" static void irqHandler(unsigned char gpio) { PinInfo *pin = pinByGpio(gpio); if (pin == NULL) return; - uint32_t index = pinIndex(pin); - if (!irqHandlerList[index]) + PinData *data = pinData(pin); + if (!data->irqHandler) return; - if (irqChangeList[index]) { - if (pin->mode == INPUT_PULLDOWN) { - pin->mode = INPUT_PULLUP; + if (data->irqChange) { + if (data->gpioMode == INPUT_PULLDOWN) { + data->gpioMode = INPUT_PULLUP; gpio_int_enable(pin->gpio, GPIO_INT_LEVEL_FALLING, irqHandler); - } else if (pin->mode == INPUT_PULLUP) { - pin->mode = INPUT_PULLDOWN; + } else if (data->gpioMode == INPUT_PULLUP) { + data->gpioMode = INPUT_PULLDOWN; gpio_int_enable(pin->gpio, GPIO_INT_LEVEL_RISING, irqHandler); } } - if (irqHandlerArgs[index] == NULL) { - ((voidFuncPtr)irqHandlerList[index])(); - } else { - ((voidFuncPtrParam)irqHandlerList[index])(irqHandlerArgs[index]); - } -} - -void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) { - attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL); + if (!data->irqParam) + ((voidFuncPtr)data->irqHandler)(); + else + ((voidFuncPtrParam)data->irqHandler)(data->irqParam); } void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) { - PinInfo *pin = pinInfo(interruptNumber); - if (!pin) - return; - if (!pinSupported(pin, PIN_IRQ)) - return; - uint32_t index = pinIndex(pin); - uint32_t event = 0; - PinMode modeNew = 0; - bool change = 0; + pinCheckGetData(interruptNumber, PIN_IRQ, ); + data->irqHandler = callback; + data->irqParam = param; + + if (pinEnabled(pin, PIN_IRQ) && data->irqMode == mode) + return; + + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_PWM); + + uint32_t event = 0; + bool change = false; switch (mode) { case LOW: - event = GPIO_INT_LEVEL_LOW; - modeNew = INPUT_PULLUP; - change = false; + event = GPIO_INT_LEVEL_LOW; break; case HIGH: - event = GPIO_INT_LEVEL_HIGH; - modeNew = INPUT_PULLDOWN; - change = false; + event = GPIO_INT_LEVEL_HIGH; break; case FALLING: - event = GPIO_INT_LEVEL_FALLING; - modeNew = INPUT_PULLUP; - change = false; + event = GPIO_INT_LEVEL_FALLING; break; case RISING: - event = GPIO_INT_LEVEL_RISING; - modeNew = INPUT_PULLDOWN; - change = false; + event = GPIO_INT_LEVEL_RISING; break; case CHANGE: - event = GPIO_INT_LEVEL_FALLING; - modeNew = INPUT_PULLUP; - change = true; + event = GPIO_INT_LEVEL_FALLING; + change = true; break; default: return; } - irqHandlerList[index] = callback; - irqHandlerArgs[index] = param; - irqChangeList[index] = change; + pinEnable(pin, PIN_IRQ); + data->irqMode = mode; + data->irqChange = change; + gpio_int_enable(pin->gpio, event, irqHandler); - pin->enabled |= PIN_IRQ | PIN_GPIO; - pin->mode = modeNew; } void detachInterrupt(pin_size_t interruptNumber) { - PinInfo *pin = pinInfo(interruptNumber); - if (!pin) - return; - if (!pinSupported(pin, PIN_IRQ)) - return; - uint32_t index = pinIndex(pin); - irqHandlerList[index] = NULL; - irqHandlerArgs[index] = NULL; - irqChangeList[index] = false; - gpio_int_disable(pin->gpio); - pin->enabled &= ~PIN_IRQ; + pinModeRemove(interruptNumber, PIN_IRQ); } diff --git a/cores/beken-72xx/base/sdk_private.h b/cores/beken-72xx/base/sdk_private.h index 044e2cb..268c7df 100644 --- a/cores/beken-72xx/base/sdk_private.h +++ b/cores/beken-72xx/base/sdk_private.h @@ -6,12 +6,18 @@ extern "C" { #endif // __cplusplus -// most stuff is here +// most stuff is here - this has to be before other includes! #include // other includes +#include +#include +#include #include #include #include +#include +#include +#include #include #include #include diff --git a/cores/common/arduino/src/wiring.c b/cores/common/arduino/src/wiring.c new file mode 100644 index 0000000..5f344de --- /dev/null +++ b/cores/common/arduino/src/wiring.c @@ -0,0 +1,17 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#include + +#if LT_HAS_FREERTOS + +__attribute__((weak)) void delay(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); +} + +__attribute__((weak)) void yield() { + runPeriodicTasks(); + vTaskDelay(1); + taskYIELD(); +} + +#endif diff --git a/cores/common/arduino/src/wiring_custom.c b/cores/common/arduino/src/wiring_custom.c index a002ea1..31bd582 100644 --- a/cores/common/arduino/src/wiring_custom.c +++ b/cores/common/arduino/src/wiring_custom.c @@ -1,6 +1,6 @@ /* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ -#include "wiring_custom.h" +#include "wiring_private.h" #if LT_HAS_FREERTOS #include @@ -32,6 +32,18 @@ void runPeriodicTasks() { #endif } +/** + * @brief Disable modes specified by 'mask'. + */ +void pinModeRemove(pin_size_t pinNumber, uint32_t mask) { + PinInfo *pin = pinInfo(pinNumber); + if (!pin) + return; + pinRemoveMode(pin, mask); + if (pin->enabled == PIN_NONE && mask == PIN_MODE_ALL) + pinRemoveData(pin); +} + /** * @brief Get PinInfo struct for the specified number. * Returns NULL if pin number is invalid. @@ -85,20 +97,6 @@ bool pinEnabled(PinInfo *pin, uint32_t mask) { return (pin->enabled & mask) == mask; } -/** - * @brief Check if GPIO pin is configured as output. - */ -bool pinIsOutput(PinInfo *pin) { - return pin->mode == OUTPUT || pin->mode == OUTPUT_OPENDRAIN; -} - -/** - * @brief Check if GPIO pin is configured as output. - */ -bool pinIsInput(PinInfo *pin) { - return pin->mode == INPUT || pin->mode == INPUT_PULLUP || pin->mode == INPUT_PULLDOWN; -} - /** * @brief Read voltage from ADC and return a value between 0 and * the current reading resolution. diff --git a/cores/common/arduino/src/wiring_custom.h b/cores/common/arduino/src/wiring_custom.h index 392e280..befc254 100644 --- a/cores/common/arduino/src/wiring_custom.h +++ b/cores/common/arduino/src/wiring_custom.h @@ -21,7 +21,10 @@ extern "C" { #define PIN_SWD (1 << 10) #define PIN_UART (1 << 11) -#define PIN_INVALID 255 +#define PIN_MODE_ALL 0xFFFFFFFF +#define PIN_INVALID 255 + +typedef struct PinData_s PinData; typedef struct { /** @@ -37,9 +40,9 @@ typedef struct { */ uint32_t enabled; /** - * @brief Pin mode (direction, IRQ level, etc.). + * @brief Pin data (direction, IRQ level, etc.). The structure is family-specific. */ - uint32_t mode; + PinData *data; } PinInfo; extern PinInfo lt_arduino_pin_info_list[PINS_COUNT]; @@ -57,14 +60,21 @@ bool startMainTask(void); void mainTask(const void *arg); // implemented in main.cpp void runPeriodicTasks(); // implemented in wiring_custom.c +void pinModeRemove(pin_size_t pinNumber, uint32_t mask); PinInfo *pinInfo(pin_size_t pinNumber); PinInfo *pinByIndex(uint32_t index); PinInfo *pinByGpio(uint32_t gpio); uint32_t pinIndex(PinInfo *pin); bool pinSupported(PinInfo *pin, uint32_t mask); bool pinEnabled(PinInfo *pin, uint32_t mask); -bool pinIsOutput(PinInfo *pin); -bool pinIsInput(PinInfo *pin); +void pinRemoveMode(PinInfo *pin, uint32_t mask); + +/** + * @brief Deinitialize the pin, by removing all enabled modes. + */ +inline void pinModeNone(pin_size_t pinNumber) { + pinModeRemove(pinNumber, PIN_MODE_ALL); +} int analogRead(pin_size_t pinNumber); void analogReadResolution(int res); diff --git a/cores/common/arduino/src/wiring_irq.c b/cores/common/arduino/src/wiring_irq.c new file mode 100644 index 0000000..f8efc37 --- /dev/null +++ b/cores/common/arduino/src/wiring_irq.c @@ -0,0 +1,7 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#include + +void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) { + attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL); +} diff --git a/cores/common/arduino/src/wiring_private.c b/cores/common/arduino/src/wiring_private.c new file mode 100644 index 0000000..0810d80 --- /dev/null +++ b/cores/common/arduino/src/wiring_private.c @@ -0,0 +1,25 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#include "wiring_private.h" + +#if __has_include() +/** + * @brief Allocate and return a PinData structure (family-specific). + */ +PinData *pinData(PinInfo *pin) { + if (pin->data == NULL) { + pin->data = calloc(1, sizeof(PinData)); + } + return (PinData *)pin->data; +} + +/** + * @brief Deallocate the PinData structure. + */ +void pinRemoveData(PinInfo *pin) { + if (pin->data != NULL) { + free(pin->data); + } + pin->data = NULL; +} +#endif diff --git a/cores/common/arduino/src/wiring_private.h b/cores/common/arduino/src/wiring_private.h new file mode 100644 index 0000000..5d0b9c3 --- /dev/null +++ b/cores/common/arduino/src/wiring_private.h @@ -0,0 +1,64 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#pragma once + +#include + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +PinData *pinData(PinInfo *pin); +void pinRemoveData(PinInfo *pin); + +inline void pinEnable(PinInfo *pin, uint32_t mask) { + pin->enabled |= mask; +} + +inline void pinDisable(PinInfo *pin, uint32_t mask) { + pin->enabled &= ~mask; +} + +#define pinCheckGetInfo(pinNumber, mask, ret) \ + PinInfo *pin = pinInfo(pinNumber); \ + if (!pin) \ + return ret; \ + if (!pinSupported(pin, mask)) \ + return ret; + +#define pinCheckGetData(pinNumber, mask, ret) \ + PinInfo *pin = pinInfo(pinNumber); \ + if (!pin) \ + return ret; \ + if (!pinSupported(pin, mask)) \ + return ret; \ + PinData *data = pinData(pin); + +#define pinIsOutput(pin, data) (pinEnabled(pin, PIN_GPIO) && (data->gpioMode ^ 0b101) < 5) +#define pinIsInput(pin, data) (pinEnabled(pin, PIN_GPIO) && (data->gpioMode ^ 0b101) > 4) + +#define pinSetOutputPull(pin, data, pinNumber, status) \ + do { \ + if (!pinIsOutput(pin, data)) { \ + pinMode(pinNumber, INPUT_PULLDOWN ^ !!status); \ + return; \ + } \ + } while (0); + +#define pinSetInputMode(pin, data, pinNumber) \ + do { \ + if (!pinIsInput(pin, data)) \ + pinMode(pinNumber, INPUT); \ + } while (0); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/realtek-amb/arduino/src/Tone.cpp b/cores/realtek-amb/arduino/src/Tone.cpp deleted file mode 100644 index 816114e..0000000 --- a/cores/realtek-amb/arduino/src/Tone.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include - -extern void pinRemoveMode(pin_size_t pinNumber); -extern void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration); - -void tone(uint32_t ulPin, unsigned int frequency, unsigned long duration) { - _tone(ulPin, frequency, duration); -} - -void noTone(uint32_t ulPin) { - pinRemoveMode(ulPin); -} diff --git a/cores/realtek-amb/arduino/src/wiring.c b/cores/realtek-amb/arduino/src/wiring.c index 0cc3839..bb0fc6b 100644 --- a/cores/realtek-amb/arduino/src/wiring.c +++ b/cores/realtek-amb/arduino/src/wiring.c @@ -1,48 +1,11 @@ -/* - Copyright (c) 2011 Arduino. All right reserved. +/* Copyright (c) Kuba Szczodrzyński 2022-04-23. */ - 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 - -#include +#include "wiring_private.h" #ifndef portNVIC_SYSTICK_CURRENT_VALUE_REG #define portNVIC_SYSTICK_CURRENT_VALUE_REG (*((volatile uint32_t *)0xe000e018)) #endif -extern uint32_t xTaskGetTickCount(); -extern uint32_t xTaskGetTickCountFromISR(); - -static __inline uint32_t __get_ipsr__(void) { - volatile uint32_t __regIPSR __asm("ipsr"); - return (__regIPSR); -} - -void *gpio_pin_struct[PINS_COUNT] = {NULL}; - -void delay(uint32_t ms) { - /* osStatus ret; */ - - /* ret = */ osDelay(ms); - /* if ((ret != osEventTimeout) && (ret != osOK)) { - printf("delay : ERROR : 0x%x \n", ret); - } */ -} - void delayMicroseconds(unsigned int us) { int i; uint32_t t0, tn; @@ -61,7 +24,7 @@ void delayMicroseconds(unsigned int us) { } unsigned long millis(void) { - return (__get_ipsr__() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR(); + return (__get_IPSR() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR(); } unsigned long micros(void) { @@ -69,7 +32,7 @@ unsigned long micros(void) { uint32_t us; uint32_t tick_per_us = F_CPU / 1000; - if (__get_ipsr__() == 0) { + if (__get_IPSR() == 0) { tick1 = xTaskGetTickCount(); us = portNVIC_SYSTICK_CURRENT_VALUE_REG; tick2 = xTaskGetTickCount(); @@ -88,8 +51,22 @@ unsigned long micros(void) { } } -void yield(void) { - runPeriodicTasks(); - vTaskDelay(1); - taskYIELD(); +void pinRemoveMode(PinInfo *pin, uint32_t mask) { + PinData *data = pinData(pin); + if ((mask & PIN_GPIO) && (pin->enabled & PIN_GPIO)) { + gpio_deinit(data->gpio); + free(data->gpio); + pinDisable(pin, PIN_GPIO); + } + if ((mask & PIN_IRQ) && (pin->enabled & PIN_IRQ)) { + data->irqHandler = NULL; + gpio_irq_free(data->irq); + free(data->irq); + pinDisable(pin, PIN_IRQ); + } + if ((mask & PIN_PWM) && (pin->enabled & PIN_PWM)) { + pwmout_free(data->pwm); + free(data->pwm); + pinDisable(pin, PIN_PWM); + } } diff --git a/cores/realtek-amb/arduino/src/wiring_analog.c b/cores/realtek-amb/arduino/src/wiring_analog.c index 05d0796..68b7f83 100644 --- a/cores/realtek-amb/arduino/src/wiring_analog.c +++ b/cores/realtek-amb/arduino/src/wiring_analog.c @@ -1,23 +1,6 @@ -/* - Copyright (c) 2011 Arduino. All right reserved. +/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */ - 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 -#include +#include "wiring_private.h" /* ADC */ static analogin_t adc1; @@ -28,17 +11,13 @@ static bool g_adc_enabled[] = {false, false, false}; // from realtek_amebaz_va0_example/example_sources/adc_vbat/src/main.c #define AD2MV(ad, offset, gain) (((ad >> 4) - offset) * 1000 / gain) -extern void *gpio_pin_struct[]; - -extern void pinRemoveMode(pin_size_t pinNumber); - // TODO implement custom ADC calibration uint16_t analogReadVoltage(pin_size_t pinNumber) { uint16_t ret = 0; switch (pinNumber) { -#ifdef PIN_A1 - case PIN_A1: +#ifdef PIN_ADC2 + case PIN_ADC2: if (g_adc_enabled[1] == false) { analogin_init(&adc2, AD_2); g_adc_enabled[1] = true; @@ -47,8 +26,8 @@ uint16_t analogReadVoltage(pin_size_t pinNumber) { // AD_1 - 0.0V-5.0V return AD2MV(ret, 0x496, 0xBA); #endif -#ifdef PIN_A0 - case PIN_A0: +#ifdef PIN_ADC1 + case PIN_ADC1: if (g_adc_enabled[0] == false) { analogin_init(&adc1, AD_1); g_adc_enabled[0] = true; @@ -56,8 +35,8 @@ uint16_t analogReadVoltage(pin_size_t pinNumber) { ret = analogin_read_u16(&adc1); break; #endif -#ifdef PIN_A2 - case PIN_A2: +#ifdef PIN_ADC3 + case PIN_ADC3: if (g_adc_enabled[2] == false) { analogin_init(&adc3, AD_3); g_adc_enabled[2] = true; @@ -82,27 +61,20 @@ uint16_t analogReadMaxVoltage(pin_size_t pinNumber) { } void analogWrite(pin_size_t pinNumber, int value) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - pwmout_t *obj; + pinCheckGetData(pinNumber, PIN_PWM, ); - if (pinSupported(pin, PIN_PWM)) { - float percent = value * 1.0 / (1 << _analogWriteResolution); - if (pin->enabled != PIN_PWM) { - if ((pin->enabled == PIN_GPIO) || (pin->enabled == PIN_IRQ)) { - pinRemoveMode(pinNumber); - } - gpio_pin_struct[pinNumber] = malloc(sizeof(pwmout_t)); - pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber]; - pwmout_init(obj, pin->gpio); - pwmout_period_us(obj, _analogWritePeriod); - pwmout_write(obj, percent); - pin->enabled = PIN_PWM; - } else { - pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber]; - // pwmout_period_us(obj, _writePeriod); - pwmout_write(obj, percent); - } + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_GPIO | PIN_IRQ); + + pwmout_t *pwm = data->pwm; + if (!pwm) { + // allocate memory if pin not used before + data->pwm = pwm = malloc(sizeof(pwmout_t)); + pwmout_init(pwm, pin->gpio); + pwmout_period_us(pwm, _analogWritePeriod); + pinEnable(pin, PIN_PWM); } + + float percent = value * 1.0 / (1 << _analogWriteResolution); + pwmout_write(pwm, percent); } diff --git a/cores/realtek-amb/arduino/src/wiring_data.h b/cores/realtek-amb/arduino/src/wiring_data.h new file mode 100644 index 0000000..1f0038f --- /dev/null +++ b/cores/realtek-amb/arduino/src/wiring_data.h @@ -0,0 +1,24 @@ +/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct PinData_s { + gpio_t *gpio; + gpio_irq_t *irq; + pwmout_t *pwm; + PinMode gpioMode; + PinStatus irqMode; + void *irqHandler; + void *irqParam; +}; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/cores/realtek-amb/arduino/src/wiring_digital.c b/cores/realtek-amb/arduino/src/wiring_digital.c index 0c8cb32..1eb2f9c 100644 --- a/cores/realtek-amb/arduino/src/wiring_digital.c +++ b/cores/realtek-amb/arduino/src/wiring_digital.c @@ -1,68 +1,32 @@ -#include -#include +/* Copyright (c) Kuba Szczodrzyński 2022-04-23. */ -extern void *gpio_pin_struct[PINS_COUNT]; - -void pinRemoveMode(pin_size_t pinNumber) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - if (pinEnabled(pin, PIN_PWM)) { - pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber]; - pwmout_free(obj); - } - if (pinEnabled(pin, PIN_GPIO)) { - gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber]; - gpio_deinit(obj); - free(obj); - } - if (pinEnabled(pin, PIN_IRQ)) { - gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber]; - gpio_irq_deinit(obj); - free(obj); - } - gpio_pin_struct[pinNumber] = NULL; - pin->enabled = PIN_NONE; -} +#include "wiring_private.h" void pinMode(pin_size_t pinNumber, PinMode pinMode) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) + pinCheckGetData(pinNumber, PIN_GPIO, ); + + if (pinEnabled(pin, PIN_GPIO) && data->gpioMode == pinMode) return; - if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode) - // Nothing changes in pin mode - return; +#if LT_RTL8720C + // apparently IRQ can't be used with any kind of pull-up/down + // TODO verify if it can be used on AmebaZ + pinRemoveMode(pin, PIN_PWM | PIN_IRQ); +#else + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_PWM); +#endif - if (!pinSupported(pin, PIN_GPIO)) - // cannot set ADC as I/O - return; - - /* if (pin->enabled == PIN_PWM) { - // If this pin has been configured as PWM, then it cannot change to another mode - return; - } */ - - if (pin->enabled != PIN_GPIO) - // pin mode changes; deinit gpio and free memory - pinRemoveMode(pinNumber); - - gpio_t *gpio; - - if (pin->enabled == PIN_NONE) { + gpio_t *gpio = data->gpio; + if (!gpio) { // allocate memory if pin not used before - gpio = malloc(sizeof(gpio_t)); - gpio_pin_struct[pinNumber] = gpio; + data->gpio = gpio = malloc(sizeof(gpio_t)); gpio_init(gpio, pin->gpio); - pin->enabled = PIN_GPIO; - } else { - // pin already used as gpio - gpio = (gpio_t *)gpio_pin_struct[pinNumber]; + pinEnable(pin, PIN_GPIO); } - pin->mode = pinMode; PinDirection dir; - PinMode mode; + PinModeRTL mode; switch (pinMode) { case INPUT: @@ -88,29 +52,20 @@ void pinMode(pin_size_t pinNumber, PinMode pinMode) { default: return; } + data->gpioMode = pinMode; gpio_dir(gpio, dir); gpio_mode(gpio, mode); } void digitalWrite(pin_size_t pinNumber, PinStatus status) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return; - if (pin->enabled != PIN_GPIO) - return; - - gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber]; - gpio_write(gpio, status); + pinCheckGetData(pinNumber, PIN_GPIO, ); + pinSetOutputPull(pin, data, pinNumber, status); + gpio_write(data->gpio, !!status); } PinStatus digitalRead(pin_size_t pinNumber) { - PinInfo *pin = pinInfo(pinNumber); - if (!pin) - return LOW; - if (pin->enabled != PIN_GPIO) - return LOW; - - gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber]; - return gpio_read(gpio); + pinCheckGetData(pinNumber, PIN_GPIO, LOW); + pinSetInputMode(pin, data, pinNumber); + return gpio_read(data->gpio); } diff --git a/cores/realtek-amb/arduino/src/wiring_irq.c b/cores/realtek-amb/arduino/src/wiring_irq.c index 4fd7cd5..f387fcc 100644 --- a/cores/realtek-amb/arduino/src/wiring_irq.c +++ b/cores/realtek-amb/arduino/src/wiring_irq.c @@ -1,59 +1,50 @@ -#include -#include +/* Copyright (c) Kuba Szczodrzyński 2022-04-23. */ -extern void *gpio_pin_struct[PINS_COUNT]; -static void *gpio_irq_handler_list[PINS_COUNT] = {NULL}; -static void *gpio_irq_handler_args[PINS_COUNT] = {NULL}; - -extern void pinRemoveMode(pin_size_t pinNumber); +#include "wiring_private.h" static void gpioIrqHandler(uint32_t id, gpio_irq_event event) { - // id is pin index - if (gpio_irq_handler_list[id] != NULL) { - if (gpio_irq_handler_args[id] == NULL) - ((voidFuncPtr)gpio_irq_handler_list[id])(); - else - ((voidFuncPtrParam)gpio_irq_handler_list[id])(gpio_irq_handler_args[id]); - } -} - -void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) { - attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL); + // id is pin data + PinData *data = (PinData *)id; + if (!data->irqHandler) + return; + if (!data->irqParam) + ((voidFuncPtr)data->irqHandler)(); + else + ((voidFuncPtrParam)data->irqHandler)(data->irqParam); } void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) { - PinInfo *pin = pinInfo(interruptNumber); - if (pin == NULL) - return; - uint32_t index = pinIndex(pin); + pinCheckGetData(interruptNumber, PIN_IRQ, ); - gpio_irq_handler_list[index] = callback; - gpio_irq_handler_args[index] = param; + data->irqHandler = callback; + data->irqParam = param; - if (pin->enabled == PIN_IRQ && pin->mode == mode) - // Nothing changes in pin mode + if (pinEnabled(pin, PIN_IRQ) && data->irqMode == mode) return; - if (pin->enabled != PIN_IRQ) - // pin mode changes; deinit gpio and free memory - pinRemoveMode(interruptNumber); +#if LT_RTL8720C + // apparently IRQ can't be used with any kind of pull-up/down + // TODO verify if it can be used on AmebaZ + pinRemoveMode(pin, PIN_PWM | PIN_GPIO); +#else + // GPIO can't be used together with PWM + pinRemoveMode(pin, PIN_PWM); +#endif - gpio_irq_t *gpio; - - if (pin->enabled == PIN_NONE) { + gpio_irq_t *irq = data->irq; + if (!irq) { // allocate memory if pin not used before - gpio = malloc(sizeof(gpio_irq_t)); - gpio_pin_struct[index] = gpio; - gpio_irq_init(gpio, pin->gpio, gpioIrqHandler, index); - pin->enabled = PIN_IRQ; - } else { - // pin already used as irq - gpio = (gpio_irq_t *)gpio_pin_struct[index]; + data->irq = irq = malloc(sizeof(gpio_irq_t)); + if (gpio_irq_init(irq, pin->gpio, gpioIrqHandler, (uint32_t)data) != 0) { + LT_W("IRQ init failed"); + free(data->irq); + data->irq = NULL; + return; + } + pinEnable(pin, PIN_IRQ); } - pin->mode = mode; gpio_irq_event event; - switch (mode) { case LOW: event = IRQ_LOW; @@ -67,22 +58,22 @@ void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, case RISING: event = IRQ_RISE; break; + case CHANGE: +#if LT_RTL8720C + event = IRQ_FALL_RISE; +#else + LT_W("CHANGE interrupts not supported"); +#endif + break; default: return; } + data->irqMode = mode; - gpio_irq_set(gpio, event, 1); - gpio_irq_enable(gpio); + gpio_irq_set(irq, event, 1); + gpio_irq_enable(irq); } void detachInterrupt(pin_size_t interruptNumber) { - PinInfo *pin = pinInfo(interruptNumber); - if (pin == NULL) - return; - uint32_t index = pinIndex(pin); - - if (pin->enabled == PIN_IRQ) { - pinRemoveMode(interruptNumber); - } - gpio_irq_handler_list[index] = NULL; + pinModeRemove(interruptNumber, PIN_IRQ); } diff --git a/cores/realtek-amb/arduino/src/wiring_pulse.c b/cores/realtek-amb/arduino/src/wiring_pulse.c index 83aeed9..9fcd794 100644 --- a/cores/realtek-amb/arduino/src/wiring_pulse.c +++ b/cores/realtek-amb/arduino/src/wiring_pulse.c @@ -16,10 +16,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include - -extern void *gpio_pin_struct[]; +#include "wiring_private.h" /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds @@ -34,19 +31,17 @@ extern unsigned long pulseIn(uint8_t pinNumber, uint8_t state, unsigned long tim return 0; uint32_t index = pinIndex(pin); - gpio_t *pGpio_t; - uint32_t start_ticks, cur_ticks; if (pin->gpio == NC) return 0; /* Handle */ - if (pin->enabled != PIN_GPIO) { + if (!pinEnabled(pin, PIN_GPIO)) { return 0; } - - pGpio_t = (gpio_t *)gpio_pin_struct[index]; + PinData *data = pinData(pin); + gpio_t *pGpio_t = data->gpio; // wait for any previous pulse to end start_ticks = us_ticker_read(); diff --git a/cores/realtek-amb/base/sdk_private.h b/cores/realtek-amb/base/sdk_private.h index d3bbf01..fb4977e 100644 --- a/cores/realtek-amb/base/sdk_private.h +++ b/cores/realtek-amb/base/sdk_private.h @@ -27,6 +27,9 @@ extern "C" { #endif #include +#undef malloc +#undef free +#undef calloc // mbed APIs #include diff --git a/cores/realtek-ambz2/base/lt_api.c b/cores/realtek-ambz2/base/lt_api.c index 658a4a9..3de1f67 100644 --- a/cores/realtek-ambz2/base/lt_api.c +++ b/cores/realtek-ambz2/base/lt_api.c @@ -78,6 +78,7 @@ lt_reboot_reason_t lt_get_reboot_reason() { void lt_gpio_recover() { sys_jtag_off(); + sys_swd_off(); } /*__ __ diff --git a/cores/realtek-ambz2/base/sdk_extern.h b/cores/realtek-ambz2/base/sdk_extern.h index c0270ce..476e0ee 100644 --- a/cores/realtek-ambz2/base/sdk_extern.h +++ b/cores/realtek-ambz2/base/sdk_extern.h @@ -11,6 +11,7 @@ extern "C" { // SDK void software_reset(); +void sys_swd_off(); void sys_uart_download_mode(); void sys_download_mode(uint8_t mode);