From b98ea17aeef1d39afe8ab290c3b6e0096d5d6986 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Sat, 25 May 2024 16:28:36 +0200 Subject: [PATCH] MK22: updated gpio driver --- platform/drivers/backlight/backlight_GDx.c | 3 +- platform/drivers/baseband/HR_C6000_GDx.cpp | 10 +- .../mcu/MK22FN512xxx12/drivers/gpio-native.h | 112 ++++++++++++++++ platform/mcu/MK22FN512xxx12/drivers/gpio.c | 123 ++++++++++-------- platform/targets/DM-1801/platform.c | 6 +- platform/targets/GD-77/platform.c | 6 +- 6 files changed, 191 insertions(+), 69 deletions(-) create mode 100644 platform/mcu/MK22FN512xxx12/drivers/gpio-native.h 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(); }