[core] Refactor Wiring, use PinData for parameters

This commit is contained in:
Kuba Szczodrzyński
2023-05-24 18:20:22 +02:00
parent bc74c21599
commit e5f98ff41f
22 changed files with 397 additions and 394 deletions

View File

@@ -1,22 +1,11 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
#include <Arduino.h>
#include <include.h>
#include <arm_arch.h>
#include <bk_timer.h>
#include <bk_timer_pub.h>
#include <rtos_pub.h>
#include <sys_rtos.h>
#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);
}
}

View File

@@ -1,10 +1,6 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include <Arduino.h>
#include <gpio_pub.h>
#include <pwm_pub.h>
#include <saradc_pub.h>
#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);

View File

@@ -0,0 +1,23 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <Arduino.h>
#include <sdk_private.h>
#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

View File

@@ -1,20 +1,16 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include <Arduino.h>
#include <gpio_pub.h>
#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);
}

View File

@@ -1,98 +1,70 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-31. */
#include <Arduino.h>
#include <gpio_pub.h>
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);
}

View File

@@ -6,12 +6,18 @@
extern "C" {
#endif // __cplusplus
// most stuff is here
// most stuff is here - this has to be before other includes!
#include <include.h>
// other includes
#include <arm_arch.h>
#include <bk_timer.h>
#include <bk_timer_pub.h>
#include <flash_pub.h>
#include <gpio_pub.h>
#include <param_config.h>
#include <pwm_pub.h>
#include <rtos_pub.h>
#include <saradc_pub.h>
#include <start_type_pub.h>
#include <sys_ctrl.h>
#include <sys_rtos.h>

View File

@@ -0,0 +1,17 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#include <Arduino.h>
#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

View File

@@ -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 <FreeRTOS.h>
@@ -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.

View File

@@ -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);

View File

@@ -0,0 +1,7 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#include <Arduino.h>
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL);
}

View File

@@ -0,0 +1,25 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#include "wiring_private.h"
#if __has_include(<wiring_data.h>)
/**
* @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

View File

@@ -0,0 +1,64 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <Arduino.h>
#if __has_include(<sdk_private.h>)
#include <sdk_private.h>
#endif
#if __has_include(<wiring_data.h>)
#include <wiring_data.h>
#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

View File

@@ -1,12 +0,0 @@
#include <Arduino.h>
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);
}

View File

@@ -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 <Arduino.h>
#include <cmsis_os.h>
#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);
}
}

View File

@@ -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 <Arduino.h>
#include <sdk_private.h>
#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);
}

View File

@@ -0,0 +1,24 @@
/* Copyright (c) Kuba Szczodrzyński 2023-05-24. */
#pragma once
#include <Arduino.h>
#include <sdk_private.h>
#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

View File

@@ -1,68 +1,32 @@
#include <Arduino.h>
#include <sdk_private.h>
/* 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);
}

View File

@@ -1,59 +1,50 @@
#include <Arduino.h>
#include <sdk_private.h>
/* 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);
}

View File

@@ -16,10 +16,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <sdk_private.h>
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();

View File

@@ -27,6 +27,9 @@ extern "C" {
#endif
#include <cmsis_os.h>
#undef malloc
#undef free
#undef calloc
// mbed APIs
#include <gpio_api.h>

View File

@@ -78,6 +78,7 @@ lt_reboot_reason_t lt_get_reboot_reason() {
void lt_gpio_recover() {
sys_jtag_off();
sys_swd_off();
}
/*__ __

View File

@@ -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);