[PATCH v5 4/4] bsps/stm32f4: Implementation for GPIO and ADC
Duc Doan
dtbpkmte at gmail.com
Sun Jul 24 12:01:11 UTC 2022
---
bsps/arm/stm32f4/adc/adc.c | 655 ++++++++++++++++++
bsps/arm/stm32f4/gpio/gpio.c | 542 +++++++++++++++
bsps/arm/stm32f4/include/bsp.h | 4 -
bsps/arm/stm32f4/include/bsp/stm32f4_adc.h | 209 ++++++
bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h | 273 ++++++++
bsps/arm/stm32f4/include/bsp/stm32f4_hal.h | 17 +
bsps/arm/stm32f4/include/bsp/stm32f4_periph.h | 50 ++
bsps/arm/stm32f4/start/bspstart.c | 7 +-
bsps/arm/stm32f4/start/bspstarthook.c | 8 +
bsps/arm/stm32f4/start/periph.c | 58 ++
spec/build/bsps/arm/stm32f4/grp.yml | 6 +-
spec/build/bsps/arm/stm32f4/obj.yml | 5 +
spec/build/bsps/arm/stm32f4/optengpio.yml | 16 +
.../build/bsps/arm/stm32f4/optnumgpioctrl.yml | 16 +
14 files changed, 1856 insertions(+), 10 deletions(-)
create mode 100644 bsps/arm/stm32f4/adc/adc.c
create mode 100644 bsps/arm/stm32f4/gpio/gpio.c
create mode 100644 bsps/arm/stm32f4/include/bsp/stm32f4_adc.h
create mode 100644 bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
create mode 100644 bsps/arm/stm32f4/include/bsp/stm32f4_hal.h
create mode 100644 bsps/arm/stm32f4/include/bsp/stm32f4_periph.h
create mode 100644 bsps/arm/stm32f4/start/periph.c
create mode 100644 spec/build/bsps/arm/stm32f4/optengpio.yml
create mode 100644 spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml
diff --git a/bsps/arm/stm32f4/adc/adc.c b/bsps/arm/stm32f4/adc/adc.c
new file mode 100644
index 0000000000..21baa9ee2c
--- /dev/null
+++ b/bsps/arm/stm32f4/adc/adc.c
@@ -0,0 +1,655 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/stm32f4_adc.h>
+#include <bsp/stm32f4_gpio.h>
+#include <stdlib.h>
+
+#if defined(ADC3)
+#define NUM_ADC 3
+#elif defined(ADC2)
+#define NUM_ADC 2
+#else
+#define NUM_ADC 1
+#endif
+
+/************** Interrupt manager *****************/
+typedef struct {
+ void *arg;
+ stm32f4_gpio *gpio;
+} stm32f4_interrupt_arg;
+
+typedef struct {
+ stm32f4_interrupt_arg arg;
+ rtems_gpio_isr isr;
+} stm32f4_interrupt;
+
+void adc_irq_handler(void *arg);
+
+static stm32f4_interrupt isr_table[NUM_ADC];
+
+/**
+ * This tells if there is already an ISR registered at each
+ * table index (element set to true).
+ */
+static bool isr_registered[NUM_ADC] = {0};
+
+typedef struct {
+ uint32_t adc_value;
+ rtems_adc_status status;
+} stm32f4_adc_data;
+static stm32f4_adc_data adc_data[NUM_ADC] = {0};
+
+static rtems_status_code stm32f4_adc_select_channel(
+ rtems_gpio *base
+);
+
+/***************/
+#ifdef ADC1
+static ADC_TypeDef_Protected _ADC1_protected = { ADC1, false };
+ADC_TypeDef_Protected *const ADC1_protected = &_ADC1_protected;
+#endif
+#ifdef ADC2
+static ADC_TypeDef_Protected _ADC2_protected = { ADC2, false };
+ADC_TypeDef_Protected *const ADC2_protected = &_ADC2_protected;
+#endif
+#ifdef ADC3
+static ADC_TypeDef_Protected _ADC3_protected = { ADC3, false };
+ADC_TypeDef_Protected *const ADC3_protected = &_ADC3_protected;
+#endif
+
+/* Helpers */
+#define STM32F4_GET_ADC_NUMBER(ADCx) \
+ ( (uintptr_t) ( ADCx ) == (uintptr_t) ADC1 ? 1 : \
+ (uintptr_t) ( ADCx ) == (uintptr_t) ADC2 ? 2 : \
+ (uintptr_t) ( ADCx ) == (uintptr_t) ADC3 ? 3 : \
+ 0 )
+#define STM32F4_GET_ADCx_FROM_NUMBER(num) (\
+ ( num ) == 1 ? ADC1 : \
+ ( num ) == 2 && NUM_ADC >= 2 ? ADC2 : \
+ ( num ) == 3 && NUM_ADC == 3 ? ADC3 : \
+ NULL)
+#define STM32F4_GET_ADCx_PROTECTED_FROM_NUMBER(num) (\
+ ( num ) == 1 ? ADC1_protected : \
+ ( num ) == 2 && NUM_ADC >= 2 ? ADC2_protected : \
+ ( num ) == 3 && NUM_ADC == 3 ? ADC3_protected : \
+ NULL)
+
+// TODO: other variants
+ADC_TypeDef *stm32f4_get_ADCx(
+ GPIO_TypeDef *gpio
+)
+{
+ switch ((uintptr_t) gpio) {
+#if defined(STM32F405xx) || defined(STM32F407xx)
+ case (uintptr_t) GPIOA:
+ case (uintptr_t) GPIOB:
+ case (uintptr_t) GPIOC:
+ return ADC1;
+ case (uintptr_t) GPIOF:
+ return ADC3;
+#endif /* defined(STM32F405xx) || defined(STM32F407xx) */
+ default:
+ return NULL;
+ }
+}
+
+// TODO: other variants
+ADC_TypeDef_Protected *stm32f4_get_ADCx_protected(
+ GPIO_TypeDef *gpio
+)
+{
+ switch ((uintptr_t) gpio) {
+#if defined(STM32F405xx) || defined(STM32F407xx)
+ case (uintptr_t) GPIOA:
+ case (uintptr_t) GPIOB:
+ case (uintptr_t) GPIOC:
+ return ADC1_protected;
+ case (uintptr_t) GPIOF:
+ return ADC3_protected;
+#endif /* defined(STM32F405xx) || defined(STM32F407xx) */
+ default:
+ return NULL;
+ }
+}
+
+// TODO: other variants
+rtems_status_code stm32f4_get_LL_ADC_CHANNEL(
+ stm32f4_gpio *gpio,
+ uint32_t *channel
+)
+{
+ uintptr_t port = (uintptr_t) gpio->port;
+#if defined(STM32F405xx) || defined(STM32F407xx)
+ if (port == (uintptr_t) GPIOA) {
+ switch (gpio->pin) {
+ case 0:
+ *channel = LL_ADC_CHANNEL_0;
+ break;
+ case 1:
+ *channel = LL_ADC_CHANNEL_1;
+ break;
+ case 2:
+ *channel = LL_ADC_CHANNEL_2;
+ break;
+ case 3:
+ *channel = LL_ADC_CHANNEL_3;
+ break;
+ case 4:
+ *channel = LL_ADC_CHANNEL_4;
+ break;
+ case 5:
+ *channel = LL_ADC_CHANNEL_5;
+ break;
+ case 6:
+ *channel = LL_ADC_CHANNEL_6;
+ break;
+ case 7:
+ *channel = LL_ADC_CHANNEL_7;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ }
+ else if (port == (uintptr_t) GPIOB) {
+ switch (gpio->pin) {
+ case 0:
+ *channel = LL_ADC_CHANNEL_8;
+ break;
+ case 1:
+ *channel = LL_ADC_CHANNEL_9;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ }
+ else if (port == (uintptr_t) GPIOC) {
+ switch (gpio->pin) {
+ case 0:
+ *channel = LL_ADC_CHANNEL_10;
+ break;
+ case 1:
+ *channel = LL_ADC_CHANNEL_11;
+ break;
+ case 2:
+ *channel = LL_ADC_CHANNEL_12;
+ break;
+ case 3:
+ *channel = LL_ADC_CHANNEL_13;
+ break;
+ case 4:
+ *channel = LL_ADC_CHANNEL_14;
+ break;
+ case 5:
+ *channel = LL_ADC_CHANNEL_15;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ }
+ else if (port == (uintptr_t) GPIOF) {
+ switch (gpio->pin) {
+ case 3:
+ *channel = LL_ADC_CHANNEL_9;
+ break;
+ case 4:
+ *channel = LL_ADC_CHANNEL_14;
+ break;
+ case 5:
+ *channel = LL_ADC_CHANNEL_15;
+ break;
+ case 6:
+ *channel = LL_ADC_CHANNEL_4;
+ break;
+ case 7:
+ *channel = LL_ADC_CHANNEL_5;
+ break;
+ case 8:
+ *channel = LL_ADC_CHANNEL_6;
+ break;
+ case 9:
+ *channel = LL_ADC_CHANNEL_7;
+ break;
+ case 10:
+ *channel = LL_ADC_CHANNEL_8;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ }
+ else
+ return RTEMS_UNSATISFIED;
+#endif /* defined(STM32F405xx) || defined(STM32F407xx) */
+ return RTEMS_SUCCESSFUL;
+}
+
+bool stm32f4_is_adc_pin(
+ stm32f4_gpio *gpio
+)
+{
+ uint32_t tmp;
+ return stm32f4_get_LL_ADC_CHANNEL(gpio, &tmp) == RTEMS_SUCCESSFUL;
+}
+
+static const rtems_adc_api stm32f4_adc_base_api =
+ RTEMS_ADC_BUILD_API(
+ stm32f4_adc_init,
+ stm32f4_adc_read_raw,
+ stm32f4_adc_start_read_raw_nb,
+ stm32f4_adc_read_raw_nb,
+ stm32f4_adc_set_resolution,
+ stm32f4_adc_set_alignment,
+ stm32f4_adc_configure_interrupt,
+ stm32f4_adc_remove_interrupt,
+ stm32f4_adc_enable_interrupt,
+ stm32f4_adc_disable_interrupt
+ );
+
+rtems_periph_api *stm32f4_adc_get(
+ rtems_gpio *pin
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(pin);
+ uint32_t channel;
+ // if the pin does not have ADC functionality
+ if (stm32f4_get_LL_ADC_CHANNEL(gpio, &channel) != RTEMS_SUCCESSFUL) {
+ return NULL;
+ }
+
+ // First allocate space for stm32f4_adc object
+ stm32f4_adc *api = malloc(sizeof(stm32f4_adc));
+ if (api == NULL) {
+ return NULL;
+ }
+ api->base_api = stm32f4_adc_base_api;
+
+ // Then allocate space for stm32f4_adc_config object
+ api->adc_config = malloc(sizeof(stm32f4_adc_config));
+ if (api->adc_config == NULL) {
+ return NULL;
+ }
+ api->adc_config->ADCx = stm32f4_get_ADCx_protected(gpio->port);
+ api->adc_config->channel = channel;
+ api->adc_config->resolution = STM32F4_ADC_DEFAULT_RESOLUTION;
+ api->adc_config->alignment = STM32F4_ADC_DEFAULT_ALIGNMENT;
+ api->adc_config->locked = false;
+ return (rtems_periph_api *) api;
+}
+
+rtems_status_code stm32f4_adc_destroy(
+ rtems_gpio *pin
+)
+{
+ if (pin->api != NULL) {
+ free(((stm32f4_adc *) pin->api)->adc_config);
+ free(pin->api);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+static rtems_status_code stm32f4_adc_select_channel(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!STM32F4_IS_LOCKED(adc_config) &&
+ !STM32F4_IS_LOCKED(adc_config->ADCx)) {
+ STM32F4_LOCK(adc_config);
+ STM32F4_LOCK(adc_config->ADCx);
+
+ LL_ADC_Disable(adc_config->ADCx->ADCx);
+
+ LL_ADC_SetResolution(adc_config->ADCx->ADCx, adc_config->resolution);
+ LL_ADC_SetDataAlignment(adc_config->ADCx->ADCx, adc_config->alignment);
+ LL_ADC_REG_SetSequencerRanks(
+ adc_config->ADCx->ADCx,
+ LL_ADC_REG_RANK_1,
+ adc_config->channel
+ );
+ LL_ADC_SetChannelSamplingTime(
+ adc_config->ADCx->ADCx,
+ adc_config->channel,
+ STM32F4_ADC_DEFAULT_SAMPLINGTIME
+ );
+
+ LL_ADC_Enable(adc_config->ADCx->ADCx);
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ volatile uint32_t counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U));
+ while(counter != 0U)
+ {
+ counter--;
+ }
+
+ STM32F4_UNLOCK(adc_config);
+ STM32F4_UNLOCK(adc_config->ADCx);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+void stm32f4_adc_start(
+ void
+)
+{
+ // Install ISR for non-blocking read
+ rtems_status_code sc = rtems_interrupt_handler_install(
+ ADC_IRQn,
+ NULL,
+ RTEMS_INTERRUPT_SHARED,
+ adc_irq_handler,
+ NULL
+ );
+ while (sc != RTEMS_SUCCESSFUL);
+}
+RTEMS_SYSINIT_ITEM(
+ stm32f4_adc_start,
+ RTEMS_SYSINIT_DEVICE_DRIVERS,
+ RTEMS_SYSINIT_ORDER_LAST
+);
+
+void stm32f4_adc_init(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!LL_ADC_IsEnabled(adc_config->ADCx->ADCx)) {
+ // Enable clock
+ switch ((uintptr_t) adc_config->ADCx->ADCx) {
+#ifdef ADC1
+ case (uintptr_t) ADC1:
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC1);
+ break;
+#endif
+#ifdef ADC2
+ case (uintptr_t) ADC2:
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC2);
+ break;
+#endif
+#ifdef ADC3
+ case (uintptr_t) ADC3:
+ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC3);
+ break;
+#endif
+ default:
+ return;
+ }
+
+ // ADC common setup
+ LL_ADC_SetSequencersScanMode(adc_config->ADCx->ADCx, LL_ADC_SEQ_SCAN_DISABLE);
+ LL_ADC_REG_SetTriggerSource(adc_config->ADCx->ADCx, LL_ADC_REG_TRIG_SOFTWARE);
+ LL_ADC_REG_SetSequencerLength(adc_config->ADCx->ADCx, LL_ADC_REG_SEQ_SCAN_DISABLE);
+ LL_ADC_REG_SetSequencerDiscont(adc_config->ADCx->ADCx, LL_ADC_REG_SEQ_DISCONT_DISABLE);
+ LL_ADC_REG_SetContinuousMode(adc_config->ADCx->ADCx, LL_ADC_REG_CONV_SINGLE);
+ LL_ADC_REG_SetDMATransfer(adc_config->ADCx->ADCx, LL_ADC_REG_DMA_TRANSFER_NONE);
+
+ LL_ADC_REG_SetFlagEndOfConversion(adc_config->ADCx->ADCx, LL_ADC_REG_FLAG_EOC_UNITARY_CONV);
+
+ LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(adc_config->ADCx->ADCx), LL_ADC_CLOCK_SYNC_PCLK_DIV2);
+ LL_ADC_SetMultimode(__LL_ADC_COMMON_INSTANCE(adc_config->ADCx->ADCx), LL_ADC_MULTI_INDEPENDENT);
+
+ LL_ADC_Enable(adc_config->ADCx->ADCx);
+ /* Delay for ADC stabilization time */
+ /* Compute number of CPU cycles to wait for */
+ volatile uint32_t counter = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U));
+ while(counter != 0U)
+ {
+ counter--;
+ }
+ }
+}
+
+rtems_status_code stm32f4_adc_read_raw(
+ rtems_gpio *base,
+ uint32_t *result,
+ uint32_t timeout
+)
+{
+ uint32_t tickstart = 0U;
+ rtems_status_code sc = stm32f4_adc_select_channel(base);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ STM32F4_LOCK(adc_config->ADCx);
+ STM32F4_LOCK(adc_config);
+ LL_ADC_REG_StartConversionSWStart(adc_config->ADCx->ADCx);
+ while (!LL_ADC_IsActiveFlag_EOCS(adc_config->ADCx->ADCx)) {
+ if (timeout != RTEMS_ADC_NO_TIMEOUT) {
+ if (timeout == 0U || ((HAL_GetTick() - tickstart) > timeout)) {
+ if (!LL_ADC_IsActiveFlag_EOCS(adc_config->ADCx->ADCx)) {
+ return RTEMS_TIMEOUT;
+ }
+ }
+ }
+ }
+ *result = LL_ADC_REG_ReadConversionData32(adc_config->ADCx->ADCx);
+ STM32F4_UNLOCK(adc_config->ADCx);
+ STM32F4_UNLOCK(adc_config);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_adc_start_read_raw_nb(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ unsigned int adc_idx = STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1;
+ if (adc_data[adc_idx].status == RTEMS_ADC_NOT_STARTED) {
+ // start conversion here
+ rtems_status_code sc = stm32f4_adc_select_channel(base);
+ if (sc != RTEMS_SUCCESSFUL) {
+ return sc;
+ }
+ STM32F4_LOCK(adc_config);
+ STM32F4_LOCK(adc_config->ADCx);
+ LL_ADC_EnableIT_EOCS(adc_config->ADCx->ADCx);
+ LL_ADC_REG_StartConversionSWStart(adc_config->ADCx->ADCx);
+ adc_data[adc_idx].status = RTEMS_ADC_NOT_READY;
+
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+rtems_adc_status stm32f4_adc_read_raw_nb(
+ rtems_gpio *base,
+ uint32_t *result
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ unsigned int adc_idx = STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1;
+ rtems_adc_status ret = adc_data[adc_idx].status;
+ if (ret == RTEMS_ADC_READY) {
+ *result = adc_data[adc_idx].adc_value;
+ adc_data[adc_idx].status = RTEMS_ADC_NOT_STARTED;
+
+ STM32F4_UNLOCK(adc_config->ADCx);
+ STM32F4_UNLOCK(adc_config);
+ }
+ return ret;
+}
+
+rtems_status_code stm32f4_adc_set_resolution(
+ rtems_gpio *base,
+ unsigned int bits
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!STM32F4_IS_LOCKED(adc_config)) {
+ STM32F4_LOCK(adc_config);
+ switch (bits) {
+ case 12:
+ adc_config->resolution = LL_ADC_RESOLUTION_12B;
+ break;
+ case 10:
+ adc_config->resolution = LL_ADC_RESOLUTION_10B;
+ break;
+ case 8:
+ adc_config->resolution = LL_ADC_RESOLUTION_8B;
+ break;
+ case 6:
+ adc_config->resolution = LL_ADC_RESOLUTION_6B;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ STM32F4_UNLOCK(adc_config);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_RESOURCE_IN_USE;
+}
+
+rtems_status_code stm32f4_adc_set_alignment(
+ rtems_gpio *base,
+ rtems_adc_align align
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!STM32F4_IS_LOCKED(adc_config)) {
+ STM32F4_LOCK(adc_config);
+ switch (align) {
+ case RTEMS_ADC_ALIGN_LEFT:
+ adc_config->alignment = LL_ADC_DATA_ALIGN_LEFT;
+ break;
+ case RTEMS_ADC_ALIGN_RIGHT:
+ adc_config->alignment = LL_ADC_DATA_ALIGN_RIGHT;
+ break;
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ STM32F4_UNLOCK(adc_config);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_RESOURCE_IN_USE;
+}
+
+rtems_status_code stm32f4_adc_configure_interrupt(
+ rtems_gpio *base,
+ rtems_adc_isr isr,
+ void *arg
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ unsigned int adc_idx = STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1;
+ if (!isr_registered[adc_idx]) {
+ isr_table[adc_idx] = (stm32f4_interrupt){
+ .arg = {
+ .arg = arg,
+ .gpio = gpio
+ },
+ .isr = isr
+ };
+ isr_registered[adc_idx] = true;
+ return rtems_interrupt_handler_install(
+ ADC_IRQn,
+ NULL,
+ RTEMS_INTERRUPT_SHARED,
+ adc_irq_handler,
+ &isr_table[adc_idx].arg
+ );
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+rtems_status_code stm32f4_adc_remove_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ unsigned int adc_idx = STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1;
+ rtems_status_code sc = rtems_interrupt_handler_remove(
+ ADC_IRQn,
+ adc_irq_handler,
+ &isr_table[adc_idx].arg
+ );
+ if (sc == RTEMS_SUCCESSFUL) {
+ isr_registered[adc_idx] = false;
+ }
+ return sc;
+}
+
+rtems_status_code stm32f4_adc_enable_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!STM32F4_IS_LOCKED(adc_config->ADCx)) {
+ if (isr_registered[STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1]) {
+ LL_ADC_EnableIT_EOCS(adc_config->ADCx->ADCx);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+ }
+ return RTEMS_RESOURCE_IN_USE;
+}
+
+rtems_status_code stm32f4_adc_disable_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_adc_config *adc_config = ((stm32f4_adc *) base->api)->adc_config;
+ if (!STM32F4_IS_LOCKED(adc_config->ADCx)) {
+ if (isr_registered[STM32F4_GET_ADC_NUMBER(adc_config->ADCx->ADCx) - 1]) {
+ LL_ADC_DisableIT_EOCS(adc_config->ADCx->ADCx);
+ return RTEMS_SUCCESSFUL;
+ }
+ return RTEMS_UNSATISFIED;
+ }
+ return RTEMS_RESOURCE_IN_USE;
+}
+
+void adc_irq_handler(void *arg) {
+ rtems_interrupt_level level;
+ rtems_interrupt_disable( level );
+ unsigned int i;
+ for (i = 0; i < NUM_ADC; ++i) {
+ ADC_TypeDef *adcx = STM32F4_GET_ADCx_FROM_NUMBER(i+1);
+ if (LL_ADC_IsActiveFlag_EOCS(adcx)) {
+ // if the current IRQ has no ISR registered,
+ // it means the IRQ happens from a non-blocking read
+ if (!isr_registered[i]) {
+ if (adc_data[i].status == RTEMS_ADC_NOT_READY) {
+ LL_ADC_DisableIT_EOCS(adcx);
+ adc_data[i].adc_value = LL_ADC_REG_ReadConversionData32(adcx);
+ adc_data[i].status = RTEMS_ADC_READY;
+ }
+ }
+ // if there is an ISR registered, call it
+ else {
+ LL_ADC_ClearFlag_EOCS(adcx);
+ stm32f4_interrupt_arg *stm32_arg = (stm32f4_interrupt_arg *) arg;
+ (*isr_table[i].isr)(stm32_arg->arg);
+ }
+ break;
+ }
+ }
+ rtems_interrupt_enable( level );
+}
+
diff --git a/bsps/arm/stm32f4/gpio/gpio.c b/bsps/arm/stm32f4/gpio/gpio.c
new file mode 100644
index 0000000000..0a54862ad2
--- /dev/null
+++ b/bsps/arm/stm32f4/gpio/gpio.c
@@ -0,0 +1,542 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp.h>
+#include <rtems.h>
+#include <stdlib.h>
+#include <bsp/stm32f4_gpio.h>
+#include <bsp/stm32f4_periph.h>
+
+/*********** GPIO API ***************/
+static rtems_status_code stm32f4_gpio_get(
+ uint32_t interm_pin,
+ rtems_gpio **out
+);
+
+static rtems_status_code stm32f4_gpio_destroy(
+ rtems_gpio *base
+);
+
+/*********************************************************/
+
+/**
+ * @brief STM32F4 GPIO handlers
+ */
+static const rtems_gpio_handlers stm32f4_gpio_handlers = {
+ .set_pin_mode = stm32f4_gpio_set_pin_mode,
+ .set_pull = stm32f4_gpio_set_pull,
+ .configure_interrupt = stm32f4_gpio_configure_interrupt,
+ .remove_interrupt = stm32f4_gpio_remove_interrupt,
+ .enable_interrupt = stm32f4_gpio_enable_interrupt,
+ .disable_interrupt = stm32f4_gpio_disable_interrupt,
+ .read = stm32f4_gpio_read,
+ .write = stm32f4_gpio_write,
+ .toggle = stm32f4_gpio_toggle
+};
+
+static GPIO_TypeDef * const GPIOx[] = {
+#ifdef GPIOA_BASE
+ GPIOA
+#endif /* GPIOA_BASE */
+#ifdef GPIOB_BASE
+ , GPIOB
+#endif /* GPIOB_BASE */
+#ifdef GPIOC_BASE
+ , GPIOC
+#endif /* GPIOC_BASE */
+#ifdef GPIOD_BASE
+ , GPIOD
+#endif /* GPIOD_BASE */
+#ifdef GPIOE_BASE
+ , GPIOE
+#endif /* GPIOE_BASE */
+#ifdef GPIOF_BASE
+ , GPIOF
+#endif /* GPIOF_BASE */
+#ifdef GPIOG_BASE
+ , GPIOG
+#endif /* GPIOG_BASE */
+#ifdef GPIOH_BASE
+ , GPIOH
+#endif /* GPIOH_BASE */
+#ifdef GPIOI_BASE
+ , GPIOI
+#endif /* GPIOI_BASE */
+#ifdef GPIOJ_BASE
+ , GPIOJ
+#endif /* GPIOJ_BASE */
+#ifdef GPIOK_BASE
+ , GPIOK
+#endif /* GPIOK_BASE */
+};
+
+static unsigned int const EXTIx_IRQn[] = {
+ EXTI0_IRQn,
+ EXTI1_IRQn,
+ EXTI2_IRQn,
+ EXTI3_IRQn,
+ EXTI4_IRQn,
+ EXTI9_5_IRQn,
+ EXTI9_5_IRQn,
+ EXTI9_5_IRQn,
+ EXTI9_5_IRQn,
+ EXTI9_5_IRQn,
+ EXTI15_10_IRQn,
+ EXTI15_10_IRQn,
+ EXTI15_10_IRQn,
+ EXTI15_10_IRQn,
+ EXTI15_10_IRQn,
+ EXTI15_10_IRQn
+};
+
+/**
+ * @brief Converts intermediate pin number to port pointer.
+ *
+ * Intermediate pin number is a way of numerically labeling
+ * pins. Pins are labeled incrementally across all ports.
+ * Pins 0-15 from port A are 0-15. Pins 0-15 from port B are
+ * 16-31. And so on.
+ *
+ * @param interm_pin is the intermediate pin number
+ */
+#define STM32F4_GET_PORT(interm_pin) (GPIOx[ ( interm_pin ) / 16 ])
+
+/**
+ * @brief Converts intermediate pin number to 0-15.
+ *
+ * Intermediate pin number is a way of numerically labeling
+ * pins. Pins are labeled incrementally across all ports.
+ * Pins 0-15 from port A are 0-15. Pins 0-15 from port B are
+ * 16-31. And so on.
+ *
+ * @param interm_pin is the intermediate pin number
+ */
+#define STM32F4_GET_PIN_0_15(interm_pin) (( interm_pin ) % 16)
+
+/**
+ * @brief Converts pin number from 0-15 to HAL pin mask.
+ * @param pin is the pin number from 0-15
+ */
+#define STM32F4_GET_HAL_GPIO_PIN(pin) ((uint16_t) (1 << ( pin )))
+
+/**
+ * @brief Get EXTI Line from pin number 0-15
+ * @param pin is the pin number from 0-15
+ */
+#define STM32F4_GET_LL_EXTI_LINE(pin) (0x1UL << ( pin ))
+
+/**
+ * @brief Get EXTI IRQ number from pin 0-15
+ * @param pin is the pin number from 0-15
+ */
+#define STM32F4_GET_EXTI_IRQn(pin) (EXTIx_IRQn[( pin )])
+
+/************** Interrupt manager *****************/
+typedef struct {
+ void *arg;
+ stm32f4_gpio *gpio;
+} stm32f4_interrupt_arg;
+
+typedef struct {
+ stm32f4_interrupt_arg arg;
+ rtems_gpio_isr isr;
+} stm32f4_interrupt;
+
+static stm32f4_interrupt isr_table[16];
+static bool isr_registered[16] = {0};
+
+void exti_handler(void *arg);
+
+
+/********** STM32F4 GPIO API functions ************/
+
+rtems_status_code bsp_gpio_register_controllers(
+ void
+)
+{
+ return rtems_gpio_register(
+ stm32f4_gpio_get,
+ stm32f4_gpio_destroy,
+ stm32f4_periph_get_api,
+ stm32f4_periph_remove_api,
+ sizeof(GPIOx)/sizeof(GPIOx[0])*16
+ );
+}
+
+rtems_status_code stm32f4_gpio_get(
+ uint32_t interm_pin,
+ rtems_gpio **out
+)
+{
+ stm32f4_gpio *tmp = malloc(sizeof(stm32f4_gpio));
+ if (tmp == NULL) {
+ return RTEMS_NO_MEMORY;
+ }
+ tmp->base = RTEMS_GPIO_BUILD_BASE(&stm32f4_gpio_handlers);
+ tmp->pin = STM32F4_GET_PIN_0_15(interm_pin);
+ tmp->port = STM32F4_GET_PORT(interm_pin);
+
+ // initialize the pin
+ stm32f4_gpio_init((rtems_gpio *) tmp);
+
+ *out = (rtems_gpio *) tmp;
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_destroy(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ free(gpio);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_set_pin_mode(
+ rtems_gpio *base,
+ rtems_gpio_pin_mode mode
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+
+ uint32_t stm32f4_mode, stm32f4_output_type;
+ switch (mode) {
+ case RTEMS_GPIO_PINMODE_OUTPUT_PP:
+ stm32f4_mode = LL_GPIO_MODE_OUTPUT;
+ stm32f4_output_type = LL_GPIO_OUTPUT_PUSHPULL;
+ break;
+ case RTEMS_GPIO_PINMODE_OUTPUT_OD:
+ stm32f4_mode = LL_GPIO_MODE_OUTPUT;
+ stm32f4_output_type = LL_GPIO_OUTPUT_OPENDRAIN;
+ break;
+ case RTEMS_GPIO_PINMODE_INPUT:
+ stm32f4_mode = LL_GPIO_MODE_INPUT;
+ break;
+ case RTEMS_GPIO_PINMODE_ANALOG:
+ stm32f4_mode = LL_GPIO_MODE_ANALOG;
+ break;
+ case RTEMS_GPIO_PINMODE_BSP_SPECIFIC:
+ stm32f4_mode = LL_GPIO_MODE_ALTERNATE;
+ break;
+ default:
+ /* illegal argument */
+ return RTEMS_UNSATISFIED;
+ }
+ LL_GPIO_SetPinMode(gpio->port, pin_mask, stm32f4_mode);
+ if (stm32f4_mode == LL_GPIO_MODE_OUTPUT) {
+ LL_GPIO_SetPinOutputType(gpio->port, pin_mask, stm32f4_output_type);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_set_pull(
+ rtems_gpio *base,
+ rtems_gpio_pull pull
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+ uint32_t stm32f4_pull;
+
+ switch (pull) {
+ case RTEMS_GPIO_NOPULL:
+ stm32f4_pull = LL_GPIO_PULL_NO;
+ break;
+ case RTEMS_GPIO_PULLUP:
+ stm32f4_pull = LL_GPIO_PULL_UP;
+ break;
+ case RTEMS_GPIO_PULLDOWN:
+ stm32f4_pull = LL_GPIO_PULL_DOWN;
+ break;
+ default:
+ /* Illegal argument */
+ return RTEMS_UNSATISFIED;
+ }
+ LL_GPIO_SetPinPull(gpio->port, pin_mask, stm32f4_pull);
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_configure_interrupt(
+ rtems_gpio *base,
+ rtems_gpio_isr isr,
+ void *arg,
+ rtems_gpio_interrupt_trig trig,
+ rtems_gpio_pull pull
+)
+{
+ // configure pin
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(gpio->pin);
+ GPIO_InitTypeDef hal_conf;
+
+ switch (trig) {
+ case RTEMS_GPIO_INT_TRIG_NONE:
+ return RTEMS_SUCCESSFUL;
+ case RTEMS_GPIO_INT_TRIG_FALLING:
+ hal_conf.Mode = GPIO_MODE_IT_FALLING;
+ break;
+ case RTEMS_GPIO_INT_TRIG_RISING:
+ hal_conf.Mode = GPIO_MODE_IT_RISING;
+ break;
+ case RTEMS_GPIO_INT_TRIG_BOTH_EDGES:
+ hal_conf.Mode = GPIO_MODE_IT_RISING_FALLING;
+ break;
+ default:
+ /* Invalid argument */
+ return RTEMS_UNSATISFIED;
+ }
+ switch (pull) {
+ case RTEMS_GPIO_NOPULL:
+ hal_conf.Pull = GPIO_NOPULL;
+ break;
+ case RTEMS_GPIO_PULLUP:
+ hal_conf.Pull = GPIO_PULLUP;
+ break;
+ case RTEMS_GPIO_PULLDOWN:
+ hal_conf.Pull = GPIO_PULLDOWN;
+ break;
+ default:
+ /* Illegal argument */
+ return RTEMS_UNSATISFIED;
+ }
+ hal_conf.Pin = pin_mask;
+ HAL_GPIO_Init(gpio->port, &hal_conf);
+
+ // RTEMS interrupt config
+ if (isr_registered[gpio->pin]) {
+ return RTEMS_UNSATISFIED;
+ }
+ isr_table[gpio->pin] = (stm32f4_interrupt){
+ .arg = {
+ .arg = arg,
+ .gpio = gpio
+ },
+ .isr = isr
+ };
+ isr_registered[gpio->pin] = true;
+ rtems_option opt = gpio->pin < 5 ?
+ RTEMS_INTERRUPT_UNIQUE :
+ RTEMS_INTERRUPT_SHARED;
+ rtems_status_code sc = rtems_interrupt_handler_install(
+ STM32F4_GET_EXTI_IRQn(gpio->pin),
+ NULL,
+ opt,
+ exti_handler,
+ &isr_table[gpio->pin].arg
+ );
+
+ return sc;
+}
+
+rtems_status_code stm32f4_gpio_remove_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ if (isr_registered[gpio->pin]) {
+ rtems_status_code sc = rtems_interrupt_handler_remove(
+ STM32F4_GET_EXTI_IRQn(gpio->pin),
+ exti_handler,
+ &isr_table[gpio->pin].arg
+ );
+ if (sc == RTEMS_SUCCESSFUL) {
+ isr_registered[gpio->pin] = false;
+ }
+ return sc;
+ }
+ return RTEMS_UNSATISFIED;
+}
+
+rtems_status_code stm32f4_gpio_enable_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ LL_EXTI_EnableIT_0_31(STM32F4_GET_LL_EXTI_LINE(gpio->pin));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_disable_interrupt(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ LL_EXTI_DisableIT_0_31(STM32F4_GET_LL_EXTI_LINE(gpio->pin));
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_write(
+ rtems_gpio *base,
+ rtems_gpio_pin_state value
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+ if (value)
+ LL_GPIO_SetOutputPin(gpio->port, STM32F4_GET_HAL_GPIO_PIN(gpio->pin));
+ else
+ LL_GPIO_ResetOutputPin(gpio->port, STM32F4_GET_HAL_GPIO_PIN(gpio->pin));
+
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_read(
+ rtems_gpio *base,
+ rtems_gpio_pin_state *value
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+ *value = LL_GPIO_IsInputPinSet(
+ gpio->port,
+ STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+ );
+ return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code stm32f4_gpio_toggle(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+ LL_GPIO_TogglePin(
+ gpio->port,
+ STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+ );
+ return RTEMS_SUCCESSFUL;
+}
+
+void exti_handler(void *arg) {
+ stm32f4_interrupt_arg *stm32_arg = (stm32f4_interrupt_arg *) arg;
+ uint32_t pin_mask = STM32F4_GET_HAL_GPIO_PIN(stm32_arg->gpio->pin);
+ if(__HAL_GPIO_EXTI_GET_IT(pin_mask) != RESET)
+ {
+ __HAL_GPIO_EXTI_CLEAR_IT(pin_mask);
+ (*isr_table[stm32_arg->gpio->pin].isr)(stm32_arg->arg);
+ }
+}
+
+/************ STM32F4 Other specific GPIO functions ************/
+rtems_status_code stm32f4_gpio_init(rtems_gpio *base) {
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+
+ switch ((uintptr_t) gpio->port) {
+#ifdef GPIOA_BASE
+ case (uintptr_t) GPIOA:
+ __HAL_RCC_GPIOA_CLK_ENABLE();
+ break;
+#endif /* GPIOA_BASE */
+#ifdef GPIOB_BASE
+ case (uintptr_t) GPIOB:
+ __HAL_RCC_GPIOB_CLK_ENABLE();
+ break;
+#endif /* GPIOB_BASE */
+#ifdef GPIOC_BASE
+ case (uintptr_t) GPIOC:
+ __HAL_RCC_GPIOC_CLK_ENABLE();
+ break;
+#endif /* GPIOC_BASE */
+#ifdef GPIOD_BASE
+ case (uintptr_t) GPIOD:
+ __HAL_RCC_GPIOD_CLK_ENABLE();
+ break;
+#endif /* GPIOD_BASE */
+#ifdef GPIOE_BASE
+ case (uintptr_t) GPIOE:
+ __HAL_RCC_GPIOE_CLK_ENABLE();
+ break;
+#endif /* GPIOE_BASE */
+#ifdef GPIOF_BASE
+ case (uintptr_t) GPIOF:
+ __HAL_RCC_GPIOF_CLK_ENABLE();
+ break;
+#endif /* GPIOF_BASE */
+#ifdef GPIOG_BASE
+ case (uintptr_t) GPIOG:
+ __HAL_RCC_GPIOG_CLK_ENABLE();
+ break;
+#endif /* GPIOG_BASE */
+#ifdef GPIOH_BASE
+ case (uintptr_t) GPIOH:
+ __HAL_RCC_GPIOH_CLK_ENABLE();
+ break;
+#endif /* GPIOH_BASE */
+#ifdef GPIOI_BASE
+ case (uintptr_t) GPIOI:
+ __HAL_RCC_GPIOI_CLK_ENABLE();
+ break;
+#endif /* GPIOI_BASE */
+#ifdef GPIOJ_BASE
+ case (uintptr_t) GPIOJ:
+ __HAL_RCC_GPIOJ_CLK_ENABLE();
+ break;
+#endif /* GPIOJ_BASE */
+#ifdef GPIOK_BASE
+ case (uintptr_t) GPIOK:
+ __HAL_RCC_GPIOK_CLK_ENABLE();
+ break;
+#endif /* GPIOK_BASE */
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+void stm32f4_gpio_lock_pin(
+ rtems_gpio *base
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ LL_GPIO_LockPin(
+ gpio->port,
+ STM32F4_GET_HAL_GPIO_PIN(gpio->pin)
+ );
+}
+
+void stm32f4_gpio_set_af(
+ rtems_gpio *base,
+ uint32_t alternate
+)
+{
+ stm32f4_gpio *gpio = stm32f4_get_gpio_from_base(base);
+ if (gpio->pin < 8)
+ LL_GPIO_SetAFPin_0_7(
+ gpio->port,
+ STM32F4_GET_HAL_GPIO_PIN(gpio->pin),
+ alternate
+ );
+ else
+ LL_GPIO_SetAFPin_8_15(
+ gpio->port,
+ STM32F4_GET_HAL_GPIO_PIN(gpio->pin),
+ alternate
+ );
+}
+
diff --git a/bsps/arm/stm32f4/include/bsp.h b/bsps/arm/stm32f4/include/bsp.h
index 42a74e109d..968545cd5a 100644
--- a/bsps/arm/stm32f4/include/bsp.h
+++ b/bsps/arm/stm32f4/include/bsp.h
@@ -42,10 +42,6 @@ extern "C" {
#define BSP_ARMV7M_SYSTICK_FREQUENCY STM32F4_HCLK
-#ifdef __rtems__
-void Error_Handler(void);
-#endif /* __rtems__ */
-
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_adc.h b/bsps/arm/stm32f4/include/bsp/stm32f4_adc.h
new file mode 100644
index 0000000000..973fadf828
--- /dev/null
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_adc.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_ARM_STM32F4_BSP_ADC
+#define LIBBSP_ARM_STM32F4_BSP_ADC
+
+#include <rtems/sysinit.h>
+#include <bsp/adc.h>
+#include <stm32f4xx_ll_bus.h>
+#include <stm32f4xx_ll_adc.h>
+#include <bsp/stm32f4_gpio.h>
+
+#define STM32F4_ADC_DEFAULT_RESOLUTION LL_ADC_RESOLUTION_10B
+#define STM32F4_ADC_DEFAULT_ALIGNMENT LL_ADC_DATA_ALIGN_RIGHT
+#define STM32F4_ADC_DEFAULT_SAMPLINGTIME LL_ADC_SAMPLINGTIME_3CYCLES
+
+/**
+ * Macros for simple locking of shared objects.
+ * Structs must have a bool member named "locked"
+ */
+#define STM32F4_LOCK(obj) \
+ do { \
+ ( obj )->locked = true; \
+ } while (0)
+
+#define STM32F4_UNLOCK(obj) \
+ do { \
+ ( obj )->locked = false; \
+ } while (0)
+
+#define STM32F4_IS_LOCKED(obj) \
+ (( obj )->locked)
+
+/**
+ * @brief Wrapper of ADC_TypeDef with a simple lock.
+ */
+typedef struct {
+ ADC_TypeDef *ADCx;
+ bool locked;
+} ADC_TypeDef_Protected;
+
+/**
+ * @brief Structure containing ADC configuration for an
+ * ADC pin.
+ */
+typedef struct {
+ /**
+ * @brief Locks ADC configuration change on this pin
+ * if set to true.
+ */
+ bool locked;
+ /**
+ * @brief STM32F4-defined ADCx.
+ */
+ ADC_TypeDef_Protected *ADCx;
+ /**
+ * @brief ADC channel of the pin.
+ * This can be LL_ADC_CHANNEL_n defined by STM32F4 LL
+ * driver, where 0 <= n <= 18.
+ */
+ uint32_t channel;
+ /**
+ * @brief Resolution of the ADC pin.
+ * This can be one of the following values:
+ * @ref LL_ADC_RESOLUTION_12B
+ * @ref LL_ADC_RESOLUTION_10B
+ * @ref LL_ADC_RESOLUTION_8B
+ * @ref LL_ADC_RESOLUTION_6B
+ */
+ uint32_t resolution;
+ /**
+ * @brief Data alignment of the ADC pin.
+ * This can be one of the following values:
+ * @ref LL_ADC_DATA_ALIGN_RIGHT
+ * @ref LL_ADC_DATA_ALIGN_LEFT
+ */
+ uint32_t alignment;
+} stm32f4_adc_config;
+
+/**
+ * @brief STM32F4 wrapper of peripherals API.
+ */
+typedef struct {
+ rtems_adc_api base_api;
+ stm32f4_adc_config *adc_config;
+} stm32f4_adc;
+
+const rtems_adc_handlers *stm32f4_get_adc_handlers(
+ void
+);
+
+/**
+ * @brief Get the HAL-defined ADCx pointer.
+ * @note This function should not be called. Use
+ * @see stm32f4_get_ADCx_protected() instead.
+ */
+ADC_TypeDef *stm32f4_get_ADCx(
+ GPIO_TypeDef *gpiox
+);
+
+ADC_TypeDef_Protected *stm32f4_get_ADCx_protected(
+ GPIO_TypeDef *gpiox
+);
+
+rtems_status_code stm32f4_get_LL_ADC_CHANNEL(
+ stm32f4_gpio *gpio,
+ uint32_t *channel
+);
+
+bool stm32f4_is_adc_pin(
+ stm32f4_gpio *gpio
+);
+
+rtems_periph_api *stm32f4_adc_get(
+ rtems_gpio *gpio
+);
+
+rtems_status_code stm32f4_adc_destroy(
+ rtems_gpio *gpio
+);
+
+/***/
+/**
+ * @brief Perform initialization for STM32F4 ADC manager
+ *
+ * This function should be called in bspstarthook under
+ * if ADC is enabled.
+ */
+extern void stm32f4_adc_start(
+ void
+);
+
+/**
+ * @brief Performs initialization for an ADC pin
+ * @note This function needs to be registered with the
+ * peripherals API.
+ */
+void stm32f4_adc_init(
+ rtems_gpio *base
+);
+
+rtems_status_code stm32f4_adc_read_raw(
+ rtems_gpio *base,
+ uint32_t *result,
+ uint32_t timeout
+);
+
+rtems_status_code stm32f4_adc_start_read_raw_nb(
+ rtems_gpio *base
+);
+
+rtems_adc_status stm32f4_adc_read_raw_nb(
+ rtems_gpio *base,
+ uint32_t *result
+);
+
+rtems_status_code stm32f4_adc_set_resolution(
+ rtems_gpio *base,
+ unsigned int bits
+);
+
+rtems_status_code stm32f4_adc_set_alignment(
+ rtems_gpio *base,
+ rtems_adc_align align
+);
+
+rtems_status_code stm32f4_adc_configure_interrupt(
+ rtems_gpio *base,
+ rtems_adc_isr isr,
+ void *arg
+);
+
+rtems_status_code stm32f4_adc_remove_interrupt(
+ rtems_gpio *base
+);
+
+rtems_status_code stm32f4_adc_enable_interrupt(
+ rtems_gpio *base
+);
+
+rtems_status_code stm32f4_adc_disable_interrupt(
+ rtems_gpio *base
+);
+
+#endif /* LIBBSP_ARM_STM32F4_BSP_ADC */
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
new file mode 100644
index 0000000000..6bd6baea86
--- /dev/null
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
@@ -0,0 +1,273 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_ARM_STM32F4_BSP_GPIO
+#define LIBBSP_ARM_STM32F4_BSP_GPIO
+
+#include <stdbool.h>
+#include <stm32f4xx.h>
+#include <stm32f4xx_ll_gpio.h>
+#include <stm32f4xx_ll_exti.h>
+#include <bsp/gpio2.h>
+
+/*********** Helpers *****************/
+/**
+ * @brief Macro to get stm32f4_gpio object from a base rtems_gpio
+ * object.
+ *
+ * This is a wrapper of RTEMS_CONTAINER_OF macro
+ *
+ * @param base The pointer to a rtems_gpio object
+ * @retval The pointer to the stm32f4_gpio object owning
+ * the specified rtems_gpio object
+ */
+#define stm32f4_get_gpio_from_base(_base) \
+ RTEMS_CONTAINER_OF(_base, stm32f4_gpio, base)
+
+/**
+ * @brief STM32F4 BSP GPIO structure
+ *
+ */
+typedef struct {
+ /**
+ * @brief This member is a rtems_gpio object.
+ */
+ rtems_gpio base;
+ /**
+ *@brief This member is the pin number from 0 to 15.
+ */
+ uint32_t pin;
+ /**
+ * @brief This member is HAL GPIOx pointer.
+ */
+ GPIO_TypeDef *port;
+} stm32f4_gpio;
+
+/**
+ * @name STM32F4 GPIO functions
+ *
+ * @{
+ */
+
+/**
+ * @name GPIO API implementation of STM32F4 BSP
+ *
+ * @{
+ */
+
+
+/**
+ * @brief Sets the pin mode.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ * @param mode is a value of @see rtems_gpio_pin_mode
+ *
+ * @retval RTEMS_SUCCESSFUL if the pin mode is valid.
+ * @retval RTEMS_UNSATISFIED if the pin mode is
+ * invalid.
+ */
+extern rtems_status_code stm32f4_gpio_set_pin_mode(
+ rtems_gpio *base,
+ rtems_gpio_pin_mode mode
+);
+
+/**
+ * @brief Sets pull resistor mode.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ * @param pull is a value of @see rtems_gpio_pull
+ *
+ * @retval RTEMS_SUCCESSFUL if the pull resistor
+ * mode is valid.
+ * @retval RTEMS_UNSATISFIED if the pull resistor
+ * mode is invalid.
+ */
+extern rtems_status_code stm32f4_gpio_set_pull(
+ rtems_gpio *base,
+ rtems_gpio_pull pull
+);
+
+/**
+ * @brief Configures user-defined ISR for an EXTI.
+ *
+ * This function is used to register a custom ISR
+ * with a GPIO pin. This API supports up to 1 ISR
+ * for each EXTI line (total 16 ISRs) at a time.
+ *
+ * @note If there is already an ISR registered with
+ * a line, it needs to be removed to be able
+ * to register a new one.
+ * @note This function does not enable interrupt.
+ * use @see rtems_gpio_enable_interrupt().
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL if interrupt
+ * configuration is successful.
+ * @retval RTEMS_UNSATISFIED if trigger mode/pull
+ * resistor mode is invalid or an ISR
+ * has already been registered for this
+ * EXTI line.
+ * @retval @see rtems_interrupt_handler_install()
+ */
+extern rtems_status_code stm32f4_gpio_configure_interrupt(
+ rtems_gpio *base,
+ rtems_gpio_isr isr,
+ void *arg,
+ rtems_gpio_interrupt_trig trig,
+ rtems_gpio_pull pull
+);
+
+/**
+ * @brief Removes the registered ISR.
+ *
+ * @note This function does not disable interrupt.
+ * @ref rtems_gpio_disable_interrupt()
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL if ISR removed successfully.
+ * @retval RTEMS_UNSATISFIED if no ISR registered for
+ * selected line.
+ * @retval @see rtems_interrupt_handler_remove()
+ */
+extern rtems_status_code stm32f4_gpio_remove_interrupt(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Enables EXTI for the line connected to this
+ * pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL
+ */
+extern rtems_status_code stm32f4_gpio_enable_interrupt(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Disables EXTI for the line connected to
+ * this pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL
+ */
+extern rtems_status_code stm32f4_gpio_disable_interrupt(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Reads digital value into a variable.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ * @param[out] value The pointer to the output
+ * variable.
+ *
+ * @retval RTEMS_SUCCESSFUL
+ */
+extern rtems_status_code stm32f4_gpio_read(
+ rtems_gpio *base,
+ rtems_gpio_pin_state *value
+);
+
+/**
+ * @brief Writes digital value to a pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ * @param value The output digital value.
+ *
+ * @retval RTEMS_SUCCESSFUL
+ */
+extern rtems_status_code stm32f4_gpio_write(
+ rtems_gpio *base,
+ rtems_gpio_pin_state value
+);
+
+/**
+ * @brief Toggles the state of a pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL
+ */
+extern rtems_status_code stm32f4_gpio_toggle(
+ rtems_gpio *base
+);
+
+/** @} */
+
+/**
+ * @name Extra functionality of STM32F4 GPIO
+ *
+ * @{
+ */
+
+/**
+ * @brief Initializes clock for the GPIO port
+ * owning this pin.
+ *
+ * @note This function is called in stm32f4_gpio_get().
+ *
+ * @param[in] base The pointer to the GPIO object.
+ *
+ * @retval RTEMS_SUCCESSFUL if the port argument is
+ * valid
+ * @retval RTEMS_UNSATISFIED if the port argument is
+ * invalid
+ */
+extern rtems_status_code stm32f4_gpio_init(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Lock configuration of a pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ */
+extern void stm32f4_gpio_lock_pin(
+ rtems_gpio *base
+);
+
+/**
+ * @brief Sets the alternate function for a pin.
+ *
+ * @param[in] base The pointer to the GPIO object.
+ * @param alternate Alternate function, from 0-15.
+ */
+extern void stm32f4_gpio_set_af(
+ rtems_gpio *base,
+ uint32_t alternate
+);
+
+/** @} */
+
+/** @} */
+
+#endif /* LIBBSP_ARM_STM32F4_BSP_GPIO */
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_hal.h b/bsps/arm/stm32f4/include/bsp/stm32f4_hal.h
new file mode 100644
index 0000000000..9e88b39067
--- /dev/null
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_hal.h
@@ -0,0 +1,17 @@
+#ifndef LIBBSP_ARM_STM32F4_BSP_STM32F4HAL_H
+#define LIBBSP_ARM_STM32F4_BSP_STM32F4HAL_H
+
+#include <stm32f4xx_hal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void stm32f4_clk_enable();
+void stm32f4_clk_disable();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/bsps/arm/stm32f4/include/bsp/stm32f4_periph.h b/bsps/arm/stm32f4/include/bsp/stm32f4_periph.h
new file mode 100644
index 0000000000..f8b9ad2540
--- /dev/null
+++ b/bsps/arm/stm32f4/include/bsp/stm32f4_periph.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIBBSP_BSP_ARM_STM32F4_PERIPH_H
+#define LIBBSP_BSP_ARM_STM32F4_PERIPH_H
+
+#include <bsp/periph_api.h>
+
+/**
+ * @brief STM32F4 BSP's function to get a
+ * peripheral API.
+ */
+rtems_periph_api *stm32f4_periph_get_api(
+ rtems_gpio *pin,
+ rtems_periph_api_type type
+);
+
+/**
+ * @brief STM32F4 BSP's function to remove a
+ * peripheral API assigned to a pin.
+ */
+rtems_status_code stm32f4_periph_remove_api(
+ rtems_gpio *pin
+);
+
+#endif /* LIBBSP_BSP_ARM_STM32F4_PERIPH_H */
diff --git a/bsps/arm/stm32f4/start/bspstart.c b/bsps/arm/stm32f4/start/bspstart.c
index 8589c6486c..2297430844 100644
--- a/bsps/arm/stm32f4/start/bspstart.c
+++ b/bsps/arm/stm32f4/start/bspstart.c
@@ -19,6 +19,7 @@
#endif /* __rtems__ */
#ifdef __rtems__
#include <stm32f4xx.h>
+#include <bsp/gpio2.h>
#endif /* __rtems__ */
#ifdef STM32F4_FAMILY_F4XXXX
@@ -46,7 +47,7 @@ uint32_t HAL_GetTick(void)
* @brief This function is executed in case of error occurrence.
* @retval None
*/
-void Error_Handler(void)
+static void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
@@ -166,7 +167,6 @@ static rtems_status_code SystemClock_Config(void)
HAL_StatusTypeDef status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if (status != HAL_OK)
{
-// Error_Handler();
return RTEMS_UNSATISFIED;
}
@@ -181,7 +181,6 @@ static rtems_status_code SystemClock_Config(void)
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, flash_latency) != HAL_OK)
{
-// Error_Handler();
return RTEMS_UNSATISFIED;
}
@@ -465,9 +464,7 @@ void bsp_start( void )
{
init_main_osc();
-#ifdef __rtems__
stm32f4_gpio_set_config_array( &stm32f4_start_config_gpio[ 0 ] );
-#endif /* __rtems__ */
bsp_interrupt_initialize();
}
diff --git a/bsps/arm/stm32f4/start/bspstarthook.c b/bsps/arm/stm32f4/start/bspstarthook.c
index bbfaed615e..0aeba0ac13 100644
--- a/bsps/arm/stm32f4/start/bspstarthook.c
+++ b/bsps/arm/stm32f4/start/bspstarthook.c
@@ -20,4 +20,12 @@ void BSP_START_TEXT_SECTION bsp_start_hook_1(void)
bsp_start_clear_bss();
/* At this point we can use objects outside the .start section */
+
+#ifndef __rtems__
+
+#if STM32F4_ENABLE_GENERIC_GPIO == 1
+ bsp_gpio_register_controllers();
+#endif /* STM32F4_ENABLE_GENERIC_GPIO */
+
+#endif /* __rtems__ */
}
diff --git a/bsps/arm/stm32f4/start/periph.c b/bsps/arm/stm32f4/start/periph.c
new file mode 100644
index 0000000000..7b1b0f1bb5
--- /dev/null
+++ b/bsps/arm/stm32f4/start/periph.c
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <bsp/stm32f4_gpio.h>
+#include <bsp/stm32f4_adc.h>
+#include <bsp/stm32f4_periph.h>
+
+rtems_periph_api *stm32f4_periph_get_api(
+ rtems_gpio *pin,
+ rtems_periph_api_type type
+)
+{
+ switch (type) {
+ case RTEMS_PERIPH_API_TYPE_ADC:
+ return stm32f4_adc_get(pin);
+ default:
+ return NULL;
+ }
+}
+
+rtems_status_code stm32f4_periph_remove_api(
+ rtems_gpio *pin
+)
+{
+ if (pin->api == NULL)
+ return RTEMS_UNSATISFIED;
+
+ switch (*(rtems_periph_api_type *) pin->api) {
+ case RTEMS_PERIPH_API_TYPE_ADC:
+ return stm32f4_adc_destroy(pin);
+ default:
+ return RTEMS_UNSATISFIED;
+ }
+}
diff --git a/spec/build/bsps/arm/stm32f4/grp.yml b/spec/build/bsps/arm/stm32f4/grp.yml
index 99a78e1890..99b3a10527 100644
--- a/spec/build/bsps/arm/stm32f4/grp.yml
+++ b/spec/build/bsps/arm/stm32f4/grp.yml
@@ -17,9 +17,11 @@ links:
- role: build-dependency
uid: abi
- role: build-dependency
- uid: obj
+ uid: optnumgpioctrl
- role: build-dependency
uid: optenhal
+- role: build-dependency
+ uid: optengpio
- role: build-dependency
uid: optvariant
- role: build-dependency
@@ -66,6 +68,8 @@ links:
uid: ../../objirq
- role: build-dependency
uid: ../../objmem
+- role: build-dependency
+ uid: obj
- role: build-dependency
uid: ../../bspopts
type: build
diff --git a/spec/build/bsps/arm/stm32f4/obj.yml b/spec/build/bsps/arm/stm32f4/obj.yml
index 7afe000024..6d08c618c6 100644
--- a/spec/build/bsps/arm/stm32f4/obj.yml
+++ b/spec/build/bsps/arm/stm32f4/obj.yml
@@ -153,6 +153,8 @@ install:
- bsps/arm/stm32f4/include/bsp/stm32f10xxx_rcc.h
- bsps/arm/stm32f4/include/bsp/stm32f4.h
- bsps/arm/stm32f4/include/bsp/stm32f4_gpio.h
+ - bsps/arm/stm32f4/include/bsp/stm32f4_periph.h
+ - bsps/arm/stm32f4/include/bsp/stm32f4_adc.h
- bsps/arm/stm32f4/include/bsp/stm32f4xxxx_adc.h
- bsps/arm/stm32f4/include/bsp/stm32f4xxxx_exti.h
- bsps/arm/stm32f4/include/bsp/stm32f4xxxx_flash.h
@@ -261,6 +263,9 @@ source:
- bsps/arm/stm32f4/hal/stm32f4xx_ll_usb.c
- bsps/arm/stm32f4/hal/stm32f4xx_ll_utils.c
- bsps/arm/stm32f4/hal/system_stm32f4xx.c
+- bsps/arm/stm32f4/gpio/gpio.c
+- bsps/arm/stm32f4/start/periph.c
+- bsps/arm/stm32f4/adc/adc.c
- bsps/arm/shared/irq/irq-armv7m.c
- bsps/arm/shared/irq/irq-dispatch-armv7m.c
- bsps/arm/shared/start/bsp-start-memcpy.S
diff --git a/spec/build/bsps/arm/stm32f4/optengpio.yml b/spec/build/bsps/arm/stm32f4/optengpio.yml
new file mode 100644
index 0000000000..8b15bce9a9
--- /dev/null
+++ b/spec/build/bsps/arm/stm32f4/optengpio.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-boolean: null
+- define-condition: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: true
+default-by-variant: []
+description: |
+ This option enables the BSP to use RTEMS GPIO API.
+enabled-by: true
+format: '{}'
+links: []
+name: STM32F4_ENABLE_GENERIC_GPIO
+type: build
diff --git a/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml b/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml
new file mode 100644
index 0000000000..da21d9c62c
--- /dev/null
+++ b/spec/build/bsps/arm/stm32f4/optnumgpioctrl.yml
@@ -0,0 +1,16 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+actions:
+- get-integer: null
+- define: null
+build-type: option
+copyrights:
+- Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com)
+default: 1
+default-by-variant: []
+description: |
+ Number of GPIO controllers of this BSP.
+enabled-by: true
+format: '{}'
+links: []
+name: BSP_GPIO_NUM_CONTROLLERS
+type: build
--
2.36.1
More information about the devel
mailing list