diff --git a/platform/drivers/backlight/backlight_GDx.c b/platform/drivers/backlight/backlight_GDx.c
index 4004f554..7d73ba66 100644
--- a/platform/drivers/backlight/backlight_GDx.c
+++ b/platform/drivers/backlight/backlight_GDx.c
@@ -38,8 +38,7 @@ void backlight_init()
FTM0->SC = FTM_SC_PS(3) /* Prescaler divide by 8 */
| FTM_SC_CLKS(1); /* Enable timer */
- gpio_setMode(LCD_BKLIGHT, OUTPUT);
- gpio_setAlternateFunction(LCD_BKLIGHT, 2);
+ gpio_setMode(LCD_BKLIGHT, OUTPUT | ALTERNATE_FUNC(4));
}
void backlight_terminate()
diff --git a/platform/drivers/baseband/HR_C6000_GDx.cpp b/platform/drivers/baseband/HR_C6000_GDx.cpp
index 4788b2bb..e7634540 100644
--- a/platform/drivers/baseband/HR_C6000_GDx.cpp
+++ b/platform/drivers/baseband/HR_C6000_GDx.cpp
@@ -171,13 +171,9 @@ template< class M >
void HR_Cx000< M >::uSpi_init()
{
gpio_setMode(DMR_CS, OUTPUT);
- gpio_setMode(DMR_CLK, OUTPUT);
- gpio_setMode(DMR_MOSI, OUTPUT);
- gpio_setMode(DMR_MISO, INPUT);
-
- gpio_setAlternateFunction(DMR_CLK, 0);
- gpio_setAlternateFunction(DMR_MOSI, 0);
- gpio_setAlternateFunction(DMR_MISO, 0);
+ gpio_setMode(DMR_CLK, OUTPUT | ALTERNATE_FUNC(2));
+ gpio_setMode(DMR_MOSI, OUTPUT | ALTERNATE_FUNC(2));
+ gpio_setMode(DMR_MISO, INPUT | ALTERNATE_FUNC(2));
SIM->SCGC6 |= SIM_SCGC6_SPI0_MASK;
diff --git a/platform/mcu/MK22FN512xxx12/drivers/gpio-native.h b/platform/mcu/MK22FN512xxx12/drivers/gpio-native.h
new file mode 100644
index 00000000..f5e864c5
--- /dev/null
+++ b/platform/mcu/MK22FN512xxx12/drivers/gpio-native.h
@@ -0,0 +1,112 @@
+/***************************************************************************
+ * Copyright (C) 2024 by Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program 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 General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#ifndef GPIO_NATIVE_H
+#define GPIO_NATIVE_H
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * This file provides the interface for MK22 gpio.
+ */
+
+/**
+ * Maximum GPIO switching speed.
+ * For more details see microcontroller's reference manual and datasheet.
+ */
+enum Speed
+{
+ SLOW = 0x0, ///< 2MHz
+ FAST = 0x1 ///< 50MHz
+};
+
+/**
+ * MK22 gpio devices
+ */
+extern const struct gpioDev GpioA;
+extern const struct gpioDev GpioB;
+extern const struct gpioDev GpioC;
+extern const struct gpioDev GpioD;
+extern const struct gpioDev GpioE;
+
+/**
+ * Configure gpio pin functional mode.
+ *
+ * @param port: gpio port.
+ * @param pin: gpio pin number, between 0 and 15.
+ * @param mode: bit 7:0 set gpio functional mode, bit 15:8 manage gpio alternate
+ * function mapping.
+ */
+void gpio_setMode(const void *port, const uint8_t pin, const uint16_t mode);
+
+/**
+ * Configure gpio pin maximum output speed.
+ *
+ * @param port: gpio port.
+ * @param pin: gpio pin number, between 0 and 15.
+ * @param spd: gpio output speed to be set.
+ */
+void gpio_setOutputSpeed(const void *port, const uint8_t pin, const enum Speed spd);
+
+/**
+ * Set gpio pin to high logic level.
+ * NOTE: this operation is performed atomically.
+ *
+ * @param port: gpio port.
+ * @param pin: gpio pin number, between 0 and 15.
+ */
+static inline void gpio_setPin(const void *port, const uint8_t pin)
+{
+ ((GPIO_Type *)(port))->PSOR = (1 << pin);
+}
+
+/**
+ * Set gpio pin to low logic level.
+ * NOTE: this operation is performed atomically.
+ *
+ * @param port: gpio port.
+ * @param pin: gpio pin number, between 0 and 15.
+ */
+static inline void gpio_clearPin(const void *port, const uint8_t pin)
+{
+ ((GPIO_Type *)(port))->PCOR = (1 << pin);
+}
+
+/**
+ * Read gpio pin's logic level.
+ *
+ * @param port: gpio port.
+ * @param pin: gpio pin number, between 0 and 15.
+ * @return 1 if pin is at high logic level, 0 if pin is at low logic level.
+ */
+static inline uint8_t gpio_readPin(const void *port, const uint8_t pin)
+{
+ GPIO_Type *g = (GPIO_Type *)(port);
+ return ((g->PDIR & (1 << pin)) != 0) ? 1 : 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GPIO_NATIVE_H */
diff --git a/platform/mcu/MK22FN512xxx12/drivers/gpio.c b/platform/mcu/MK22FN512xxx12/drivers/gpio.c
index 4f8b6b37..9223632c 100644
--- a/platform/mcu/MK22FN512xxx12/drivers/gpio.c
+++ b/platform/mcu/MK22FN512xxx12/drivers/gpio.c
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2020 - 2023 by Silvano Seva IU2KWO *
+ * Copyright (C) 2020 - 2024 by Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@@ -14,9 +14,9 @@
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see *
***************************************************************************/
-
+#include
#include "MK22F51212.h"
-#include
+#include "gpio-native.h"
/*
* MK22 GPIO management is a bit convoluted: instead of having all the registers
@@ -29,7 +29,7 @@
* PORT one. Ah, and, of course, this cannot be made using simple pointer
* addition/subtraction/multiplication...
*/
-PORT_Type *getPortFromGPio(const GPIO_Type *gpio)
+static PORT_Type *getPortFromGPio(const GPIO_Type *gpio)
{
PORT_Type *port;
@@ -63,52 +63,54 @@ PORT_Type *getPortFromGPio(const GPIO_Type *gpio)
return port;
}
-void gpio_setMode(void *port, uint8_t pin, enum Mode mode)
+void gpio_setMode(const void *port, const uint8_t pin, const uint16_t mode)
{
GPIO_Type *g = (GPIO_Type *)(port);
PORT_Type *p = getPortFromGPio(g);
- /* Clear previous settings */
- g->PDDR &= ~(1 << pin);
- p->PCR[pin] = 0;
-
- switch(mode)
+ switch(mode & 0xFF)
{
case INPUT:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- g->PDDR &= ~(1 << pin); /* Input mode */
+ p->PCR[pin] = PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
+ g->PDDR &= ~(1 << pin); /* Input mode */
break;
case INPUT_PULL_UP:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- p->PCR[pin] |= PORT_PCR_PS(1); /* Pull up mode */
- p->PCR[pin] |= PORT_PCR_PE(1); /* Pull up/down enable */
- g->PDDR &= ~(1 << pin); /* Input mode */
+ p->PCR[pin] = PORT_PCR_MUX(1) /* Enable pin in GPIO mode */
+ | PORT_PCR_PS(1) /* Pull up mode */
+ | PORT_PCR_PE(1); /* Pull up/down enable */
+ g->PDDR &= ~(1 << pin); /* Input mode */
break;
case INPUT_PULL_DOWN:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- p->PCR[pin] &= ~PORT_PCR_PS(1); /* Pull down mode */
- p->PCR[pin] |= PORT_PCR_PE(1); /* Pull up/down enable */
- g->PDDR &= ~(1 << pin); /* Input mode */
+ p->PCR[pin] = PORT_PCR_MUX(1) /* Enable pin in GPIO mode */
+ | PORT_PCR_PE(1); /* Pull up/down enable */
+ g->PDDR &= ~(1 << pin); /* Input mode */
break;
- /*
- * case INPUT_ANALOG:
- * NOTE: analog input mode unimplemented here for hardware structure
- * reasons.
- */
+ case ANALOG:
+ p->PCR[pin] = PORT_PCR_MUX(0); /* Enable pin in AF0 mode */
+ g->PDDR &= ~(1 << pin); /* Input mode */
+ break;
case OUTPUT:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- g->PDDR |= (1 << pin); /* Output mode */
+ p->PCR[pin] = PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
+ g->PDDR |= (1 << pin); /* Output mode */
break;
case OPEN_DRAIN:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- p->PCR[pin] |= PORT_PCR_ODE(1); /* Enable open drain mode */
- g->PDDR |= (1 << pin); /* Output mode */
+ p->PCR[pin] = PORT_PCR_MUX(1) /* Enable pin in GPIO mode */
+ | PORT_PCR_ODE(1); /* Enable open drain mode */
+ g->PDDR |= (1 << pin); /* Output mode */
+ break;
+
+ case OPEN_DRAIN_PU:
+ p->PCR[pin] = PORT_PCR_MUX(1) /* Enable pin in GPIO mode */
+ | PORT_PCR_ODE(1) /* Enable open drain mode */
+ | PORT_PCR_PS(1) /* Pull up mode */
+ | PORT_PCR_PE(1); /* Pull up/down enable */
+ g->PDDR |= (1 << pin); /* Output mode */
break;
/*
@@ -124,27 +126,25 @@ void gpio_setMode(void *port, uint8_t pin, enum Mode mode)
*/
default:
- p->PCR[pin] |= PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
- g->PDDR &= ~(1 << pin); /* Input mode */
+ p->PCR[pin] = PORT_PCR_MUX(1); /* Enable pin in GPIO mode */
+ g->PDDR &= ~(1 << pin); /* Input mode */
break;
}
+
+ uint8_t af = (mode >> 8) & 0xFF;
+ if(af > 1)
+ {
+ p->PCR[pin] &= ~PORT_PCR_MUX_MASK; /* Clear old configuration */
+ p->PCR[pin] |= PORT_PCR_MUX(af); /* Set new AF, range 0 - 7 */
+ }
}
-void gpio_setAlternateFunction(void *port, uint8_t pin, uint8_t afNum)
+void gpio_setOutputSpeed(const void *port, uint8_t pin, enum Speed spd)
{
GPIO_Type *g = (GPIO_Type *)(port);
PORT_Type *p = getPortFromGPio(g);
- p->PCR[pin] &= ~PORT_PCR_MUX_MASK; /* Clear old configuration */
- p->PCR[pin] |= PORT_PCR_MUX(2 + afNum); /* Set new AF, range 0 - 7 */
-}
-
-void gpio_setOutputSpeed(void *port, uint8_t pin, enum Speed spd)
-{
- GPIO_Type *g = (GPIO_Type *)(port);
- PORT_Type *p = getPortFromGPio(g);
-
- if(spd >= FAST)
+ if(spd == FAST)
{
p->PCR[pin] |= PORT_PCR_SRE(1);
}
@@ -154,23 +154,42 @@ void gpio_setOutputSpeed(void *port, uint8_t pin, enum Speed spd)
}
}
-void gpio_setPin(void *port, uint8_t pin)
+static int gpioApi_mode(const struct gpioDev *dev, const uint8_t pin,
+ const uint16_t mode)
{
- ((GPIO_Type *)(port))->PSOR = (1 << pin);
+ if(pin > 15)
+ return -EINVAL;
+
+ gpio_setMode((void *) dev->priv, pin, mode);
+ return 0;
}
-void gpio_clearPin(void *port, uint8_t pin)
+static void gpioApi_set(const struct gpioDev *dev, const uint8_t pin)
{
- ((GPIO_Type *)(port))->PCOR = (1 << pin);
+ gpio_setPin((void *) dev->priv, pin);
}
-void gpio_togglePin(void *port, uint8_t pin)
+static void gpioApi_clear(const struct gpioDev *dev, const uint8_t pin)
{
- ((GPIO_Type *)(port))->PTOR ^= (1 << pin);
+ gpio_clearPin((void *) dev->priv, pin);
}
-uint8_t gpio_readPin(const void *port, uint8_t pin)
+static bool gpioApi_read(const struct gpioDev *dev, const uint8_t pin)
{
- GPIO_Type *g = (GPIO_Type *)(port);
- return ((g->PDIR & (1 << pin)) != 0) ? 1 : 0;
+ uint8_t val = gpio_readPin(dev->priv, pin);
+ return (val != 0) ? true : false;
}
+
+static const struct gpioApi gpioApi =
+{
+ .mode = gpioApi_mode,
+ .set = gpioApi_set,
+ .clear = gpioApi_clear,
+ .read = gpioApi_read
+};
+
+const struct gpioDev GpioA = { .api = &gpioApi, .priv = GPIOA };
+const struct gpioDev GpioB = { .api = &gpioApi, .priv = GPIOB };
+const struct gpioDev GpioC = { .api = &gpioApi, .priv = GPIOC };
+const struct gpioDev GpioD = { .api = &gpioApi, .priv = GPIOD };
+const struct gpioDev GpioE = { .api = &gpioApi, .priv = GPIOE };
diff --git a/platform/targets/DM-1801/platform.c b/platform/targets/DM-1801/platform.c
index dd2b4288..e12da75a 100644
--- a/platform/targets/DM-1801/platform.c
+++ b/platform/targets/DM-1801/platform.c
@@ -67,10 +67,8 @@ void platform_init()
/*
* Initialise I2C driver, once for all the modules
*/
- gpio_setMode(I2C_SDA, OPEN_DRAIN);
- gpio_setMode(I2C_SCL, OPEN_DRAIN);
- gpio_setAlternateFunction(I2C_SDA, 3);
- gpio_setAlternateFunction(I2C_SCL, 3);
+ gpio_setMode(I2C_SDA, OPEN_DRAIN | ALTERNATE_FUNC(5));
+ gpio_setMode(I2C_SCL, OPEN_DRAIN | ALTERNATE_FUNC(5));
i2c0_init();
}
diff --git a/platform/targets/GD-77/platform.c b/platform/targets/GD-77/platform.c
index 4da8f5bc..22688eeb 100644
--- a/platform/targets/GD-77/platform.c
+++ b/platform/targets/GD-77/platform.c
@@ -67,10 +67,8 @@ void platform_init()
/*
* Initialise I2C driver, once for all the modules
*/
- gpio_setMode(I2C_SDA, OPEN_DRAIN);
- gpio_setMode(I2C_SCL, OPEN_DRAIN);
- gpio_setAlternateFunction(I2C_SDA, 3);
- gpio_setAlternateFunction(I2C_SCL, 3);
+ gpio_setMode(I2C_SDA, OPEN_DRAIN | ALTERNATE_FUNC(5));
+ gpio_setMode(I2C_SCL, OPEN_DRAIN | ALTERNATE_FUNC(5));
i2c0_init();
}