Gpiochips integration (#740)
* gpio-chips core function renames * efi_gpio, pin_repository: add support for external gpios * gpio-chips update * gpio-chips: add api to name each pin of gpiochip * tle6240: provide individual names for each pin
This commit is contained in:
parent
8d924a2f49
commit
1b39480e64
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "global.h"
|
||||
#include "rusefi_enums.h"
|
||||
#include "drivers/gpio/gpio_ext.h"
|
||||
const char *getEngine_type_e(engine_type_e value){
|
||||
switch(value) {
|
||||
case ACURA_RSX:
|
||||
|
@ -805,6 +806,11 @@ case GPIOH_8:
|
|||
return "GPIOH_8";
|
||||
case GPIOH_9:
|
||||
return "GPIOH_9";
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
default:
|
||||
/* gpichips */
|
||||
return gpiochips_getPinName(value);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "global.h"
|
||||
#include "engine.h"
|
||||
#include "efi_gpio.h"
|
||||
#include "drivers/gpio/gpio_ext.h"
|
||||
|
||||
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
|
||||
#include "pin_repository.h"
|
||||
|
@ -68,7 +69,17 @@ EnginePins::EnginePins() {
|
|||
(outputPin)->currentLogicValue = (logicValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define gpiochip_setPinValue(outputPin, electricalValue, logicValue) \
|
||||
{ \
|
||||
if ((outputPin)->currentLogicValue != (logicValue)) { \
|
||||
gpiochips_writePad((outputPin)->brainPin, (electricalValue)); \
|
||||
(outputPin)->currentLogicValue = (logicValue); \
|
||||
} \
|
||||
}
|
||||
|
||||
#else /* EFI_PROD_CODE */
|
||||
|
||||
#define setPinValue(outputPin, electricalValue, logicValue) \
|
||||
{ \
|
||||
if ((outputPin)->currentLogicValue != (logicValue)) { \
|
||||
|
@ -295,13 +306,26 @@ void OutputPin::toggle() {
|
|||
}
|
||||
void OutputPin::setValue(int logicValue) {
|
||||
#if EFI_PROD_CODE
|
||||
if (port != GPIO_NULL) {
|
||||
efiAssertVoid(CUSTOM_ERR_6621, modePtr!=NULL, "pin mode not initialized");
|
||||
pin_output_mode_e mode = *modePtr;
|
||||
efiAssertVoid(CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e");
|
||||
int eValue = getElectricalValue(logicValue, mode);
|
||||
setPinValue(this, eValue, logicValue);
|
||||
}
|
||||
efiAssertVoid(CUSTOM_ERR_6621, modePtr!=NULL, "pin mode not initialized");
|
||||
pin_output_mode_e mode = *modePtr;
|
||||
efiAssertVoid(CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e");
|
||||
int eValue = getElectricalValue(logicValue, mode);
|
||||
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
if (!this->ext) {
|
||||
/* onchip pin */
|
||||
if (port != GPIO_NULL) {
|
||||
setPinValue(this, eValue, logicValue);
|
||||
}
|
||||
} else {
|
||||
/* external pin */
|
||||
gpiochip_setPinValue(this, this->brainPin, logicValue);
|
||||
}
|
||||
#else
|
||||
if (port != GPIO_NULL) {
|
||||
setPinValue(this, eValue, logicValue);
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* EFI_PROD_CODE */
|
||||
setPinValue(this, eValue, logicValue);
|
||||
|
@ -381,37 +405,50 @@ void OutputPin::initPin(const char *msg, brain_pin_e brainPin, const pin_output_
|
|||
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
|
||||
if (brainPin == GPIO_UNASSIGNED)
|
||||
return;
|
||||
ioportid_t port = getHwPort(msg, brainPin);
|
||||
int pin = getHwPin(msg, brainPin);
|
||||
|
||||
/**
|
||||
* This method is used for digital GPIO pins only, for peripheral pins see mySetPadMode
|
||||
*/
|
||||
if (port == GPIO_NULL) {
|
||||
// that's for GRIO_NONE
|
||||
this->port = port;
|
||||
return;
|
||||
}
|
||||
|
||||
assertOMode(*outputMode);
|
||||
iomode_t mode = (*outputMode == OM_DEFAULT || *outputMode == OM_INVERTED) ?
|
||||
PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN;
|
||||
|
||||
/**
|
||||
* @brief Initialize the hardware output pin while also assigning it a logical name
|
||||
*/
|
||||
if (this->port != NULL && (this->port != port || this->pin != pin)) {
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
this->ext = false;
|
||||
#endif
|
||||
if (brain_pin_is_onchip(brainPin)) {
|
||||
ioportid_t port = getHwPort(msg, brainPin);
|
||||
int pin = getHwPin(msg, brainPin);
|
||||
|
||||
/**
|
||||
* here we check if another physical pin is already assigned to this logical output
|
||||
* This method is used for digital GPIO pins only, for peripheral pins see mySetPadMode
|
||||
*/
|
||||
// todo: need to clear '&outputs' in io_pins.c
|
||||
warning(CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned to %x%d", msg, this->port, this->pin);
|
||||
engine->withError = true;
|
||||
return;
|
||||
if (port == GPIO_NULL) {
|
||||
// that's for GRIO_NONE
|
||||
this->port = port;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the hardware output pin while also assigning it a logical name
|
||||
*/
|
||||
if (this->port != NULL && (this->port != port || this->pin != pin)) {
|
||||
/**
|
||||
* here we check if another physical pin is already assigned to this logical output
|
||||
*/
|
||||
// todo: need to clear '&outputs' in io_pins.c
|
||||
warning(CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned to %x%d", msg, this->port, this->pin);
|
||||
engine->withError = true;
|
||||
return;
|
||||
}
|
||||
this->port = port;
|
||||
this->pin = pin;
|
||||
}
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
else {
|
||||
this->ext = true;
|
||||
this->brainPin = brainPin;
|
||||
}
|
||||
#endif
|
||||
|
||||
this->currentLogicValue = INITIAL_PIN_STATE;
|
||||
this->port = port;
|
||||
this->pin = pin;
|
||||
|
||||
efiSetPadMode(msg, brainPin, mode);
|
||||
|
||||
|
@ -492,5 +529,3 @@ const char *hwPortname(brain_pin_e brainPin) {
|
|||
return "N/A";
|
||||
}
|
||||
#endif /* EFI_GPIO_HARDWARE */
|
||||
|
||||
|
||||
|
|
|
@ -51,6 +51,11 @@ public:
|
|||
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
|
||||
ioportid_t port;
|
||||
uint8_t pin;
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
/* used for external pins */
|
||||
brain_pin_e brainPin;
|
||||
bool ext;
|
||||
#endif
|
||||
#endif /* EFI_GPIO_HARDWARE */
|
||||
int8_t currentLogicValue;
|
||||
/**
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
/*==========================================================================*/
|
||||
|
||||
/* fist available gpio number after on-chip gpios */
|
||||
#define EXT_GPIOS_FIRST (GPIOH_15 + 1)
|
||||
static size_t gpio_base_free = EXT_GPIOS_FIRST;
|
||||
#define EXT_GPIOS_FIRST (BRAIN_PIN_LAST_ONCHIP + 1)
|
||||
static brain_pin_e gpio_base_free = EXT_GPIOS_FIRST;
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Exported variables. */
|
||||
|
@ -29,7 +29,7 @@ static size_t gpio_base_free = EXT_GPIOS_FIRST;
|
|||
|
||||
/* TODO: chnage array to list? */
|
||||
struct gpiochip {
|
||||
size_t base;
|
||||
brain_pin_e base;
|
||||
size_t size;
|
||||
struct gpiochip_ops *ops;
|
||||
const char *name;
|
||||
|
@ -68,7 +68,7 @@ static struct gpiochip *gpiochip_find(unsigned int pin)
|
|||
* @details
|
||||
*/
|
||||
|
||||
int getHwPinExt(unsigned int pin)
|
||||
int gpiochips_getPinOffset(unsigned int pin)
|
||||
{
|
||||
struct gpiochip *chip = gpiochip_find(pin);
|
||||
|
||||
|
@ -78,18 +78,36 @@ int getHwPinExt(unsigned int pin)
|
|||
return EFI_ERROR_CODE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Register gpiochip
|
||||
* @details return pin name or gpiochip name (if no pins names provided)
|
||||
* @brief Get external chip name
|
||||
* @details return gpiochip name
|
||||
*/
|
||||
|
||||
const char *portNameExt(unsigned int pin)
|
||||
const char *gpiochips_getChipName(unsigned int pin)
|
||||
{
|
||||
struct gpiochip *chip = gpiochip_find(pin);
|
||||
|
||||
if (chip)
|
||||
return chip->name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get external chip port name
|
||||
* @details return pin name or gpiochip name (if no pins names provided)
|
||||
*/
|
||||
|
||||
const char *gpiochips_getPinName(unsigned int pin)
|
||||
{
|
||||
int offset;
|
||||
struct gpiochip *chip = gpiochip_find(pin);
|
||||
|
||||
if (chip) {
|
||||
if (chip->gpio_names)
|
||||
return chip->gpio_names[pin - chip->base];
|
||||
offset = pin - chip->base;
|
||||
if ((chip->gpio_names) && (chip->gpio_names[offset]))
|
||||
return chip->gpio_names[offset];
|
||||
else
|
||||
return chip->name;
|
||||
}
|
||||
|
@ -142,6 +160,24 @@ int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, v
|
|||
return (chip->base);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set pins names for registered gpiochip
|
||||
* @details should be called after chip registration. May be called several times
|
||||
* Names array size should be aqual to chip gpio count
|
||||
*/
|
||||
|
||||
int gpiochips_setPinNames(brain_pin_e pin, const char **names)
|
||||
{
|
||||
struct gpiochip *chip = gpiochip_find(pin);
|
||||
|
||||
if (!chip)
|
||||
return -1;
|
||||
|
||||
chip->gpio_names = names;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init all registered gpiochips
|
||||
* @details will call gpiochip init ops for all registered chips
|
||||
|
@ -251,14 +287,21 @@ int gpiochips_get_total_pins(void)
|
|||
|
||||
#else /* BOARD_EXT_GPIOCHIPS > 0 */
|
||||
|
||||
int getHwPinExt(unsigned int pin)
|
||||
int gpiochips_getPinOffset(unsigned int pin)
|
||||
{
|
||||
(void)pin;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *portNameExt(unsigned int pin)
|
||||
const char *gpiochips_getChipName(unsigned int pin)
|
||||
{
|
||||
(void)pin;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *gpiochips_getPinName(unsigned int pin)
|
||||
{
|
||||
(void)pin;
|
||||
|
||||
|
@ -275,6 +318,13 @@ int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, v
|
|||
return 0;
|
||||
}
|
||||
|
||||
int gpiochips_setPinNames(brain_pin_e pin, const char **names)
|
||||
{
|
||||
(void)pin; (void)names;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpiochips_init(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -38,12 +38,16 @@ struct gpiochip_ops {
|
|||
int (*deinit)(void *data);
|
||||
};
|
||||
|
||||
int getHwPinExt(unsigned int pin);
|
||||
const char *portNameExt(unsigned int pin);
|
||||
int gpiochips_getPinOffset(unsigned int pin);
|
||||
const char *gpiochips_getChipName(unsigned int pin);
|
||||
const char *gpiochips_getPinName(unsigned int pin);
|
||||
|
||||
/* register gpio cgip */
|
||||
int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, void *priv);
|
||||
|
||||
/* Set individual names for pins */
|
||||
int gpiochips_setPinNames(brain_pin_e pin, const char **names);
|
||||
|
||||
/* gpio extenders subsystem init */
|
||||
int gpiochips_init(void);
|
||||
|
||||
|
|
|
@ -104,6 +104,13 @@ struct tle6240_priv {
|
|||
|
||||
static struct tle6240_priv chips[BOARD_TLE6240_COUNT];
|
||||
|
||||
static const char* tle6240_pin_names[TLE6240_OUTPUTS] = {
|
||||
"tle6240.OUT1", "tle6240.OUT2", "tle6240.OUT3", "tle6240.OUT4",
|
||||
"tle6240.OUT5", "tle6240.OUT6", "tle6240.OUT7", "tle6240.OUT8",
|
||||
"tle6240.OUT9", "tle6240.OUT10", "tle6240.OUT11", "tle6240.OUT12",
|
||||
"tle6240.OUT13", "tle6240.OUT14", "tle6240.OUT15", "tle6240.OUT16",
|
||||
};
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*==========================================================================*/
|
||||
|
@ -456,6 +463,7 @@ struct gpiochip_ops tle6240_ops = {
|
|||
int tle6240_add(unsigned int index, const struct tle6240_config *cfg)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
struct tle6240_priv *chip;
|
||||
|
||||
/* no config or no such chip */
|
||||
|
@ -485,7 +493,12 @@ int tle6240_add(unsigned int index, const struct tle6240_config *cfg)
|
|||
chip->drv_state = TLE6240_WAIT_INIT;
|
||||
|
||||
/* register, return gpio chip base */
|
||||
return gpiochip_register(DRIVER_NAME, &tle6240_ops, TLE6240_OUTPUTS, chip);
|
||||
ret = gpiochip_register(DRIVER_NAME, &tle6240_ops, TLE6240_OUTPUTS, chip);
|
||||
|
||||
/* set default pin names, board init code can rewrite */
|
||||
gpiochips_setPinNames(ret, tle6240_pin_names);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* BOARD_TLE6240_COUNT > 0 */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#if EFI_PROD_CODE
|
||||
#include "io_pins.h"
|
||||
#include "efi_gpio.h"
|
||||
#include "drivers/gpio/gpio_ext.h"
|
||||
|
||||
#include "pin_repository.h"
|
||||
#include "status_loop.h"
|
||||
|
@ -40,29 +41,48 @@ ioportid_t getHwPort(const char *msg, brain_pin_e brainPin) {
|
|||
}
|
||||
|
||||
bool efiReadPin(brain_pin_e pin) {
|
||||
return palReadPad(getHwPort("readPin", pin), getHwPin("readPin", pin));
|
||||
if (brain_pin_is_onchip(pin))
|
||||
return palReadPad(getHwPort("readPin", pin), getHwPin("readPin", pin));
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
else if (brain_pin_is_ext(pin))
|
||||
return (gpiochips_readPad(pin) > 0);
|
||||
#endif
|
||||
|
||||
/* incorrect pin */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method would set an error condition if pin is already used
|
||||
*/
|
||||
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode) {
|
||||
ioportid_t port = getHwPort(msg, brainPin);
|
||||
ioportmask_t pin = getHwPin(msg, brainPin);
|
||||
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
|
||||
{
|
||||
bool wasUsed;
|
||||
|
||||
if (port == GPIO_NULL) {
|
||||
return;
|
||||
//efiAssertVoid(OBD_PCM_Processor_Fault, pin != EFI_ERROR_CODE, "pin_error");
|
||||
|
||||
scheduleMsg(&logger, "%s on %s", msg, getBrain_pin_e(brainPin));
|
||||
|
||||
wasUsed = brain_pin_markUsed(brainPin, msg);
|
||||
|
||||
if (!wasUsed) {
|
||||
/*check if on-chip pin or external */
|
||||
if (brain_pin_is_onchip(brainPin)) {
|
||||
/* on-cip */
|
||||
ioportid_t port = getHwPort(msg, brainPin);
|
||||
ioportmask_t pin = getHwPin(msg, brainPin);
|
||||
/* paranoid */
|
||||
if (port == GPIO_NULL)
|
||||
return;
|
||||
|
||||
palSetPadMode(port, pin, mode);
|
||||
}
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
else {
|
||||
gpiochips_setPadMode(brainPin, mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
efiAssertVoid(OBD_PCM_Processor_Fault, pin != EFI_ERROR_CODE, "pin_error");
|
||||
|
||||
scheduleMsg(&logger, "%s on %s%d", msg, portname(port), pin);
|
||||
|
||||
bool wasUsed = gpio_pin_markUsed(port, pin, msg);
|
||||
if (wasUsed) {
|
||||
return;
|
||||
}
|
||||
|
||||
palSetPadMode(port, pin, mode);
|
||||
}
|
||||
|
||||
iomode_t getInputMode(pin_input_mode_e mode) {
|
||||
|
|
|
@ -15,6 +15,11 @@
|
|||
#include "eficonsole.h"
|
||||
#include "memstreams.h"
|
||||
#include "chprintf.h"
|
||||
#include "drivers/gpio/gpio_ext.h"
|
||||
|
||||
#ifndef BOARD_EXT_PINREPOPINS
|
||||
#define BOARD_EXT_PINREPOPINS 0
|
||||
#endif
|
||||
|
||||
static ioportid_t ports[] = {GPIOA,
|
||||
GPIOB,
|
||||
|
@ -44,7 +49,7 @@ static ioportid_t ports[] = {GPIOA,
|
|||
|
||||
#define PIN_REPO_SIZE (sizeof(ports) / sizeof(ports[0])) * PORT_SIZE
|
||||
// todo: move this into PinRepository class
|
||||
const char *PIN_USED[PIN_REPO_SIZE];
|
||||
const char *PIN_USED[PIN_REPO_SIZE + BOARD_EXT_PINREPOPINS];
|
||||
static int initialized = FALSE;
|
||||
|
||||
static LoggingWithStorage logger("pin repos");
|
||||
|
@ -110,15 +115,38 @@ static void reportPins(void) {
|
|||
unsigned int i;
|
||||
|
||||
for (i = 0; i < PIN_REPO_SIZE; i++) {
|
||||
const char *name = PIN_USED[i];
|
||||
int portIndex = i / PORT_SIZE;
|
||||
int pin = i % PORT_SIZE;
|
||||
ioportid_t port = ports[portIndex];
|
||||
if (name != NULL) {
|
||||
scheduleMsg(&logger, "pin %s%d: %s", portname(port), pin, name);
|
||||
const char *pin_user = PIN_USED[i];
|
||||
|
||||
/* show used pins */
|
||||
if (pin_user != NULL) {
|
||||
int portIndex = i / PORT_SIZE;
|
||||
int pin = i % PORT_SIZE;
|
||||
ioportid_t port = ports[portIndex];
|
||||
|
||||
scheduleMsg(&logger, "pin %s%d: %s\n", portname(port), pin, pin_user);
|
||||
}
|
||||
}
|
||||
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
for (i = PIN_REPO_SIZE ; i < PIN_REPO_SIZE + BOARD_EXT_PINREPOPINS /* gpiochips_get_total_pins()*/ ; i++) {
|
||||
const char *pin_name;
|
||||
const char *pin_user;
|
||||
brain_pin_e brainPin = index_to_brainPin(i);
|
||||
|
||||
pin_name = gpiochips_getPinName(brainPin);
|
||||
pin_user = PIN_USED[i];
|
||||
|
||||
/* here show all pins, unused too */
|
||||
if (pin_name != NULL) {
|
||||
scheduleMsg(&logger, "ext %s: %s\n",
|
||||
pin_name, pin_user ? pin_user : "free");
|
||||
} else {
|
||||
scheduleMsg(&logger, "ext %s.%d: %s\n",
|
||||
gpiochips_getChipName(brainPin), gpiochips_getPinOffset(brainPin), pin_user ? pin_user : "free");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
scheduleMsg(&logger, "Total pins count: %d", totalPinsUsed);
|
||||
}
|
||||
|
||||
|
@ -155,14 +183,25 @@ const char *hwPortname(brain_pin_e brainPin) {
|
|||
if (brainPin == GPIO_INVALID) {
|
||||
return "INVALID";
|
||||
}
|
||||
ioportid_t hwPort = getHwPort("hostname", brainPin);
|
||||
if (hwPort == GPIO_NULL) {
|
||||
return "NONE";
|
||||
}
|
||||
int hwPin = getHwPin("hostname", brainPin);
|
||||
portNameStream.eos = 0; // reset
|
||||
chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin);
|
||||
if (brain_pin_is_onchip(brainPin)) {
|
||||
int hwPin;
|
||||
|
||||
ioportid_t hwPort = getHwPort("hostname", brainPin);
|
||||
if (hwPort == GPIO_NULL) {
|
||||
return "NONE";
|
||||
}
|
||||
hwPin = getHwPin("hostname", brainPin);
|
||||
chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin);
|
||||
}
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
else {
|
||||
chprintf((BaseSequentialStream *) &portNameStream, "ext:%s.%d (%s)",
|
||||
gpiochips_getChipName(brainPin), gpiochips_getPinOffset(brainPin), gpiochips_getPinName(brainPin));
|
||||
}
|
||||
#endif
|
||||
portNameStream.buffer[portNameStream.eos] = 0; // need to terminate explicitly
|
||||
|
||||
return portNameBuffer;
|
||||
}
|
||||
|
||||
|
@ -176,6 +215,12 @@ void initPinRepository(void) {
|
|||
memset(PIN_USED, 0, sizeof(PIN_USED));
|
||||
|
||||
initialized = true;
|
||||
|
||||
#if (BOARD_EXT_GPIOCHIPS > 0)
|
||||
/* external chip init */
|
||||
gpiochips_init();
|
||||
#endif
|
||||
|
||||
addConsoleAction("pins", reportPins);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue