| Name (related to mcu/hal_api folder) | Description |
-| @ref button.h "button.h" | Button functions |
| @ref ds.h "ds.h" | Deep sleep control module |
| @ref radio.h "radio.h" | Radio FEM (front-end module)
|
@@ -281,6 +280,8 @@ are following:
| @ref hw_delay.h "hw_delay.h" | Hardware delay module |
| @ref i2c.h "i2c.h" | Simple minimal I2C master driver |
+| @ref gpio.h "gpio.h" | GPIO functions |
+| @ref button.h "button.h" | Button functions |
| @ref led.h "led.h" | LED functions |
| @ref power.h "power.h" | Enabling of DCDC converter |
| @ref spi.h "spi.h" | Simple minimal SPI master driver |
diff --git a/doc_src_doxy/a5_application_examples.h b/doc_src_doxy/a5_application_examples.h
index fcd49935..e4fb0342 100644
--- a/doc_src_doxy/a5_application_examples.h
+++ b/doc_src_doxy/a5_application_examples.h
@@ -281,6 +281,7 @@ This page contains following sections:
- @subpage source_makefile_app_printing
- @subpage source_makefile_app_scheduler
- @subpage source_makefile_cflags
+- @subpage source_makefile_hal_gpio
- @subpage source_makefile_hal_button
- @subpage source_makefile_hal_hw_delay
- @subpage source_makefile_hal_i2c
@@ -338,6 +339,19 @@ CFLAGS += -DNETWORK_ADDRESS=$(default_network_address)
CFLAGS += -DNETWORK_CHANNEL=$(default_network_channel)
@endcode
+@subsection source_makefile_hal_gpio HAL_GPIO
+
+Using of @ref gpio.h "HAL for GPIOs" can be done by this flag.
+
+Example:
+@code
+# This application use HAL for GPIOs
+HAL_GPIO=yes
+@endcode
+
+@note: in order for application to be able to drive GPIOs, they must be
+defined in specific @ref board_folder "board".
+
@subsection source_makefile_hal_button HAL_BUTTON
Using of @ref button.h "HAL for buttons" can be done by this flag.
@@ -350,7 +364,6 @@ HAL_BUTTON=yes
@note: in order for application to be able to drive buttons, they must be
defined in specific @ref board_folder "board".
-@note This option is supported only on nRF52 architectures.
@subsection source_makefile_hal_hw_delay HAL_HW_DELAY
diff --git a/libraries/config.mk b/libraries/config.mk
index a8de3aa8..395330e3 100644
--- a/libraries/config.mk
+++ b/libraries/config.mk
@@ -78,6 +78,7 @@ scheduler_tasks+= + 2
endif
ifeq ($(DUALMCU_LIB), yes)
+HAL_GPIO=yes
scheduler_tasks+= + 3
app_config_filters+= + 1
SHARED_DATA=yes
diff --git a/libraries/dualmcu/drivers/efr32/exti.c b/libraries/dualmcu/drivers/efr32/exti.c
deleted file mode 100644
index ea368f42..00000000
--- a/libraries/dualmcu/drivers/efr32/exti.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/* Copyright 2019 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-#include
-#include
-
-#include "hal_api.h"
-#include "io.h"
-#include "board.h"
-#include "api.h"
-#include "em_gpio.h"
-
-// Amount of channels per vector (IO port width / 2)
-#define IRQ_CHANNELS_PER_VECTOR 8
-
-// Callbacks
-static wakeup_cb_f m_even_callbacks[IRQ_CHANNELS_PER_VECTOR];
-static wakeup_cb_f m_odd_callbacks[IRQ_CHANNELS_PER_VECTOR];
-
-// Declare ISR
-void __attribute__((__interrupt__)) GPIO_EVEN_IRQHandler(void);
-void __attribute__((__interrupt__)) GPIO_ODD_IRQHandler(void);
-
-static inline void clear_interrupt(uint32_t pin)
-{
-#if defined(_SILICON_LABS_32B_SERIES_1)
- /** IFC is a latch register, safe to use without bit-band */
- GPIO->IFC = (1 << pin);
-#elif defined(_SILICON_LABS_32B_SERIES_2)
- GPIO->IF_CLR = (1 << pin);
-#else
-#error "Unknown EFR32 series and config"
-#endif
-}
-
-static void pin_config(uint32_t pin, uint32_t port)
-{
- // Code does not set GPIO->EXTIPINSELL or GPIO->EXTIPINSELH
- // thus direct mapping: pin x ==> EXTI x is used.
- if (pin < 8)
- {
- GPIO->EXTIPSELL = (GPIO->EXTIPSELL & ~(0xF << (4 * pin))) |
- (port << (4 * pin));
- }
-#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- else
- {
- GPIO->EXTIPSELH = (GPIO->EXTIPSELH & ~(0xF << (4 * (pin - 8)))) |
- (port << (4 * (pin - 8)));
- }
-#endif
-}
-
-void Wakeup_pinInit(wakeup_cb_f cb)
-{
- /* Clear interrupt sources and flags */
- GPIO->IEN = _GPIO_IEN_RESETVALUE;
-#if defined(_SILICON_LABS_32B_SERIES_1)
- GPIO->IFC = _GPIO_IFC_MASK;
-#elif defined(_SILICON_LABS_32B_SERIES_2)
- GPIO->IF_CLR = _GPIO_IF_MASK;
-#else
-#error "Unknown EFR32 series and config"
-#endif
- uint32_t pin = BOARD_USART_RX_PIN;
- uint32_t index = pin;
- index >>= 1;
- if((pin % 2) == 0)
- {
- /* Even IRQ (only one pin per channel supported) */
- m_even_callbacks[index] = cb;
- }
- else
- {
- /* Odd IRQ (only one pin per channel supported) */
- m_odd_callbacks[index] = cb;
- }
-
- pin_config(BOARD_USART_RX_PIN, BOARD_USART_GPIO_PORT);
- /* Enable interrupt source for even pins */
- Sys_clearFastAppIrq(GPIO_EVEN_IRQn);
- Sys_enableFastAppIrq(GPIO_EVEN_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_HI,
- GPIO_EVEN_IRQHandler);
- Sys_clearFastAppIrq(GPIO_ODD_IRQn);
- Sys_enableFastAppIrq(GPIO_ODD_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_HI,
- GPIO_ODD_IRQHandler);
-}
-
-void Wakeup_off(void)
-{
- Sys_disableAppIrq(GPIO_EVEN_IRQn);
- Sys_clearFastAppIrq(GPIO_EVEN_IRQn);
- Sys_disableAppIrq(GPIO_ODD_IRQn);
- Sys_clearFastAppIrq(GPIO_ODD_IRQn);
-}
-
-void Wakeup_clearIrq(void)
-{
- clear_interrupt(BOARD_USART_RX_PIN);
-}
-
-void Wakeup_setEdgeIRQ(exti_irq_config_e edge, bool enable)
-{
- bool risingEdge, fallingEdge;
- edge & EXTI_IRQ_RISING_EDGE ? (risingEdge = true) : (risingEdge = false);
- edge & EXTI_IRQ_FALLING_EDGE ? (fallingEdge = true) : (fallingEdge = false);
- GPIO_IntConfig((GPIO_Port_TypeDef)BOARD_USART_GPIO_PORT, BOARD_USART_RX_PIN,
- risingEdge,
- fallingEdge,
- enable);
-}
-
-void __attribute__((__interrupt__)) GPIO_EVEN_IRQHandler(void)
-{
-#if defined(_SILICON_LABS_32B_SERIES_1)
- uint32_t epin = GPIO->IF & _GPIO_IF_EXT_MASK;
- epin &= GPIO->IEN & _GPIO_IEN_EXT_MASK;
-#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- uint32_t epin = GPIO->IF & _GPIO_IF_EXT_MASK;
- epin &= GPIO->IEN & _GPIO_IEN_EXTIEN_MASK;
-#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
- uint32_t epin = GPIO->IF & 0x0FFF;
- epin &= GPIO->IEN & 0x0FFF;
-#else
-#error "Unknown EFR32 series and config"
-#endif
- uint32_t index;
- for(index = 0; index < IRQ_CHANNELS_PER_VECTOR; index++)
- {
- if((epin & 0x01) == 0x01)
- {
- clear_interrupt(2 * index);
- if(m_even_callbacks[index] != NULL)
- {
- m_even_callbacks[index]();
- }
- }
- epin >>= 2;
- }
-}
-
-void __attribute__((__interrupt__)) GPIO_ODD_IRQHandler(void)
-{
-#if defined(_SILICON_LABS_32B_SERIES_1)
- uint32_t opin = GPIO->IF & _GPIO_IF_EXT_MASK;
- opin &= GPIO->IEN & _GPIO_IEN_EXT_MASK;
-#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- uint32_t opin = GPIO->IF & _GPIO_IF_EXT_MASK;
- opin &= GPIO->IEN & _GPIO_IEN_EXTIEN_MASK;
-#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
- uint32_t opin = GPIO->IF & 0x0FFF;
- opin &= GPIO->IEN & 0x0FFF;
-#else
-#error "Unknown EFR32 series and config"
-#endif
- opin >>= 1;
- uint32_t index;
- for(index = 0; index < IRQ_CHANNELS_PER_VECTOR; index++)
- {
- if((opin & 0x01) == 0x01)
- {
- clear_interrupt(2 * index + 1);
- if(m_odd_callbacks[index] != NULL)
- {
- m_odd_callbacks[index]();
- }
- }
- opin >>= 2;
- }
-}
-
diff --git a/libraries/dualmcu/drivers/efr32/io.c b/libraries/dualmcu/drivers/efr32/io.c
deleted file mode 100644
index c62241cb..00000000
--- a/libraries/dualmcu/drivers/efr32/io.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Copyright 2019 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-
-#include "hal_api.h"
-#include "io.h"
-#include "board.h"
-
-#if defined(BOARD_UART_INT_PIN) && defined(BOARD_UART_INT_PORT)
-
-void Io_init(void)
-{
-// /* Enable clocks */
- CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
-
- hal_gpio_set_mode(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN);
-}
-
-void Io_enableUartIrq(void)
-{
-
- hal_gpio_set_mode(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN,
- GPIO_MODE_OUT_PP);
-}
-
-void Io_setUartIrq(void)
-{
- // Active low IRQ pin
- hal_gpio_clear(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN);
-}
-
-void Io_clearUartIrq(void)
-{
- // To clear we pull pin up
- hal_gpio_set(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN);
-}
-
-void Io_setModeDisabled(void)
-{
- // Disable pin
- hal_gpio_set_mode(BOARD_UART_INT_PORT,
- BOARD_UART_INT_PIN,
- GPIO_MODE_DISABLED);
-}
-
-#else
-// IRQ pin not defined, no functionality
-void Io_init(void)
-{
-}
-
-void Io_enableUartIrq(void)
-{
-}
-
-void Io_setUartIrq(void)
-{
-}
-
-void Io_clearUartIrq(void)
-{
-}
-#endif
diff --git a/libraries/dualmcu/drivers/efr32/makefile b/libraries/dualmcu/drivers/efr32/makefile
deleted file mode 100644
index 292e78eb..00000000
--- a/libraries/dualmcu/drivers/efr32/makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-EFR32_DRIVERS_PREFIX := $(DRIVERS_PREFIX)efr32/
-
-SRCS += $(EFR32_DRIVERS_PREFIX)exti.c \
- $(EFR32_DRIVERS_PREFIX)io.c
diff --git a/libraries/dualmcu/drivers/indication_signal.c b/libraries/dualmcu/drivers/indication_signal.c
new file mode 100644
index 00000000..462457b6
--- /dev/null
+++ b/libraries/dualmcu/drivers/indication_signal.c
@@ -0,0 +1,54 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file indication_signal.c
+ * \brief Used to generate the Interrupt ReQuest ("IRQ") signal to notify the application that it has one or more pending indications.
+ */
+
+#include "board.h"
+#include "gpio.h"
+
+#ifdef BOARD_GPIO_ID_UART_IRQ
+
+void IndicationSignal_enable(void)
+{
+ const gpio_out_cfg_t gpio_out_cfg =
+ {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH // Active low IRQ pin
+ };
+
+ Gpio_outputSetCfg(BOARD_GPIO_ID_UART_IRQ, &gpio_out_cfg);
+}
+
+void IndicationSignal_set(void)
+{
+ // Active low IRQ pin
+ Gpio_outputWrite(BOARD_GPIO_ID_UART_IRQ, GPIO_LEVEL_LOW);
+}
+
+void IndicationSignal_clear(void)
+{
+ // Active low IRQ pin
+ Gpio_outputWrite(BOARD_GPIO_ID_UART_IRQ, GPIO_LEVEL_HIGH);
+}
+
+#else // else if BOARD_GPIO_ID_UART_IRQ is undefined
+
+void IndicationSignal_enable(void)
+{
+}
+
+void IndicationSignal_set(void)
+{
+}
+
+void IndicationSignal_clear(void)
+{
+}
+
+#endif // BOARD_GPIO_ID_UART_IRQ
diff --git a/libraries/dualmcu/drivers/indication_signal.h b/libraries/dualmcu/drivers/indication_signal.h
new file mode 100644
index 00000000..a72e2c35
--- /dev/null
+++ b/libraries/dualmcu/drivers/indication_signal.h
@@ -0,0 +1,30 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file indication_signal.h
+ * \brief Used to generate the Interrupt ReQuest ("IRQ") signal to notify the application that it has one or more pending indications.
+ */
+
+#ifndef INDICATION_SIGNAL_
+#define INDICATION_SIGNAL_
+
+/**
+ * \brief Enables indication signal (UART IRQ) pin
+ */
+void IndicationSignal_enable(void);
+
+/**
+ * \brief Sets (asserts) indication signal (UART IRQ) pin
+ */
+void IndicationSignal_set(void);
+
+/**
+ * \brief Clears (de-asserts) indication signal (UART IRQ) pin
+ */
+void IndicationSignal_clear(void);
+
+#endif /* INDICATION_SIGNAL_ */
diff --git a/libraries/dualmcu/drivers/io.h b/libraries/dualmcu/drivers/io.h
deleted file mode 100644
index e6641d1a..00000000
--- a/libraries/dualmcu/drivers/io.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright 2017 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-#ifndef EXTI_H_
-#define EXTI_H_
-
-#include "api.h"
-
-/**
- * \brief Initialize IO's to a known state
- *
- */
-void Io_init(void);
-
-/**
- * \brief Enables UART IRQ pin
- */
-void Io_enableUartIrq(void);
-
-/**
- * \brief Sets (asserts) UART IRQ pin
- */
-void Io_setUartIrq(void);
-
-/**
- * \brief Clears (de-asserts) UART IRQ pin
- */
-void Io_clearUartIrq(void);
-
-typedef enum
-{
- EXTI_IRQ_RISING_EDGE = 0x01,
- EXTI_IRQ_FALLING_EDGE = 0x10,
- EXTI_IRQ_STATE_CHANGE = EXTI_IRQ_RISING_EDGE | EXTI_IRQ_FALLING_EDGE
-}exti_irq_config_e;
-
-/**
- * \brief Mandatory callback for EXTI events
- */
-typedef void (*wakeup_cb_f)(void);
-
-/**
- * \brief Setup wake-up pin
- * \param cb
- * Mandatory callback that is invoked on event
- * \post Pin (EXTI channel) is fired and waiting for a falling edge trigger
- */
-void Wakeup_pinInit(wakeup_cb_f cb);
-
-/**
- * \brief Disable wake-up functionality.
- */
-void Wakeup_off(void);
-
-/**
- * \brief Clear interrupt source flag
- */
-void Wakeup_clearIrq(void);
-
-/**
- * \brief Change edge for wake-up pin
- * \param edge
- * Edge type to configure
- * \param enable
- * Enable pin interrrupt
- */
-void Wakeup_setEdgeIRQ(exti_irq_config_e edge, bool enable);
-#endif /* EXTI_H_ */
diff --git a/libraries/dualmcu/drivers/makefile b/libraries/dualmcu/drivers/makefile
index 88d7bd39..51a3ab51 100644
--- a/libraries/dualmcu/drivers/makefile
+++ b/libraries/dualmcu/drivers/makefile
@@ -3,10 +3,5 @@ DRIVERS_PREFIX := $(WP_LIB_PATH)dualmcu/drivers/
INCLUDES += -I$(DRIVERS_PREFIX)
-ifneq (,$(filter $(MCU), nrf52 nrf91))
- include $(DRIVERS_PREFIX)nrf/makefile
-else ifeq ($(MCU),efr32)
- include $(DRIVERS_PREFIX)efr32/makefile
-else
- $(error Cannot determine MCU for drivers)
-endif
+SRCS += $(DRIVERS_PREFIX)indication_signal.c
+SRCS += $(DRIVERS_PREFIX)uart_wakeup.c
diff --git a/libraries/dualmcu/drivers/nrf/exti.c b/libraries/dualmcu/drivers/nrf/exti.c
deleted file mode 100644
index 2163ba46..00000000
--- a/libraries/dualmcu/drivers/nrf/exti.c
+++ /dev/null
@@ -1,107 +0,0 @@
-/* Copyright 2017 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-#include
-#include
-
-#include "hal_api.h"
-#include "io.h"
-#include "api.h"
-#include "board.h"
-
-#ifndef UART_USE_USB
-// Callback for wake-up pin
-static wakeup_cb_f m_callback;
-
-// Declare the GPIOTE ISR
-void __attribute__((__interrupt__)) GPIOTE_IRQHandler(void);
-
-void Wakeup_pinInit(wakeup_cb_f cb)
-{
- // Clear interrupt sources and flags
- NRF_GPIOTE->INTENCLR = 0xFFFFFFFF;
- NRF_GPIOTE->EVENTS_PORT = 0;
- // Start with falling edge trigger
- nrf_gpio_cfg_sense_set(BOARD_USART_RX_PIN, NRF_GPIO_PIN_SENSE_LOW);
- m_callback = cb;
- Sys_clearFastAppIrq(GPIOTE_IRQn);
- Sys_enableFastAppIrq(GPIOTE_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_HI,
- GPIOTE_IRQHandler);
-}
-
-void Wakeup_off(void)
-{
- Sys_disableAppIrq(GPIOTE_IRQn);
- Sys_clearFastAppIrq(GPIOTE_IRQn);
-}
-
-void Wakeup_clearIrq(void)
-{
- NRF_GPIOTE->EVENTS_PORT = 0;
-}
-
-void Wakeup_setEdgeIRQ(exti_irq_config_e edge, bool enable)
-{
- uint8_t mode = NRF_GPIO_PIN_NOSENSE;
- if(edge & EXTI_IRQ_RISING_EDGE)
- {
- mode = NRF_GPIO_PIN_SENSE_HIGH;
- }
- else if(edge & EXTI_IRQ_FALLING_EDGE)
- {
- mode = NRF_GPIO_PIN_SENSE_LOW;
- }
-
- /* Enable/disable the rising edge interrupt. */
- nrf_gpio_cfg_sense_set(BOARD_USART_RX_PIN, mode);
-
- /* Clear any pending interrupt. */
- Wakeup_clearIrq();
-
- /* Finally enable/disable interrupt. */
- if (enable)
- {
- NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
- }
- else
- {
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
- }
-}
-
-void __attribute__((__interrupt__)) GPIOTE_IRQHandler(void)
-{
- if (NRF_GPIOTE->EVENTS_PORT != 0)
- {
- NRF_GPIOTE->EVENTS_PORT = 0;
- // read any event from peripheral to flush the write buffer:
- EVENT_READBACK = NRF_GPIOTE->EVENTS_PORT;
- if (m_callback)
- {
- m_callback();
- }
- }
-}
-#else
-// With USB connection, no wakeup mechanism (not needed)
-void Wakeup_pinInit(wakeup_cb_f cb)
-{
- (void) cb;
-}
-
-void Wakeup_off(void)
-{
-}
-
-void Wakeup_clearIrq(void)
-{
-}
-
-void Wakeup_setEdgeIRQ(exti_irq_config_e edge, bool enable)
-{
-}
-#endif
diff --git a/libraries/dualmcu/drivers/nrf/io.c b/libraries/dualmcu/drivers/nrf/io.c
deleted file mode 100644
index 8bb15a3f..00000000
--- a/libraries/dualmcu/drivers/nrf/io.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright 2017 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-
-#include "hal_api.h"
-#include "board.h"
-
-#ifdef BOARD_UART_IRQ_PIN
-
-void Io_init(void)
-{
- // Disconnect uart_irq_pin
- nrf_gpio_cfg_default(BOARD_UART_IRQ_PIN);
- // But set light pull-up
- nrf_gpio_pin_set(BOARD_UART_IRQ_PIN);
-}
-
-void Io_enableUartIrq(void)
-{
- nrf_gpio_cfg(BOARD_UART_IRQ_PIN,
- NRF_GPIO_PIN_DIR_OUTPUT,
- NRF_GPIO_PIN_INPUT_CONNECT,
- NRF_GPIO_PIN_NOPULL,
- NRF_GPIO_PIN_S0S1,
- NRF_GPIO_PIN_NOSENSE);
-}
-
-void Io_setUartIrq(void)
-{
- // Active low IRQ pin
- nrf_gpio_pin_clear(BOARD_UART_IRQ_PIN);
-}
-
-void Io_clearUartIrq(void)
-{
- // To clear we pull pin up
- nrf_gpio_pin_set(BOARD_UART_IRQ_PIN);
-}
-
-#else
-
-// IRQ pin not defined, no functionality
-void Io_init(void)
-{
-}
-
-void Io_enableUartIrq(void)
-{
-}
-
-void Io_setUartIrq(void)
-{
-}
-
-void Io_clearUartIrq(void)
-{
-}
-
-#endif
diff --git a/libraries/dualmcu/drivers/nrf/makefile b/libraries/dualmcu/drivers/nrf/makefile
deleted file mode 100644
index f5b1a12f..00000000
--- a/libraries/dualmcu/drivers/nrf/makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-NRF_DRIVERS_PREFIX := $(DRIVERS_PREFIX)nrf/
-
-SRCS += $(NRF_DRIVERS_PREFIX)exti.c \
- $(NRF_DRIVERS_PREFIX)io.c \
diff --git a/libraries/dualmcu/drivers/uart_wakeup.c b/libraries/dualmcu/drivers/uart_wakeup.c
new file mode 100644
index 00000000..18c4c60a
--- /dev/null
+++ b/libraries/dualmcu/drivers/uart_wakeup.c
@@ -0,0 +1,53 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file uart_wakeup.c
+ * \brief Used to detect rising/falling edges on the UART RX GPIO in order to wake up the UART receiver.
+ */
+
+#include "gpio.h"
+#include "board.h"
+#include "hal_api.h"
+
+#ifndef UART_USE_USB
+
+void UartWakeup_enable(gpio_in_event_cb_f cb)
+{
+ const gpio_in_cfg_t gpio_in_cfg =
+ {
+ .event_cb = cb,
+ .event_cfg = GPIO_IN_EVENT_RISING_EDGE | GPIO_IN_EVENT_FALLING_EDGE,
+ .in_mode_cfg = GPIO_IN_PULL_NONE
+ };
+
+ Gpio_inputSetCfg(BOARD_GPIO_ID_USART_WAKEUP, &gpio_in_cfg);
+}
+
+void UartWakeup_disable(void)
+{
+ const gpio_in_cfg_t gpio_in_cfg =
+ {
+ .event_cb = NULL,
+ .event_cfg = GPIO_IN_EVENT_NONE,
+ .in_mode_cfg = GPIO_IN_PULL_NONE
+ };
+
+ Gpio_inputSetCfg(BOARD_GPIO_ID_USART_WAKEUP, &gpio_in_cfg);
+}
+
+#else // else if UART_USE_USB is defined
+// With USB connection, no wakeup mechanism (not needed)
+
+void UartWakeup_enable(gpio_in_event_cb_f cb)
+{
+}
+
+void UartWakeup_disable(void)
+{
+}
+
+#endif // UART_USE_USB
diff --git a/libraries/dualmcu/drivers/uart_wakeup.h b/libraries/dualmcu/drivers/uart_wakeup.h
new file mode 100644
index 00000000..ca84054e
--- /dev/null
+++ b/libraries/dualmcu/drivers/uart_wakeup.h
@@ -0,0 +1,29 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file uart_wakeup.c
+ * \brief Used to detect rising/falling edges on the UART RX GPIO in order to wake up the UART receiver.
+ */
+
+#ifndef UART_WAKEUP_
+#define UART_WAKEUP_
+
+#include "gpio.h"
+
+/**
+ * \brief Enable wake-up functionality.
+ * \param cb
+ * Callback that is invoked on GPIO edge transition
+ */
+void UartWakeup_enable(gpio_in_event_cb_f cb);
+
+/**
+ * \brief Disable wake-up functionality.
+ */
+void UartWakeup_disable(void);
+
+#endif /* UART_WAKEUP_ */
diff --git a/libraries/dualmcu/dualmcu_lib.c b/libraries/dualmcu/dualmcu_lib.c
index ce860320..4f97a33d 100644
--- a/libraries/dualmcu/dualmcu_lib.c
+++ b/libraries/dualmcu/dualmcu_lib.c
@@ -1,12 +1,8 @@
#include "dualmcu_lib.h"
-#include "io.h"
#include "waps.h"
dualmcu_lib_res_e Dualmcu_lib_init(uint32_t baudrate, bool flow_ctrl)
{
- // Initialize IO's (enable clock and initialize pins)
- Io_init();
-
// Initialize the Dual-MCU API protocol
if (Waps_init(baudrate, flow_ctrl))
{
diff --git a/libraries/dualmcu/waps/comm/uart/waps_uart.c b/libraries/dualmcu/waps/comm/uart/waps_uart.c
index c3affe81..5eb202ed 100644
--- a/libraries/dualmcu/waps/comm/uart/waps_uart.c
+++ b/libraries/dualmcu/waps/comm/uart/waps_uart.c
@@ -10,7 +10,7 @@
#include
#include
-#include "io.h"
+#include "indication_signal.h"
#include "usart.h"
#include "crc.h"
#include "waps/waps_buffer_sizes.h"
@@ -119,8 +119,8 @@ void Waps_uart_powerReset(void)
}
// Initialize UART IRQ pin
- Io_enableUartIrq();
- Io_clearUartIrq();
+ IndicationSignal_enable();
+ IndicationSignal_clear();
}
bool Waps_uart_send(const void * buffer, uint32_t size)
@@ -160,12 +160,12 @@ void Waps_uart_setIrq(bool state)
if(state)
{
// Assert IRQ pin
- Io_setUartIrq();
+ IndicationSignal_set();
}
else
{
// De-assert IRQ pin
- Io_clearUartIrq();
+ IndicationSignal_clear();
}
}
diff --git a/libraries/dualmcu/waps/comm/uart/waps_uart_power.c b/libraries/dualmcu/waps/comm/uart/waps_uart_power.c
index 3b91fb36..fd7f49eb 100644
--- a/libraries/dualmcu/waps/comm/uart/waps_uart_power.c
+++ b/libraries/dualmcu/waps/comm/uart/waps_uart_power.c
@@ -7,8 +7,8 @@
#include
#include "waps_private.h"
-
-#include "io.h"
+#include "uart_wakeup.h"
+#include "gpio.h"
#include "ds.h"
#include "usart.h"
@@ -57,7 +57,7 @@ static volatile usart_power_state_e m_power_on = USART_POWER_OFF;
/**
* \brief Callback for RX pin state change
*/
-static void uart_gpio_isr(void);
+static void uart_gpio_isr(gpio_id_t gpio_id, gpio_in_event_e gpio_event);
/**
* \brief Turn receiver power off
@@ -73,9 +73,7 @@ void Waps_uart_AutoPowerOn(void)
{
Sys_enterCriticalSection();
m_power_on = USART_POWER_OFF;
- Wakeup_pinInit(uart_gpio_isr);
- // Expecting falling edge interrupt
- Wakeup_setEdgeIRQ(EXTI_IRQ_FALLING_EDGE, true);
+ UartWakeup_enable(uart_gpio_isr);
m_autopower_enabled = true;
Sys_exitCriticalSection();
}
@@ -84,9 +82,7 @@ void Waps_uart_AutoPowerOff(void)
{
Sys_enterCriticalSection();
m_power_on = USART_POWER_OFF;
- Wakeup_setEdgeIRQ(EXTI_IRQ_FALLING_EDGE, false);
- Wakeup_clearIrq();
- Wakeup_off();
+ UartWakeup_disable();
m_autopower_enabled = false;
Sys_exitCriticalSection();
}
@@ -127,21 +123,19 @@ void Waps_uart_powerOff(void)
}
/** This function expects three preamble bytes, will not work otherwise */
-static void uart_gpio_isr(void)
+static void uart_gpio_isr(gpio_id_t gpio_id, gpio_in_event_e gpio_event)
{
- if(m_power_on == USART_POWER_OFF)
+ if((m_power_on == USART_POWER_OFF) && (gpio_event == GPIO_IN_EVENT_FALLING_EDGE))
{
/* MCU Wake-up (falling edge)! Start edge trigger VERY quickly */
Sys_enterCriticalSection();
- /* Change sense direction and enable rising edge trigger */
- Wakeup_setEdgeIRQ(EXTI_IRQ_RISING_EDGE, true);
m_power_on = USART_POWER_UP;
Sys_exitCriticalSection();
// Rising edge comes very fast, may not be safe to enter deep sleep
DS_Disable(DS_SOURCE_USART_POWER);
wakeup_task();
}
- else if(m_power_on == USART_POWER_UP)
+ else if((m_power_on == USART_POWER_UP) && (gpio_event == GPIO_IN_EVENT_RISING_EDGE))
{
/* Rising edge (receiver is on!) enable receiver and disable isr */
Sys_enterCriticalSection();
@@ -152,7 +146,7 @@ static void uart_gpio_isr(void)
Sys_exitCriticalSection();
// Uart is now awake, safe to enable deep sleep
DS_Enable(DS_SOURCE_USART_POWER);
- Wakeup_setEdgeIRQ(EXTI_IRQ_FALLING_EDGE, false);
+ UartWakeup_disable();
}
}
@@ -187,6 +181,6 @@ static void power_off(void)
/* Power is now off */
m_power_on = USART_POWER_OFF;
- /* Change edge to falling edge and enable power-up pin */
- Wakeup_setEdgeIRQ(EXTI_IRQ_FALLING_EDGE, true);
+ /* Enable detection of UART RX rising/falling edges, so that the UART receiver can be woken */
+ UartWakeup_enable(uart_gpio_isr);
}
diff --git a/libraries/local_provisioning/local_provisioning.c b/libraries/local_provisioning/local_provisioning.c
index 20c6d9a9..3780497a 100644
--- a/libraries/local_provisioning/local_provisioning.c
+++ b/libraries/local_provisioning/local_provisioning.c
@@ -292,7 +292,7 @@ static void enable_proxy(void)
// add filter for proxy asynchronously in case we are not started yet
// In fact if a sink, adding filter may trigger immediately cb and enabling
// joining beacon will work only after stack is really started (app_init has returned)
- App_Scheduler_addTask_execTime(add_filter_for_proxy, APP_SCHEDULER_SCHEDULE_ASAP, 50);
+ App_Scheduler_addTask_execTime(add_filter_for_proxy, APP_SCHEDULER_SCHEDULE_ASAP, 60);
}
/**
diff --git a/libraries/scheduler/app_scheduler.c b/libraries/scheduler/app_scheduler.c
index cd7a0cb4..81110746 100644
--- a/libraries/scheduler/app_scheduler.c
+++ b/libraries/scheduler/app_scheduler.c
@@ -19,8 +19,8 @@ static uint32_t m_max_time_ms;
*/
static bool m_initialized = false;
-/** Measured time on nrf52 (13us) */
-#define EXECUTION_TIME_NEEDED_FOR_SCHEDULING_US 20
+/** Measured time on nrf52 (13us) and nrf91 (32us) */
+#define EXECUTION_TIME_NEEDED_FOR_SCHEDULING_US 35
/** Maximum execution time application can request from stack (100ms) */
#define MAX_EXECUTION_TIME_ALLOWED_BY_STACK_US (100 * 1000)
@@ -419,7 +419,10 @@ void App_Scheduler_init()
}
// Maximum time to postpone the periodic work
- m_max_time_ms = lib_time->getMaxHpDelay() / 1000;
+ // Add some margin to avoid rounding issue. So take 80% of the max value
+ // In fact it is also used as the value to determine in which time domain
+ // tasks are scheduled (hp or coarse timestamp)
+ m_max_time_ms = lib_time->getMaxHpDelay() / 1000 * 8 / 10;
m_next_task_p = NULL;
m_force_reschedule = false;
diff --git a/libraries/shared_data/shared_data.c b/libraries/shared_data/shared_data.c
index b6a021bc..51e65ff7 100644
--- a/libraries/shared_data/shared_data.c
+++ b/libraries/shared_data/shared_data.c
@@ -9,6 +9,10 @@
#define DEBUG_LOG_MAX_LEVEL LVL_NOLOG
#include "debug_log.h"
+#ifdef WIRESHARK
+#include "wireshark.h"
+#endif
+
/** Some helpers macros for packet filtering. */
#define IS_UNICAST(mode) (mode == SHARED_DATA_NET_MODE_UNICAST)
#define IS_BROADCAST(mode) (mode == SHARED_DATA_NET_MODE_BROADCAST)
@@ -224,6 +228,21 @@ static app_lib_data_receive_res_e received_cb(
{
app_lib_data_receive_res_e res = APP_LIB_DATA_RECEIVE_RES_NOT_FOR_APP;
shared_data_item_t * item;
+
+#ifdef WIRESHARK
+ Wireshark_print(
+ data->src_address,
+ data->dest_address,
+ data->qos,
+ data->src_endpoint,
+ data->dest_endpoint,
+ data->rssi,
+ data->delay_hp,
+ data->bytes,
+ data->num_bytes
+ );
+#endif
+
sl_list_t * i = sl_list_begin((sl_list_t *)&m_shared_data_head);
LOG(LVL_DEBUG, "Rx (%u, %d -> %d)",
@@ -300,6 +319,11 @@ app_res_e Shared_Data_init(void)
return APP_RES_OK;
}
+#ifdef WIRESHARK
+ Wireshark_init();
+#endif
+
+
sl_list_init(&m_shared_data_head);
m_iterating_list = false;
@@ -478,6 +502,27 @@ app_lib_data_send_res_e Shared_Data_sendData(
/* Send the data packet. */
res = lib_data->sendData(data);
+ if (res == APP_LIB_DATA_SEND_RES_SUCCESS)
+ {
+ app_addr_t node_addr;
+ lib_settings->getNodeAddress(&node_addr);
+
+#ifdef WIRESHARK
+ Wireshark_print(
+ // no rssi nor delay so 0 for both
+ node_addr,
+ data->dest_address,
+ data->qos,
+ data->src_endpoint,
+ data->dest_endpoint,
+ 0,
+ 0,
+ data->bytes,
+ data->num_bytes
+ );
+#endif
+ }
+
/* Free resources if packet is tracked. */
if (res != APP_LIB_DATA_SEND_RES_SUCCESS && sent_cb != NULL)
{
diff --git a/makefile b/makefile
index 8fc75eab..53d8e82b 100644
--- a/makefile
+++ b/makefile
@@ -8,17 +8,27 @@ include makefile_common.mk
#
# Scratchpads for OTAP
+
FULL_SCRATCHPAD_NAME := $(APP_NAME)_$(FIRMWARE_NAME)
FULL_SCRATCHPAD_BIN := $(BUILDPREFIX_APP)$(FULL_SCRATCHPAD_NAME).otap
APP_SCRATCHPAD_NAME := $(APP_NAME)
APP_SCRATCHPAD_BIN := $(BUILDPREFIX_APP)$(APP_SCRATCHPAD_NAME).otap
STACK_SCRATCHPAD_NAME := $(FIRMWARE_NAME)
STACK_SCRATCHPAD_BIN := $(BUILDPREFIX_APP)$(STACK_SCRATCHPAD_NAME).otap
+ifneq ($(modemfw_area_id),)
+ifneq ($(radio),none)
+MODEM_FW_CBOR=$(BUILDPREFIX_APP)stack/modem_fw.cbor
+ifneq ("$(wildcard $(MODEM_FW_CBOR))","")
+FULL_SCRATCHPAD_WITH_MODEMFW_NAME := $(APP_NAME)_$(FIRMWARE_NAME)_modem_fw
+FULL_SCRATCHPAD_WITH_MODEMFW_BIN := $(BUILDPREFIX_APP)$(FULL_SCRATCHPAD_WITH_MODEMFW_NAME).otap
+endif
+endif
+endif
BOOTLOADER_CONFIG_INI := $(BUILDPREFIX_APP)bootloader_full_config.ini
PLATFORM_CONFIG_INI := $(MCU_PATH)$(MCU_FAMILY)/$(MCU)/ini_files/$(MCU)$(MCU_SUB)$(MCU_MEM_VAR)_platform.ini
-CLEAN += $(FULL_SCRATCHPAD_BIN) $(APP_SCRATCHPAD_BIN) $(STACK_SCRATCHPAD_BIN) $(BOOTLOADER_CONFIG_INI)
+CLEAN += $(FULL_SCRATCHPAD_BIN) $(APP_SCRATCHPAD_BIN) $(STACK_SCRATCHPAD_BIN) $(FULL_SCRATCHPAD_WITH_MODEMFW_BIN) $(BOOTLOADER_CONFIG_INI)
# Final image for programming
FINAL_IMAGE_NAME := final_image_$(APP_NAME)
@@ -69,6 +79,15 @@ updater_app_area_id=$(updater_app_specific_area_id)$(HW_VARIANT_ID)
#
# Functions
+define BUILD_FULL_SCRATCHPAD_WITH_MODEMFW
+ @echo " Creating Full Scratchpad with modem: $(2) + $(3) + $(4) -> $(1)"
+ $(SCRAT_GEN) --configfile=$(BOOTLOADER_CONFIG_INI) \
+ $(1) \
+ $(modemfw_area_id):$(2) \
+ $(patsubst %.hex,%.conf,$(3)):$(firmware_area_id):$(3) \
+ $(app_major).$(app_minor).$(app_maintenance).$(app_development):$(app_area_id):$(4)
+endef
+
define BUILD_FULL_SCRATCHPAD
@echo " Creating Full Scratchpad: $(2) + $(3) -> $(1)"
$(SCRAT_GEN) --configfile=$(BOOTLOADER_CONFIG_INI) \
@@ -116,7 +135,7 @@ all: $(TARGETS)
app_only: $(APP_HEX) $(APP_SCRATCHPAD_BIN)
-otap: $(FULL_SCRATCHPAD_BIN) $(APP_SCRATCHPAD_BIN) $(STACK_SCRATCHPAD_BIN)
+otap: $(FULL_SCRATCHPAD_BIN) $(APP_SCRATCHPAD_BIN) $(STACK_SCRATCHPAD_BIN) $(FULL_SCRATCHPAD_WITH_MODEMFW_BIN)
bootloader: $(BOOTLOADER_HEX)
@@ -183,6 +202,14 @@ $(APP_SCRATCHPAD_BIN): initial_setup $(APP_HEX) $(BOOTLOADER_CONFIG_INI)
$(FULL_SCRATCHPAD_BIN): initial_setup $(STACK_HEX) $(APP_HEX) $(BOOTLOADER_CONFIG_INI)
$(call BUILD_FULL_SCRATCHPAD,$(FULL_SCRATCHPAD_BIN),$(STACK_HEX),$(APP_HEX))
+ifneq ($(modemfw_area_id),)
+ifneq ($(radio),none)
+$(FULL_SCRATCHPAD_WITH_MODEMFW_BIN): initial_setup $(STACK_HEX) $(APP_HEX) $(BOOTLOADER_CONFIG_INI)
+ $(call BUILD_FULL_SCRATCHPAD_WITH_MODEMFW,$(FULL_SCRATCHPAD_WITH_MODEMFW_BIN),${MODEM_FW_CBOR},$(STACK_HEX),$(APP_HEX))
+
+endif
+endif
+
$(FINAL_IMAGE_HEX): initial_setup $(STACK_HEX) $(APP_HEX) $(BOOTLOADER_HEX) $(BOOTLOADER_CONFIG_INI)
$(call BUILD_HEX,$(FINAL_IMAGE_HEX),$(BOOTLOADER_HEX),$(STACK_HEX),$(APP_HEX),$(EXTRA_HEX))
diff --git a/makefile_app.mk b/makefile_app.mk
index 2e17f3ee..683b88a3 100644
--- a/makefile_app.mk
+++ b/makefile_app.mk
@@ -54,7 +54,10 @@ CFLAGS += -DVER_MAJOR=$(app_major) -DVER_MINOR=$(app_minor) -DVER_MAINT=$(app_ma
-include $(WP_LIB_PATH)makefile
INCLUDES += -I$(WP_LIB_PATH)
-# Include HAL drivers code
+# Include MCU config first
+-include $(MCU_PATH)config.mk
+
+# Include MCU HAL drivers code
-include $(HAL_API_PATH)makefile
# Include common MCU sources
@@ -107,4 +110,3 @@ clean:
$(RM) -rf $(CLEAN)
-include $(DEPS)
-
diff --git a/makefile_common.mk b/makefile_common.mk
index 1d068085..9f1816ee 100644
--- a/makefile_common.mk
+++ b/makefile_common.mk
@@ -3,7 +3,7 @@ GCC_TESTED_VERSION := 10.2.1
# Minimum binaries version required by this SDK version
MIN_BOOTLOADER_VERSION := 7
-MIN_STACK_VERSION := 5.3.0.0
+MIN_STACK_VERSION := 5.4.0.0
# SDK itself
SDK_PATH := .
diff --git a/makefile_stack.mk b/makefile_stack.mk
index b47ea5da..f9b3fd60 100644
--- a/makefile_stack.mk
+++ b/makefile_stack.mk
@@ -4,6 +4,7 @@ include makefile_common.mk
stack_mode?=normal
+modemfw_name?=
mac_profile?=ism_24_ghz
$(STACK_HEX): FORCE
@@ -19,6 +20,7 @@ $(STACK_HEX): FORCE
--mac_profile=$(mac_profile)\
--mac_profileid=$(mac_profileid)\
--mode=$(stack_mode)\
+ --modem_fw=$(modemfw_name)\
--radio=$(radio)\
--radio_config=$(radio_config)\
--version=$(MIN_STACK_VERSION)
diff --git a/mcu/common/button.c b/mcu/common/button.c
new file mode 100644
index 00000000..b25b2f3f
--- /dev/null
+++ b/mcu/common/button.c
@@ -0,0 +1,313 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/*
+ * \file button.c
+ * \brief Board-independent button functions.
+ */
+
+#include "button.h"
+#include "gpio.h"
+#include "board.h"
+#include "api.h"
+
+
+#ifdef BOARD_BUTTON_ID_LIST
+
+/*
+ * The selected board has buttons
+ */
+
+#ifndef BOARD_DEBOUNCE_TIME_MS
+/** \brief Debounce time of button in ms. It can be overwritten from board.h */
+#define BOARD_DEBOUNCE_TIME_MS 100
+#endif
+
+#ifndef BOARD_BUTTON_ACTIVE_LOW
+/** \brief Is button active low. It can be overwritten from board.h */
+#define BOARD_BUTTON_ACTIVE_LOW true
+#endif
+
+#ifndef BOARD_BUTTON_INTERNAL_PULL
+/** \brief Does the driver needs to activate internal pull-up/down.
+ * If true; pull-up (down) is enabled if BOARD_BUTTON_ACTIVE_LOW is
+ * true (false). It can be overwritten from board.h
+ */
+#define BOARD_BUTTON_INTERNAL_PULL true
+#endif
+
+/** \brief Button id to GPIO id map (array index: button id ; array value: GPIO id) */
+static const uint8_t m_id_map[] = BOARD_BUTTON_ID_LIST;
+
+/** \brief Compute number of button on the board */
+#define BOARD_BUTTON_NUMBER (sizeof(m_id_map) / sizeof(m_id_map[0]))
+
+typedef struct
+{
+ // Callback when button pressed
+ on_button_event_cb on_pressed;
+ // Callback when button released
+ on_button_event_cb on_released;
+ // Used for debounce
+ app_lib_time_timestamp_hp_t last_button_event;
+} button_internal_t;
+
+/** \brief Button id to button conf map (array index: button id ; array value: button conf) */
+static button_internal_t m_button_conf[BOARD_BUTTON_NUMBER];
+
+/** \brief Has the button library been initialized */
+static bool m_initialized = false;
+
+static void button_event_handle(gpio_id_t gpio_id, gpio_in_event_e gpio_event);
+static bool get_button_id_from_gpio_id(gpio_id_t gpio_id, uint8_t *button_id);
+
+static inline gpio_in_cfg_t get_button_gpio_cfg(void)
+{
+ gpio_in_cfg_t gpio_in_cfg;
+
+ gpio_in_cfg.event_cb = NULL;
+ gpio_in_cfg.event_cfg = GPIO_IN_EVENT_NONE;
+#if BOARD_BUTTON_INTERNAL_PULL
+#if BOARD_BUTTON_ACTIVE_LOW
+ gpio_in_cfg.in_mode_cfg = GPIO_IN_PULL_UP;
+#else
+ gpio_in_cfg.in_mode_cfg = GPIO_IN_PULL_DOWN;
+#endif // BOARD_BUTTON_ACTIVE_LOW
+#else
+ gpio_in_cfg.in_mode_cfg = GPIO_IN_PULL_NONE;
+#endif // BOARD_BUTTON_INTERNAL_PULL
+
+ return gpio_in_cfg;
+}
+
+void Button_init(void)
+{
+ uint8_t button_id;
+ app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
+ button_internal_t button_conf =
+ {
+ .on_pressed = NULL,
+ .on_released = NULL,
+ .last_button_event = now
+ };
+ gpio_id_t gpio_id;
+ gpio_in_cfg_t gpio_in_cfg;
+
+ if (m_initialized)
+ {
+ /* return if button initialization has already been performed */
+ return;
+ }
+
+ gpio_in_cfg = get_button_gpio_cfg();
+
+ for (button_id = 0; button_id < BOARD_BUTTON_NUMBER; button_id++)
+ {
+ gpio_id = m_id_map[button_id];
+ Gpio_inputSetCfg(gpio_id, &gpio_in_cfg);
+ m_button_conf[button_id] = button_conf;
+ }
+
+ m_initialized = true;
+}
+
+button_res_e Button_getState(uint8_t button_id, bool * state_p)
+{
+ gpio_level_e gpio_level = GPIO_LEVEL_LOW;
+ gpio_id_t gpio_id;
+
+ if (!m_initialized)
+ {
+ return BUTTON_RES_UNINITIALIZED;
+ }
+ if (button_id >= BOARD_BUTTON_NUMBER)
+ {
+ return BUTTON_RES_INVALID_ID;
+ }
+
+ gpio_id = m_id_map[button_id];
+ Gpio_inputRead(gpio_id, &gpio_level);
+
+ /*
+ * level | active_low | state |
+ * clear | 0 | 0 |
+ * set | 0 | 1 |
+ * clear | 1 | 1 |
+ * set | 1 | 0 |
+ */
+ *state_p = ((gpio_level != GPIO_LEVEL_LOW) != BOARD_BUTTON_ACTIVE_LOW);
+
+ return BUTTON_RES_OK;
+}
+
+button_res_e Button_register_for_event(uint8_t button_id,
+ button_event_e event,
+ on_button_event_cb cb)
+{
+ gpio_id_t gpio_id;
+ gpio_in_cfg_t gpio_in_cfg;
+
+ if (!m_initialized)
+ {
+ return BUTTON_RES_UNINITIALIZED;
+ }
+ if (button_id >= BOARD_BUTTON_NUMBER)
+ {
+ return BUTTON_RES_INVALID_ID;
+ }
+ if ((event != BUTTON_PRESSED && event != BUTTON_RELEASED) ||
+ (cb == NULL))
+ {
+ return BUTTON_RES_INVALID_PARAM;
+ }
+
+ gpio_in_cfg = get_button_gpio_cfg();
+
+ Sys_enterCriticalSection();
+
+ if (event == BUTTON_PRESSED)
+ {
+ m_button_conf[button_id].on_pressed = cb;
+ }
+ else
+ {
+ m_button_conf[button_id].on_released = cb;
+ }
+
+ /* if on both press and release */
+ if (m_button_conf[button_id].on_pressed &&
+ m_button_conf[button_id].on_released)
+ {
+ gpio_in_cfg.event_cfg = GPIO_IN_EVENT_RISING_EDGE | GPIO_IN_EVENT_FALLING_EDGE;
+ }
+ /* else if on press only or on release only */
+ else
+ {
+ /*
+ * button_event | active_low | gpio_event |
+ * on_pressed | 0 | on_rising_edge |
+ * on_released | 0 | on_falling_edge |
+ * on_pressed | 1 | on_falling_edge |
+ * on_released | 1 | on_rising_edge |
+ */
+ gpio_in_cfg.event_cfg = ((m_button_conf[button_id].on_pressed != NULL) != BOARD_BUTTON_ACTIVE_LOW) ?
+ GPIO_IN_EVENT_RISING_EDGE : GPIO_IN_EVENT_FALLING_EDGE;
+ }
+ gpio_in_cfg.event_cb = button_event_handle;
+
+ gpio_id = m_id_map[button_id];
+ Gpio_inputSetCfg(gpio_id, &gpio_in_cfg);
+
+ Sys_exitCriticalSection();
+
+ return BUTTON_RES_OK;
+}
+
+uint8_t Button_get_number(void)
+{
+ return BOARD_BUTTON_NUMBER;
+}
+
+static void button_event_handle(gpio_id_t gpio_id, gpio_in_event_e gpio_event)
+{
+ uint8_t button_id;
+ bool button_id_found;
+ app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
+
+ if (gpio_id >= Gpio_getNumber())
+ {
+ return;
+ }
+
+ /* get button id from gpio id */
+ button_id_found = get_button_id_from_gpio_id(gpio_id, &button_id);
+ if (button_id_found == false)
+ {
+ return;
+ }
+
+ if (lib_time->getTimeDiffUs(now, m_button_conf[button_id].last_button_event)
+ > (BOARD_DEBOUNCE_TIME_MS * 1000))
+ {
+ m_button_conf[button_id].last_button_event = now;
+
+ if ((m_button_conf[button_id].on_pressed) &&
+ (((gpio_event == GPIO_IN_EVENT_RISING_EDGE) && !BOARD_BUTTON_ACTIVE_LOW) ||
+ ((gpio_event == GPIO_IN_EVENT_FALLING_EDGE) && BOARD_BUTTON_ACTIVE_LOW)))
+ {
+ m_button_conf[button_id].on_pressed(button_id, BUTTON_PRESSED);
+ }
+ else if ((m_button_conf[button_id].on_released) &&
+ (((gpio_event == GPIO_IN_EVENT_FALLING_EDGE) && !BOARD_BUTTON_ACTIVE_LOW) ||
+ ((gpio_event == GPIO_IN_EVENT_RISING_EDGE) && BOARD_BUTTON_ACTIVE_LOW)))
+ {
+ m_button_conf[button_id].on_released(button_id, BUTTON_RELEASED);
+ }
+ }
+}
+
+static bool get_button_id_from_gpio_id(gpio_id_t gpio_id, uint8_t *button_id)
+{
+ uint8_t button_id_tmp;
+
+ if (button_id == NULL)
+ {
+ return false;
+ }
+
+ /* browse the button IDs and find the one that is mapped to the given GPIO id */
+ for (button_id_tmp = 0; button_id_tmp < BOARD_BUTTON_NUMBER; button_id_tmp++)
+ {
+ if (m_id_map[button_id_tmp] == gpio_id)
+ {
+ *button_id = button_id_tmp;
+ return true;
+ }
+ }
+ return false;
+}
+
+#else // BOARD_BUTTON_ID_LIST
+/*
+ * The selected board has no buttons
+ *
+ * As some example apps support such boards but also provide extra features
+ * when a board has buttons, the button driver has this dummy implementation
+ * to simplify the build process.
+ */
+
+void Button_init(void)
+{
+ // Do nothing
+}
+
+button_res_e Button_getState(uint8_t button_id, bool * state_p)
+{
+ (void) button_id;
+ *state_p = false;
+
+ // Invalid button number
+ return BUTTON_RES_INVALID_ID;
+}
+
+uint8_t Button_get_number(void)
+{
+ return 0;
+}
+
+button_res_e Button_register_for_event(uint8_t button_id,
+ button_event_e event,
+ on_button_event_cb cb)
+{
+ (void) button_id;
+ (void) event;
+ (void) cb;
+
+ // Invalid button number
+ return BUTTON_RES_INVALID_ID;
+}
+
+#endif // BOARD_BUTTON_ID_LIST
diff --git a/mcu/common/gpio_weak.c b/mcu/common/gpio_weak.c
new file mode 100644
index 00000000..1d4083b1
--- /dev/null
+++ b/mcu/common/gpio_weak.c
@@ -0,0 +1,87 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file gpio_weak.c
+ * \brief Definitions of gpio weak functions.
+ * \attention Should be compatible with the gpio.h interface.
+ */
+
+#include "gpio.h"
+
+gpio_res_e __attribute__((weak))
+ Gpio_init(void)
+{
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_inputSetCfg(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ (void) id;
+ (void) in_cfg;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_inputRead(gpio_id_t id, gpio_level_e *level)
+{
+ (void) id;
+ (void) level;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_outputSetCfg(gpio_id_t id, const gpio_out_cfg_t *out_cfg)
+{
+ (void) id;
+ (void) out_cfg;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak)) Gpio_outputWrite(gpio_id_t id, gpio_level_e level)
+{
+ (void) id;
+ (void) level;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_outputToggle(gpio_id_t id)
+{
+ (void) id;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_outputRead(gpio_id_t id, gpio_level_e *level)
+{
+ (void) id;
+ (void) level;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+gpio_res_e __attribute__((weak))
+ Gpio_getPin(gpio_id_t id, gpio_port_t *port, gpio_pin_t *pin)
+{
+ (void) id;
+ (void) port;
+ (void) pin;
+
+ return GPIO_RES_NOT_IMPLEMENTED;
+}
+
+uint8_t __attribute__((weak))
+ Gpio_getNumber(void)
+{
+ return 0;
+}
diff --git a/mcu/common/led.c b/mcu/common/led.c
new file mode 100644
index 00000000..734ed75e
--- /dev/null
+++ b/mcu/common/led.c
@@ -0,0 +1,180 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/*
+ * \file led.c
+ * \brief Board-independent led functions.
+ */
+
+#include "led.h"
+#include "gpio.h"
+#include "board.h"
+
+#ifdef BOARD_LED_ID_LIST
+
+/*
+ * The selected board has LEDs
+ */
+
+#ifndef BOARD_LED_ACTIVE_LOW
+/** \brief Are LEDs active low. It can be overwritten from board.h */
+#define BOARD_LED_ACTIVE_LOW true
+#endif
+
+/** \brief Button id to GPIO id map (array index: button id ; array value: GPIO id) */
+static const uint8_t m_id_map[] = BOARD_LED_ID_LIST;
+
+/** \brief Compute number of leds on the board */
+#define NUMBER_OF_LEDS (sizeof(m_id_map) / sizeof(m_id_map[0]))
+
+/** \brief Has the LED library been initialized */
+static bool m_initialized = false;
+
+void Led_init(void)
+{
+ gpio_id_t gpio_id;
+ uint8_t led_id;
+ gpio_out_cfg_t gpio_out_cfg = {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = BOARD_LED_ACTIVE_LOW ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW
+ };
+
+ if (m_initialized)
+ {
+ /* return if Led initialization has already been performed */
+ return;
+ }
+
+ for (led_id = 0; led_id < NUMBER_OF_LEDS; led_id++)
+ {
+ gpio_id = m_id_map[led_id];
+ Gpio_outputSetCfg(gpio_id, &gpio_out_cfg);
+ }
+
+ m_initialized = true;
+}
+
+led_res_e Led_set(uint8_t led_id, bool state)
+{
+ gpio_id_t gpio_id;
+ gpio_level_e gpio_level;
+
+ if (!m_initialized)
+ {
+ return LED_RES_UNINITIALIZED;
+ }
+ if (led_id >= NUMBER_OF_LEDS)
+ {
+ return LED_RES_INVALID_ID;
+ }
+
+ /*
+ * state | active_low | level |
+ * 0 | 0 | clear |
+ * 1 | 0 | set |
+ * 0 | 1 | set |
+ * 1 | 1 | clear |
+ */
+ gpio_level = (state != BOARD_LED_ACTIVE_LOW) ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW;
+
+ gpio_id = m_id_map[led_id];
+ Gpio_outputWrite(gpio_id, gpio_level);
+
+ return LED_RES_OK;
+}
+
+bool Led_get(uint8_t led_id)
+{
+ gpio_level_e level;
+ gpio_id_t gpio_id;
+ bool state;
+
+ if (!m_initialized)
+ {
+ return LED_RES_UNINITIALIZED;
+ }
+ if (led_id >= NUMBER_OF_LEDS)
+ {
+ return LED_RES_INVALID_ID;
+ }
+
+ gpio_id = m_id_map[led_id];
+ Gpio_outputRead(gpio_id, &level);
+
+ /*
+ * level | active_low | state |
+ * clear | 0 | 0 |
+ * set | 0 | 1 |
+ * clear | 1 | 1 |
+ * set | 1 | 0 |
+ */
+ state = (level != GPIO_LEVEL_LOW) != BOARD_LED_ACTIVE_LOW;
+
+ return state;
+}
+
+led_res_e Led_toggle(uint8_t led_id)
+{
+ gpio_id_t gpio_id;
+
+ if (!m_initialized)
+ {
+ return LED_RES_UNINITIALIZED;
+ }
+ if (led_id >= NUMBER_OF_LEDS)
+ {
+ return LED_RES_INVALID_ID;
+ }
+
+ gpio_id = m_id_map[led_id];
+ Gpio_outputToggle(gpio_id);
+
+ return LED_RES_OK;
+}
+
+uint8_t Led_getNumber(void)
+{
+ return NUMBER_OF_LEDS;
+}
+
+#else // BOARD_LED_ID_LIST
+
+/*
+ * The selected board has no LEDs
+ *
+ * As some example apps support such boards but also provide extra status
+ * information when a board has LEDs, the LED driver has this dummy
+ * implementation to simplify the build process.
+ */
+
+void Led_init(void)
+{
+ // Do nothing
+}
+
+led_res_e Led_set(uint8_t led_id, bool state)
+{
+ (void) led_id;
+ (void) state;
+
+ // Invalid LED number
+ return LED_RES_INVALID_ID;
+}
+
+led_res_e Led_toggle(uint8_t led_id)
+{
+ (void) led_id;
+
+ // Invalid LED number
+ return LED_RES_INVALID_ID;
+}
+
+uint8_t Led_getNumber(void)
+{
+ return 0;
+}
+
+#endif // BOARD_LED_ID_LIST
diff --git a/mcu/common/makefile b/mcu/common/makefile
index be599bd5..e755bd92 100644
--- a/mcu/common/makefile
+++ b/mcu/common/makefile
@@ -1,7 +1,19 @@
MCU_COMMON_SRCS_PATH := $(MCU_PATH)common/
+include $(MCU_COMMON_SRCS_PATH)radio/makefile
+
ASM_SRCS += $(MCU_COMMON_SRCS_PATH)entrypoint.s
SRCS += $(MCU_COMMON_SRCS_PATH)start.c
-include $(MCU_COMMON_SRCS_PATH)radio/makefile
+ifeq ($(HAL_BUTTON), yes)
+SRCS += $(MCU_COMMON_SRCS_PATH)button.c
+endif
+
+ifeq ($(HAL_LED), yes)
+SRCS += $(MCU_COMMON_SRCS_PATH)led.c
+endif
+
+ifeq ($(HAL_GPIO), yes)
+SRCS += $(MCU_COMMON_SRCS_PATH)gpio_weak.c
+endif
diff --git a/mcu/common/start.c b/mcu/common/start.c
index fdb3ee8e..7d261048 100644
--- a/mcu/common/start.c
+++ b/mcu/common/start.c
@@ -13,6 +13,7 @@
#include "api.h"
#include "board_init.h"
#include "libraries_init.h"
+#include "hal_init.h"
/** Addresses determined by the linker */
extern unsigned int __text_start__;
@@ -109,6 +110,9 @@ intptr_t _start(const app_global_functions_t * functions,
API_Open(functions);
+ /* Initialize HAL drivers */
+ Hal_init();
+
/* Call any board specific initialization */
Board_init();
diff --git a/mcu/config.mk b/mcu/config.mk
new file mode 100644
index 00000000..5a3b3489
--- /dev/null
+++ b/mcu/config.mk
@@ -0,0 +1,14 @@
+# Button lib requires the GPIO lib
+ifeq ($(HAL_BUTTON), yes)
+HAL_GPIO=yes
+endif
+
+# LED lib requires the GPIO lib
+ifeq ($(HAL_LED), yes)
+HAL_GPIO=yes
+endif
+
+# UART lib requires the GPIO lib
+ifeq ($(HAL_UART), yes)
+HAL_GPIO=yes
+endif
\ No newline at end of file
diff --git a/mcu/efr/common/vendor/em_eusart.c b/mcu/efr/common/vendor/em_eusart.c
new file mode 100644
index 00000000..a7ed6b07
--- /dev/null
+++ b/mcu/efr/common/vendor/em_eusart.c
@@ -0,0 +1,1345 @@
+/***************************************************************************//**
+ * @file
+ * @brief Universal asynchronous receiver/transmitter (EUSART) peripheral API
+ *******************************************************************************
+ * # License
+ * Copyright 2019 Silicon Laboratories Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+#include "em_eusart.h"
+#if defined(EUART_PRESENT) || defined(EUSART_PRESENT)
+#include "em_cmu.h"
+#include
+
+/*******************************************************************************
+ ********************************* DEFINES *********************************
+ ******************************************************************************/
+
+#if defined(EUART_PRESENT)
+ #define EUSART_REF_VALID(ref) ((ref) == EUART0)
+ #define EUSART_EM2_CAPABLE(ref) (true)
+ #define EUSART_RX_FIFO_SIZE 4u
+#elif defined(EUSART_PRESENT)
+ #define EUSART_REF_VALID(ref) (EUSART_NUM(ref) != -1)
+ #define EUSART_RX_FIFO_SIZE 16u
+#endif
+
+/*******************************************************************************
+ ************************** LOCAL VARIABLES ********************************
+ ******************************************************************************/
+#if defined(EUSART_DALICFG_DALIEN)
+static uint8_t dali_tx_nb_packets[EUSART_COUNT];
+static uint8_t dali_rx_nb_packets[EUSART_COUNT];
+#endif /* EUSART_DALICFG_DALIEN */
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+
+static CMU_Clock_TypeDef EUSART_ClockGet(EUSART_TypeDef *eusart);
+
+static void EUSART_AsyncInitCommon(EUSART_TypeDef *eusart,
+ const EUSART_UartInit_TypeDef *init,
+ const EUSART_IrDAInit_TypeDef *irdaInit,
+ const EUSART_DaliInit_TypeDef *daliInit);
+
+#if defined(EUSART_PRESENT)
+static void EUSART_SyncInitCommon(EUSART_TypeDef *eusart,
+ const EUSART_SpiInit_TypeDef *init);
+#endif
+
+/***************************************************************************//**
+ * Wait for ongoing sync of register(s) to the low-frequency domain to complete.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param mask A bitmask corresponding to SYNCBUSY register defined bits,
+ * indicating registers that must complete any ongoing
+ * synchronization.
+ ******************************************************************************/
+__STATIC_INLINE void eusart_sync(EUSART_TypeDef *eusart, uint32_t mask)
+{
+ // Wait for any pending previous write operation to have been completed
+ // in the low-frequency domain.
+ while ((eusart->SYNCBUSY & mask) != 0U) {
+ }
+}
+
+/***************************************************************************//**
+ * Calculate baudrate for a given reference frequency, clock division,
+ * and oversampling rate.
+ ******************************************************************************/
+__STATIC_INLINE uint32_t EUSART_AsyncBaudrateCalc(uint32_t refFreq,
+ uint32_t clkdiv,
+ EUSART_OVS_TypeDef ovs);
+
+/***************************************************************************//**
+ * Execute the EUSART peripheral disabling sequence.
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_Disable(EUSART_TypeDef *eusart);
+
+/*******************************************************************************
+ ************************** GLOBAL FUNCTIONS *******************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * Initializes the EUSART when used with the high frequency clock.
+ ******************************************************************************/
+void EUSART_UartInitHf(EUSART_TypeDef *eusart, const EUSART_UartInit_TypeDef *init)
+{
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+ // Init structure must be provided.
+ EFM_ASSERT(init);
+
+ // Assert features specific to HF.
+ // The oversampling must not be disabled when using a high frequency clock.
+ EFM_ASSERT(init->oversampling != eusartOVS0);
+
+ // Uart mode only supports up to 9 databits frame.
+ EFM_ASSERT(init->databits <= eusartDataBits9);
+
+ // Initialize EUSART with common features to HF and LF.
+ EUSART_AsyncInitCommon(eusart, init, NULL, NULL);
+}
+
+/***************************************************************************//**
+ * Initializes the EUSART when used with the low frequency clock.
+ *
+ * @note (1) When EUSART oversampling is set to eusartOVS0 (Disable), the peripheral
+ * clock frequency must be at least three times higher than the
+ * chosen baud rate. In LF, max input clock is 32768 (LFXO or LFRCO),
+ * thus 32768 / 3 ~ 9600 baudrate.
+ ******************************************************************************/
+void EUSART_UartInitLf(EUSART_TypeDef *eusart, const EUSART_UartInit_TypeDef *init)
+{
+ // Make sure the module exists and is Low frequency capable.
+ EFM_ASSERT(EUSART_REF_VALID(eusart) && EUSART_EM2_CAPABLE(EUSART_NUM(eusart)));
+ // Init structure must be provided.
+ EFM_ASSERT(init);
+
+ // Assert features specific to LF.
+ // LFXO, LFRCO, ULFRCO can be a clock source in LF.
+#if defined(DEBUG_EFM) || defined(DEBUG_EFM_USER)
+ {
+ CMU_Select_TypeDef clock_source = (CMU_Select_TypeDef) NULL;
+#if defined(EUART_PRESENT)
+ if (eusart == EUART0) {
+ clock_source = CMU_ClockSelectGet(cmuClock_EUART0);
+ }
+#endif
+#if defined(EUSART_PRESENT) && defined(EUSART0)
+ if (eusart == EUSART0) {
+ clock_source = CMU_ClockSelectGet(cmuClock_EUSART0);
+ }
+#endif
+ EFM_ASSERT((clock_source == cmuSelect_LFRCO) || (clock_source == cmuSelect_ULFRCO) || (clock_source == cmuSelect_LFXO));
+ }
+#endif
+ // Uart mode only supports up to 9 databits frame.
+ EFM_ASSERT(init->databits <= eusartDataBits9);
+ // The oversampling must be disabled when using a low frequency clock.
+ EFM_ASSERT(init->oversampling == eusartOVS0);
+ // The Majority Vote must be disabled when using a low frequency clock.
+ EFM_ASSERT(init->majorityVote == eusartMajorityVoteDisable);
+ // Number of stop bits can only be 1 or 2 in LF.
+ EFM_ASSERT((init->stopbits == eusartStopbits1) || (init->stopbits == eusartStopbits2));
+ // In LF, max baudrate is 9600. See Note #1.
+ EFM_ASSERT(init->baudrate <= 9600 && init->baudrate != 0);
+
+ // Initialize EUSART with common features to HF and LF.
+ EUSART_AsyncInitCommon(eusart, init, NULL, NULL);
+}
+
+/***************************************************************************//**
+ * Initializes the EUSART when used in IrDA mode with the high or low
+ * frequency clock.
+ ******************************************************************************/
+void EUSART_IrDAInit(EUSART_TypeDef *eusart,
+ const EUSART_IrDAInit_TypeDef *irdaInit)
+{
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+ // Init structure must be provided.
+ EFM_ASSERT(irdaInit);
+
+ if (irdaInit->irDALowFrequencyEnable) {
+ // Validate the low frequency capability of the EUSART instance.
+ EFM_ASSERT(EUSART_EM2_CAPABLE(EUSART_NUM(eusart)));
+ // The oversampling must be disabled when using a low frequency clock.
+ EFM_ASSERT(irdaInit->init.oversampling == eusartOVS0);
+ // Number of stop bits can only be 1 or 2 in LF.
+ EFM_ASSERT((irdaInit->init.stopbits == eusartStopbits1) || (irdaInit->init.stopbits == eusartStopbits2));
+ // In LF, max baudrate is 9600. See Note #1.
+ EFM_ASSERT(irdaInit->init.baudrate <= 9600);
+ EFM_ASSERT(irdaInit->init.enable == eusartEnableRx || irdaInit->init.enable == eusartDisable);
+ } else {
+ EFM_ASSERT(irdaInit->init.oversampling != eusartOVS0);
+ // In HF, 2.4 kbps <= baudrate <= 1.152 Mbps.
+ EFM_ASSERT(irdaInit->init.baudrate >= 2400 && irdaInit->init.baudrate <= 1152000);
+ }
+
+ // Initialize EUSART with common features to HF and LF.
+ EUSART_AsyncInitCommon(eusart, &irdaInit->init, irdaInit, NULL);
+}
+
+#if defined(EUSART_PRESENT)
+/***************************************************************************//**
+ * Initializes the EUSART when used in SPI mode.
+ ******************************************************************************/
+void EUSART_SpiInit(EUSART_TypeDef *eusart, EUSART_SpiInit_TypeDef const *init)
+{
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+ // Init structure must be provided.
+ EFM_ASSERT(init);
+ if (init->master) {
+ EFM_ASSERT(init->bitRate <= 20000000);
+
+ if (init->advancedSettings) {
+ EFM_ASSERT(!(init->advancedSettings->prsClockEnable));
+ }
+ } else {
+ EFM_ASSERT(init->bitRate <= 10000000);
+
+ if (init->advancedSettings && init->advancedSettings->forceLoad) {
+ // If baud-rate is more than 5MHz, a value of 4 is recommended, any values
+ // smaller than that can be tried out but avoid using 0. If baud-rate is less than 5MHz,
+ // value of 5 is recommended, values higher than 5 can be used but it may make the load
+ // error easy to occur. The recommended values for frequency bands should be sufficient
+ // to work all the time.
+ EFM_ASSERT((init->bitRate >= 5000000 && init->advancedSettings->setupWindow <= 4)
+ || (init->bitRate < 5000000 && init->advancedSettings->setupWindow >= 5));
+ }
+ }
+
+ EUSART_SyncInitCommon(eusart, init);
+}
+
+#if defined(EUSART_DALICFG_DALIEN)
+/***************************************************************************//**
+ * Initializes the EUSART when used in DALI mode with the high or low
+ * frequency clock.
+ *
+ * @note (1) When EUSART oversampling is set to eusartOVS0 (Disable), the peripheral
+ * clock frequency must be at least three times higher than the
+ * chosen baud rate. In LF, max input clock is 32768 (LFXO or LFRCO),
+ * thus 32768 / 3 ~ 9600 baudrate.
+ ******************************************************************************/
+void EUSART_DaliInit(EUSART_TypeDef *eusart,
+ const EUSART_DaliInit_TypeDef *daliInit)
+{
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+ // Init structure must be provided.
+ EFM_ASSERT(daliInit);
+
+ if (daliInit->init.loopbackEnable) {
+ // If LOOPBK in CFG0 is set to 1 in order to do loopback testing for DALI,
+ // then in this case DALIRXENDT should be set to 1 and DALIRXDATABITS should
+ // be set the same as DALITXDATABITS.
+ EFM_ASSERT( (daliInit->TXdatabits >> _EUSART_DALICFG_DALITXDATABITS_SHIFT)
+ == (daliInit->RXdatabits >> _EUSART_DALICFG_DALIRXDATABITS_SHIFT));
+ }
+
+ if (daliInit->daliLowFrequencyEnable) {
+ // Validate the low frequency capability of the EUSART instance.
+ EFM_ASSERT(EUSART_EM2_CAPABLE(EUSART_NUM(eusart)));
+ // The oversampling must be disabled when using a low frequency clock.
+ EFM_ASSERT(daliInit->init.oversampling == eusartOVS0);
+ // In LF, max baudrate is 9600. See Note #1.
+ // but manchester is running at 2x clock 9600 => 4800
+ EFM_ASSERT(daliInit->init.baudrate <= 4800);
+ } else {
+ EFM_ASSERT(daliInit->init.oversampling != eusartOVS0);
+ // In HF, 2.4 kbps <= baudrate <= 1.152 Mbps.
+ // but manchester is running at 2x clock so 2.4 kbps => 1.2 kbps
+ EFM_ASSERT(daliInit->init.baudrate >= 1200 && daliInit->init.baudrate <= 57600);
+ }
+
+ // Initialize EUSART with common features to HF and LF.
+ EUSART_AsyncInitCommon(eusart, &daliInit->init, NULL, daliInit);
+}
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/***************************************************************************//**
+ * Configure the EUSART to its reset state.
+ ******************************************************************************/
+void EUSART_Reset(EUSART_TypeDef *eusart)
+{
+ // 1. Properly disable the module
+ EUSART_Disable(eusart);
+
+#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3) \
+ || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4) \
+ || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
+ // Manual toggling tx_sclk_mst to synchronize handshake
+ // when switching from SPI master to other modes
+ // so module is disabling correctly.
+ uint32_t forcedClkCycle = 4u;
+
+ while (forcedClkCycle--) {
+ eusart->CFG2_SET = _EUSART_CFG2_CLKPHA_MASK;
+ eusart->CFG2_CLR = _EUSART_CFG2_CLKPHA_MASK;
+ }
+#endif
+ // All registers that end with CFG should be programmed before EUSART gets enabled (EUSARTn_EN is set).
+ // Set all configurable register to its reset value.
+ // Note: Program desired settings to all registers that have names ending with CFG in the following sequence:
+ // a. CFG2
+#if defined(EUSART_PRESENT)
+ eusart->CFG2 = _EUSART_CFG2_RESETVALUE;
+#endif
+ // b. CFG1
+ eusart->CFG1 = _EUSART_CFG1_RESETVALUE;
+ // c. CFG0
+ eusart->CFG0 = _EUSART_CFG0_RESETVALUE;
+ // d. FRAMECFG, DTXDATCFG, TIMINGCFG (Any sequence)
+ eusart->FRAMECFG = _EUSART_FRAMECFG_RESETVALUE;
+#if defined(EUSART_PRESENT)
+ eusart->DTXDATCFG = _EUSART_DTXDATCFG_RESETVALUE;
+#if defined(EUSART_DALICFG_DALIEN)
+ eusart->DALICFG = _EUSART_DALICFG_RESETVALUE;
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+ eusart->TIMINGCFG = _EUSART_TIMINGCFG_RESETVALUE;
+ eusart->IRHFCFG = _EUSART_IRHFCFG_RESETVALUE;
+ eusart->IRLFCFG = _EUSART_IRLFCFG_RESETVALUE;
+ eusart->STARTFRAMECFG = _EUSART_STARTFRAMECFG_RESETVALUE;
+ eusart->SIGFRAMECFG = _EUSART_SIGFRAMECFG_RESETVALUE;
+ eusart->TRIGCTRL = _EUSART_TRIGCTRL_RESETVALUE;
+ eusart->IEN = _EUSART_IEN_RESETVALUE;
+ eusart->IF_CLR = _EUSART_IF_MASK;
+
+ // no need to sync while EN=0, multiple writes can be queued up,
+ // and the last one will synchronize once EN=1
+ eusart->CLKDIV = _EUSART_CLKDIV_RESETVALUE;
+}
+
+/***************************************************************************//**
+ * Enables/disables the EUSART receiver and/or transmitter.
+ ******************************************************************************/
+void EUSART_Enable(EUSART_TypeDef *eusart, EUSART_Enable_TypeDef enable)
+{
+ uint32_t tmp = 0;
+
+ // Make sure that the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ if (enable == eusartDisable) {
+ EUSART_Disable(eusart);
+ } else {
+ // Enable peripheral to configure Rx and Tx.
+ eusart->EN_SET = EUSART_EN_EN;
+
+ // Enable or disable Rx and/or Tx
+ tmp = (enable)
+ & (_EUSART_CMD_RXEN_MASK | _EUSART_CMD_TXEN_MASK
+ | _EUSART_CMD_RXDIS_MASK | _EUSART_CMD_TXDIS_MASK);
+
+ eusart_sync(eusart, _EUSART_SYNCBUSY_MASK);
+ eusart->CMD = tmp;
+ eusart_sync(eusart,
+ EUSART_SYNCBUSY_RXEN | EUSART_SYNCBUSY_TXEN
+ | EUSART_SYNCBUSY_RXDIS | EUSART_SYNCBUSY_TXDIS);
+
+ // Wait for the status register to be updated.
+ tmp = 0;
+ if (_EUSART_CMD_RXEN_MASK & enable) {
+ tmp |= EUSART_STATUS_RXENS;
+ }
+ if (_EUSART_CMD_TXEN_MASK & enable) {
+ tmp |= EUSART_STATUS_TXENS;
+ }
+ while ((eusart->STATUS & (_EUSART_STATUS_TXENS_MASK | _EUSART_STATUS_RXENS_MASK)) != tmp) {
+ }
+ }
+}
+
+/***************************************************************************//**
+ * Receives one 8 bit frame, (or part of 9 bit frame).
+ ******************************************************************************/
+uint8_t EUSART_Rx(EUSART_TypeDef *eusart)
+{
+ while (!(eusart->STATUS & EUSART_STATUS_RXFL)) {
+ } // Wait for incoming data.
+
+ return (uint8_t)eusart->RXDATA;
+}
+
+/***************************************************************************//**
+ * Receives one 8-9 bit frame with extended information.
+ ******************************************************************************/
+uint16_t EUSART_RxExt(EUSART_TypeDef *eusart)
+{
+ while (!(eusart->STATUS & EUSART_STATUS_RXFL)) {
+ } // Wait for incoming data.
+
+ return (uint16_t)eusart->RXDATA;
+}
+
+/***************************************************************************//**
+ * Transmits one frame.
+ ******************************************************************************/
+void EUSART_Tx(EUSART_TypeDef *eusart, uint8_t data)
+{
+ // Check that transmit FIFO is not full.
+ while (!(eusart->STATUS & EUSART_STATUS_TXFL)) {
+ }
+
+ eusart->TXDATA = (uint32_t)data;
+}
+
+/***************************************************************************//**
+ * Transmits one 8-9 bit frame with extended control.
+ ******************************************************************************/
+void EUSART_TxExt(EUSART_TypeDef *eusart, uint16_t data)
+{
+ // Check that transmit FIFO is not full.
+ while (!(eusart->STATUS & EUSART_STATUS_TXFL)) {
+ }
+
+ eusart->TXDATA = (uint32_t)data;
+}
+
+#if defined(EUSART_PRESENT)
+/***************************************************************************//**
+ * Transmits one 8-16 bit frame and return received data.
+ ******************************************************************************/
+uint16_t EUSART_Spi_TxRx(EUSART_TypeDef *eusart, uint16_t data)
+{
+ // Check that transmit FIFO is not full.
+ while (!(eusart->STATUS & EUSART_STATUS_TXFL)) {
+ }
+ eusart->TXDATA = (uint32_t)data;
+
+ // Wait for Rx data to be available.
+ while (!(eusart->STATUS & EUSART_STATUS_RXFL)) {
+ }
+ return (uint16_t)eusart->RXDATA;
+}
+
+#if defined(EUSART_DALICFG_DALIEN)
+/***************************************************************************//**
+ * Transmits one frame.
+ ******************************************************************************/
+void EUSART_Dali_Tx(EUSART_TypeDef *eusart, uint32_t data)
+{
+ uint32_t packet;
+
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ // Check that transmit FIFO is not full.
+ while (!(eusart->STATUS & EUSART_STATUS_TXFL)) {
+ }
+
+ for (uint8_t index = 0; index < dali_tx_nb_packets[EUSART_NUM(eusart)]; index++) {
+ // when DALICFG.DALIEN is set to 1, then all 16 bits [15:0] represent data
+ // First write to TXDATA register should contain 16 LSBs of the TX frame.
+ // Transmission will not start after this first write.
+ // Second write to TXDATA register should contain the remaining TX frame bits.
+ // This second write will result in start of transmission.
+ packet = (data >> (index * 16));
+ // To ensure compatibility with future devices, always write bits [31:16] to 0.
+ packet &= 0x0000FFFF;
+ eusart->TXDATA = packet;
+ }
+}
+
+/***************************************************************************//**
+ * Receive one frame.
+ ******************************************************************************/
+uint32_t EUSART_Dali_Rx(EUSART_TypeDef *eusart)
+{
+ uint32_t data = 0;
+
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ while (!(eusart->STATUS & EUSART_STATUS_RXFL)) {
+ } // Wait for incoming data.
+
+ for (uint8_t index = 0; index < dali_rx_nb_packets[EUSART_NUM(eusart)]; index++) {
+ // when DALICFG.DALIEN is set to 1, then all 16 bits [15:0] represent data
+ // When receiving a frame that has more than 16 databits,
+ // RXDATA register needs to be read twice:
+ // First read will provide 16 LSBs of the received frame.
+ // Second read will provide the remaining RX frame bits.
+ data |= ((eusart->RXDATA & _EUSART_RXDATA_RXDATA_MASK) << (index * 16));
+ }
+ return data;
+}
+
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/***************************************************************************//**
+ * Configures the baudrate (or as close as possible to a specified baudrate)
+ * depending on the current mode of the EU(S)ART peripheral.
+ *
+ * @note (1) When the oversampling is disabled, the peripheral clock frequency
+ * must be at least three times higher than the chosen baud rate.
+ ******************************************************************************/
+void EUSART_BaudrateSet(EUSART_TypeDef *eusart,
+ uint32_t refFreq,
+ uint32_t baudrate)
+{
+ uint32_t clkdiv;
+ uint8_t oversample = 0;
+
+ // Prevent dividing by 0.
+ EFM_ASSERT(baudrate);
+
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ // Get the current frequency.
+ if (!refFreq) {
+ refFreq = CMU_ClockFreqGet(EUSART_ClockGet(eusart));
+ }
+
+#if defined(EUSART_PRESENT)
+ // In synchronous mode (ex: SPI)
+ if (eusart->CFG0 & _EUSART_CFG0_SYNC_MASK ) {
+ EFM_ASSERT(baudrate <= refFreq);
+
+ EUSART_Enable_TypeDef txrxEnStatus = eusartDisable;
+ bool wasEnabled = (eusart->EN & _EUSART_EN_EN_MASK) == true;
+ clkdiv = refFreq / baudrate - 1UL;
+
+ // If the desired bit rate requires a divider larger than the Synchronous divider bitfield (CFG2_SDIV),
+ // the resulting spi master bus clock will be undefined because the result will be truncated.
+ EFM_ASSERT(clkdiv <= (_EUSART_CFG2_SDIV_MASK >> _EUSART_CFG2_SDIV_SHIFT));
+
+ if (wasEnabled) {
+ eusart_sync(eusart, _EUSART_SYNCBUSY_RXEN_MASK | _EUSART_SYNCBUSY_TXEN_MASK);
+
+ // Save the state of the reveiver and transmitter before disabling the peripheral.
+ if (eusart->STATUS & (_EUSART_STATUS_RXENS_MASK | _EUSART_STATUS_TXENS_MASK)) {
+ txrxEnStatus = eusartEnable;
+ } else if (eusart->STATUS & (_EUSART_STATUS_RXENS_MASK)) {
+ txrxEnStatus = eusartEnableRx;
+ } else if (eusart->STATUS & (_EUSART_STATUS_TXENS_MASK)) {
+ txrxEnStatus = eusartEnableTx;
+ } else {
+ EFM_ASSERT(false);
+ }
+
+ // Disable the eusart to be able to modify the CFG2 register.
+ EUSART_Disable(eusart);
+ }
+
+ // In Synchronous mode the clock divider that is managing the bitRate
+ // is located inside the sdiv bitfield of the CFG2 register instead of
+ // the CLKDIV register combined with the oversample setting for asynchronous mode.
+ eusart->CFG2 = (eusart->CFG2 & ~(_EUSART_CFG2_SDIV_MASK)) | ((clkdiv << _EUSART_CFG2_SDIV_SHIFT) & _EUSART_CFG2_SDIV_MASK);
+
+ if (wasEnabled) {
+ EUSART_Enable(eusart, txrxEnStatus);
+ }
+ } else // In asynchronous mode (ex: UART)
+#endif
+ {
+ // The peripheral must be enabled to configure the baud rate.
+ EFM_ASSERT(eusart->EN == EUSART_EN_EN);
+
+#if defined(EUSART_DALICFG_DALIEN)
+ if (eusart->DALICFG & EUSART_DALICFG_DALIEN) {
+ // adjust for manchester double-clocking scheme
+ baudrate *= 2;
+ }
+#endif
+
+ /*
+ * Use integer division to avoid forcing in float division
+ * utils, and yet keep rounding effect errors to a minimum.
+ *
+ * CLKDIV is given by:
+ *
+ * CLKDIV = 256 * (fUARTn/(oversample * br) - 1)
+ * or
+ * CLKDIV = (256 * fUARTn)/(oversample * br) - 256
+ *
+ * Since fUARTn may be derived from HFCORECLK, consider the overflow when
+ * using integer arithmetic.
+ *
+ * The basic problem with integer division in the above formula is that
+ * the dividend (256 * fUARTn) may become higher than the maximum 32 bit
+ * integer. Yet, the dividend should be evaluated first before dividing
+ * to get as small rounding effects as possible.
+ * Also, harsh restrictions on the maximum fUARTn value should not be made.
+ *
+ * Since the last 3 bits of CLKDIV are don't care, base the
+ * integer arithmetic on the below formula:
+ *
+ * CLKDIV/8 = ((32*fUARTn)/(br * Oversample)) - 32
+ *
+ * and calculate 1/8 of CLKDIV first. This allows for fUARTn
+ * up to 128 MHz without overflowing a 32 bit value.
+ */
+
+ // Map oversampling.
+ switch (eusart->CFG0 & _EUSART_CFG0_OVS_MASK) {
+ case eusartOVS16:
+ EFM_ASSERT(baudrate <= (refFreq / 16));
+ oversample = 16;
+ break;
+
+ case eusartOVS8:
+ EFM_ASSERT(baudrate <= (refFreq / 8));
+ oversample = 8;
+ break;
+
+ case eusartOVS6:
+ EFM_ASSERT(baudrate <= (refFreq / 6));
+ oversample = 6;
+ break;
+
+ case eusartOVS4:
+ EFM_ASSERT(baudrate <= (refFreq / 4));
+ oversample = 4;
+ break;
+
+ case eusartOVS0:
+ EFM_ASSERT(refFreq >= (3 * baudrate)); // See Note #1.
+ oversample = 1;
+ break;
+
+ default:
+ // Invalid input
+ EFM_ASSERT(0);
+ break;
+ }
+
+ if (oversample > 0U) {
+ // Calculate and set the CLKDIV with fractional bits.
+ clkdiv = (32 * refFreq) / (baudrate * oversample);
+ clkdiv -= 32;
+ clkdiv *= 8;
+
+ // Verify that the resulting clock divider is within limits.
+ EFM_ASSERT(clkdiv <= _EUSART_CLKDIV_MASK);
+
+ // If the EFM_ASSERT is not enabled, make sure not to write to reserved bits.
+ clkdiv &= _EUSART_CLKDIV_MASK;
+
+ eusart_sync(eusart, _EUSART_SYNCBUSY_DIV_MASK);
+ eusart->CLKDIV = clkdiv;
+ eusart_sync(eusart, _EUSART_SYNCBUSY_DIV_MASK);
+ }
+ }
+}
+
+/***************************************************************************//**
+ * Gets the current baudrate.
+ ******************************************************************************/
+uint32_t EUSART_BaudrateGet(EUSART_TypeDef *eusart)
+{
+ uint32_t freq;
+ uint32_t div = 1;
+ uint32_t br = 0;
+ EUSART_OVS_TypeDef ovs = eusartOVS0;
+
+ // Make sure the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ freq = CMU_ClockFreqGet(EUSART_ClockGet(eusart));
+
+#if defined(EUSART_PRESENT)
+ // In synchronous mode (ex: SPI)
+ if (eusart->CFG0 & _EUSART_CFG0_SYNC_MASK) {
+ div = (eusart->CFG2 & _EUSART_CFG2_SDIV_MASK) >> _EUSART_CFG2_SDIV_SHIFT;
+ br = freq / (div + 1);
+ }
+ // In asynchronous mode (ex: UART)
+ else
+#endif
+ {
+ div = eusart->CLKDIV;
+ ovs = (EUSART_OVS_TypeDef)(eusart->CFG0 & _EUSART_CFG0_OVS_MASK);
+ br = EUSART_AsyncBaudrateCalc(freq, div, ovs);
+
+#if defined(EUSART_DALICFG_DALIEN)
+ if (eusart->DALICFG & EUSART_DALICFG_DALIEN) {
+ // adjust for manchester double-clocking scheme
+ br /= 2;
+ }
+#endif
+ }
+
+ return br;
+}
+
+/***************************************************************************//**
+ * Enable/Disable reception operations until the configured start frame is
+ * received.
+ ******************************************************************************/
+void EUSART_RxBlock(EUSART_TypeDef *eusart, EUSART_BlockRx_TypeDef enable)
+{
+ uint32_t tmp;
+
+ // Make sure that the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ tmp = ((uint32_t)(enable));
+ tmp &= (_EUSART_CMD_RXBLOCKEN_MASK | _EUSART_CMD_RXBLOCKDIS_MASK);
+
+ eusart_sync(eusart, EUSART_SYNCBUSY_RXBLOCKEN | EUSART_SYNCBUSY_RXBLOCKDIS);
+ eusart->CMD_SET = tmp;
+ eusart_sync(eusart, EUSART_SYNCBUSY_RXBLOCKEN | EUSART_SYNCBUSY_RXBLOCKDIS);
+
+ tmp = 0u;
+ if ((_EUSART_CMD_RXBLOCKEN_MASK & enable) != 0u) {
+ tmp |= EUSART_STATUS_RXBLOCK;
+ }
+ while ((eusart->STATUS & _EUSART_STATUS_RXBLOCK_MASK) != tmp) {
+ } // Wait for the status register to be updated.
+}
+
+/***************************************************************************//**
+ * Enables/Disables the tristating of the transmitter output.
+ ******************************************************************************/
+void EUSART_TxTristateSet(EUSART_TypeDef *eusart,
+ EUSART_TristateTx_TypeDef enable)
+{
+ uint32_t tmp;
+
+ // Make sure that the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ tmp = ((uint32_t)(enable));
+ tmp &= (_EUSART_CMD_TXTRIEN_MASK | _EUSART_CMD_TXTRIDIS_MASK);
+
+ eusart_sync(eusart, EUSART_SYNCBUSY_TXTRIEN | EUSART_SYNCBUSY_TXTRIDIS);
+ eusart->CMD = tmp;
+ eusart_sync(eusart, EUSART_SYNCBUSY_TXTRIEN | EUSART_SYNCBUSY_TXTRIDIS);
+
+ tmp = 0u;
+ if ((_EUSART_CMD_TXTRIEN_MASK & enable) != 0u) {
+ tmp |= EUSART_STATUS_TXTRI;
+ }
+ while ((eusart->STATUS & _EUSART_STATUS_TXTRI_MASK) != tmp) {
+ } // Wait for the status register to be updated.
+}
+
+/***************************************************************************//**
+ * Initializes the automatic enabling of transmissions and/or reception using
+ * the PRS as a trigger.
+ ******************************************************************************/
+void EUSART_PrsTriggerEnable(EUSART_TypeDef *eusart,
+ const EUSART_PrsTriggerInit_TypeDef *init)
+{
+ uint32_t tmp;
+
+ // Make sure that the module exists on the selected chip.
+ EFM_ASSERT(EUSART_REF_VALID(eusart));
+
+ // The peripheral must be enabled to configure the PRS trigger.
+ EFM_ASSERT(eusart->EN == EUSART_EN_EN);
+
+#if defined(EUART_PRESENT)
+ PRS->CONSUMER_EUART0_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUART0_TRIGGER_MASK);
+#else
+
+#if defined(EUSART0)
+ if (eusart == EUSART0) {
+ PRS->CONSUMER_EUSART0_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUSART0_TRIGGER_MASK);
+ }
+#endif
+#if defined(EUSART1)
+ if (eusart == EUSART1) {
+ PRS->CONSUMER_EUSART1_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUSART1_TRIGGER_MASK);
+ }
+#endif
+#if defined(EUSART2)
+ if (eusart == EUSART2) {
+ PRS->CONSUMER_EUSART2_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUSART2_TRIGGER_MASK);
+ }
+#endif
+#if defined(EUSART3)
+ if (eusart == EUSART3) {
+ PRS->CONSUMER_EUSART3_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUSART3_TRIGGER_MASK);
+ }
+#endif
+#if defined(EUSART4)
+ if (eusart == EUSART4) {
+ PRS->CONSUMER_EUSART4_TRIGGER = (init->prs_trigger_channel & _PRS_CONSUMER_EUSART4_TRIGGER_MASK);
+ }
+#endif
+#endif
+
+ tmp = ((uint32_t)(init->prs_trigger_enable));
+ tmp &= (_EUSART_TRIGCTRL_RXTEN_MASK | _EUSART_TRIGCTRL_TXTEN_MASK);
+
+ eusart->TRIGCTRL_SET = tmp;
+ eusart_sync(eusart, EUSART_SYNCBUSY_RXTEN | EUSART_SYNCBUSY_TXTEN);
+
+ tmp = ~((uint32_t)(init->prs_trigger_enable));
+ tmp &= (_EUSART_TRIGCTRL_RXTEN_MASK | _EUSART_TRIGCTRL_TXTEN_MASK);
+ eusart->TRIGCTRL_CLR = tmp;
+ eusart_sync(eusart, EUSART_SYNCBUSY_RXTEN | EUSART_SYNCBUSY_TXTEN);
+}
+
+/*******************************************************************************
+ ************************** LOCAL FUNCTIONS ********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * Gets the clock associated to the specified EUSART instance.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @return Clock corresponding to the eusart.
+ ******************************************************************************/
+static CMU_Clock_TypeDef EUSART_ClockGet(EUSART_TypeDef *eusart)
+{
+ CMU_Clock_TypeDef clock;
+
+#if defined(EUART0)
+ if (eusart == EUART0) {
+ clock = cmuClock_EUART0;
+ }
+#endif
+#if defined(EUSART0)
+ if (eusart == EUSART0) {
+ clock = cmuClock_EUSART0;
+ }
+#endif
+#if defined(EUSART1)
+ else if (eusart == EUSART1) {
+ clock = cmuClock_EUSART1;
+ }
+#endif
+#if defined(EUSART2)
+ else if (eusart == EUSART2) {
+ clock = cmuClock_EUSART2;
+ }
+#endif
+#if defined(EUSART3)
+ else if (eusart == EUSART3) {
+ clock = cmuClock_EUSART3;
+ }
+#endif
+#if defined(EUSART4)
+ else if (eusart == EUSART4) {
+ clock = cmuClock_EUSART4;
+ }
+#endif
+ else {
+ EFM_ASSERT(0);
+ return (CMU_Clock_TypeDef)0u;
+ }
+ return clock;
+}
+
+/***************************************************************************//**
+ * Initializes the EUSART with asynchronous common settings to high
+ * and low frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init A pointer to the initialization structure.
+ * @param irdaInit Pointer to IrDA initialization structure.
+ ******************************************************************************/
+static void EUSART_AsyncInitCommon(EUSART_TypeDef *eusart,
+ const EUSART_UartInit_TypeDef *init,
+ const EUSART_IrDAInit_TypeDef *irdaInit,
+ const EUSART_DaliInit_TypeDef *daliInit)
+{
+ // LF register about to be modified requires sync busy check.
+ if (eusart->EN) {
+ eusart_sync(eusart, _EUSART_SYNCBUSY_MASK);
+ }
+ // Initialize EUSART registers to hardware reset state.
+ EUSART_Reset(eusart);
+
+ // Configure frame format
+ eusart->FRAMECFG = (eusart->FRAMECFG & ~(_EUSART_FRAMECFG_DATABITS_MASK
+ | _EUSART_FRAMECFG_STOPBITS_MASK
+ | _EUSART_FRAMECFG_PARITY_MASK))
+ | (uint32_t)(init->databits)
+ | (uint32_t)(init->parity)
+ | (uint32_t)(init->stopbits);
+
+ // Configure global configuration register 0.
+ eusart->CFG0 = (eusart->CFG0 & ~(_EUSART_CFG0_OVS_MASK
+ | _EUSART_CFG0_LOOPBK_MASK
+ | _EUSART_CFG0_MVDIS_MASK))
+ | (uint32_t)(init->oversampling)
+ | (uint32_t)(init->loopbackEnable)
+ | (uint32_t)(init->majorityVote);
+
+ if (init->baudrate == 0) {
+ eusart->CFG0 |= EUSART_CFG0_AUTOBAUDEN;
+ }
+
+ if (init->advancedSettings) {
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->dmaHaltOnError << _EUSART_CFG0_ERRSDMA_SHIFT;
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->txAutoTristate << _EUSART_CFG0_AUTOTRI_SHIFT;
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->invertIO & (_EUSART_CFG0_RXINV_MASK | _EUSART_CFG0_TXINV_MASK);
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->collisionDetectEnable << _EUSART_CFG0_CCEN_SHIFT;
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->multiProcessorEnable << _EUSART_CFG0_MPM_SHIFT;
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->multiProcessorAddressBitHigh << _EUSART_CFG0_MPAB_SHIFT;
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->msbFirst << _EUSART_CFG0_MSBF_SHIFT;
+
+ // Configure global configuration register 1.
+ eusart->CFG1 = (uint32_t)init->advancedSettings->dmaWakeUpOnRx << _EUSART_CFG1_RXDMAWU_SHIFT
+ | (uint32_t)init->advancedSettings->dmaWakeUpOnTx << _EUSART_CFG1_TXDMAWU_SHIFT;
+
+ if (init->advancedSettings->hwFlowControl == eusartHwFlowControlCts
+ || init->advancedSettings->hwFlowControl == eusartHwFlowControlCtsAndRts) {
+ eusart->CFG1 |= EUSART_CFG1_CTSEN;
+ }
+ // Enable RTS route pin if necessary. CTS is an input so it is enabled by default.
+ if ((init->advancedSettings->hwFlowControl == eusartHwFlowControlRts)
+ || (init->advancedSettings->hwFlowControl == eusartHwFlowControlCtsAndRts)) {
+#if defined(EUART0)
+ GPIO->EUARTROUTE_SET->ROUTEEN = GPIO_EUART_ROUTEEN_RTSPEN;
+#elif defined(EUSART0)
+ GPIO->EUSARTROUTE_SET[EUSART_NUM(eusart)].ROUTEEN = GPIO_EUSART_ROUTEEN_RTSPEN;
+#endif
+ } else {
+#if defined(EUART0)
+ GPIO->EUARTROUTE_CLR->ROUTEEN = GPIO_EUART_ROUTEEN_RTSPEN;
+#elif defined(EUSART0)
+ GPIO->EUSARTROUTE_CLR[EUSART_NUM(eusart)].ROUTEEN = GPIO_EUSART_ROUTEEN_RTSPEN;
+#endif
+ }
+ eusart->STARTFRAMECFG_SET = (uint32_t)init->advancedSettings->startFrame;
+ if (init->advancedSettings->startFrame) {
+ eusart->CFG1 |= EUSART_CFG1_SFUBRX;
+ }
+ if (init->advancedSettings->prsRxEnable) {
+ eusart->CFG1 |= EUSART_CFG1_RXPRSEN;
+ // Configure PRS channel as input data line for EUSART.
+#if defined(EUART_PRESENT)
+ PRS->CONSUMER_EUART0_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUART0_RX_MASK);
+#elif defined(EUSART_PRESENT)
+
+ if (eusart == EUSART0) {
+ PRS->CONSUMER_EUSART0_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART0_RX_MASK);
+ }
+#if defined(EUSART1)
+ if (eusart == EUSART1) {
+ }
+ PRS->CONSUMER_EUSART1_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART1_RX_MASK);
+#endif
+#if defined(EUSART2)
+ if (eusart == EUSART2) {
+ PRS->CONSUMER_EUSART2_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART2_RX_MASK);
+ }
+#endif
+#if defined(EUSART3)
+ if (eusart == EUSART3) {
+ PRS->CONSUMER_EUSART3_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART3_RX_MASK);
+ }
+#endif
+#if defined(EUSART4)
+ if (eusart == EUSART4) {
+ PRS->CONSUMER_EUSART4_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART4_RX_MASK);
+ }
+#endif
+#endif
+ }
+ }
+
+ if (irdaInit) {
+ if (irdaInit->irDALowFrequencyEnable) {
+ eusart->IRLFCFG_SET = (uint32_t)(EUSART_IRLFCFG_IRLFEN);
+ } else {
+ // Configure IrDA HF configuration register.
+ eusart->IRHFCFG_SET = (eusart->IRHFCFG & ~(_EUSART_IRHFCFG_IRHFEN_MASK
+ | _EUSART_IRHFCFG_IRHFEN_MASK
+ | _EUSART_IRHFCFG_IRHFFILT_MASK))
+ | (uint32_t)(EUSART_IRHFCFG_IRHFEN)
+ | (uint32_t)(irdaInit->irDAPulseWidth)
+ | (uint32_t)(irdaInit->irDARxFilterEnable);
+ }
+ }
+
+#if defined(EUSART_DALICFG_DALIEN)
+ // DALI-specific configuration section
+ if (daliInit) {
+ if (init->loopbackEnable) {
+ // If LOOPBK in CFG0 is set to 1 in order to do loopback testing for DALI,
+ // then in this case DALIRXENDT should be set to 1.
+ eusart->DALICFG_SET = EUSART_DALICFG_DALIRXENDT;
+ }
+
+ // keep track of the number of 16-bits packet to send
+ if (daliInit->TXdatabits <= eusartDaliTxDataBits16) {
+ dali_tx_nb_packets[EUSART_NUM(eusart)] = 1;
+ } else {
+ dali_tx_nb_packets[EUSART_NUM(eusart)] = 2;
+ }
+
+ // keep track of the number of 16-bits packet to receive
+ if (daliInit->RXdatabits <= eusartDaliRxDataBits16) {
+ dali_rx_nb_packets[EUSART_NUM(eusart)] = 1;
+ } else {
+ dali_rx_nb_packets[EUSART_NUM(eusart)] = 2;
+ }
+
+ // Configure the numbers of bits per TX and RX frames
+ eusart->DALICFG = (eusart->DALICFG & ~(_EUSART_DALICFG_DALITXDATABITS_MASK
+ | _EUSART_DALICFG_DALIRXDATABITS_MASK))
+ | daliInit->TXdatabits
+ | daliInit->RXdatabits;
+ eusart->DALICFG_SET = EUSART_DALICFG_DALIEN;
+ }
+#else
+ (void)(daliInit);
+#endif /* EUSART_DALICFG_DALIEN */
+
+ // Enable EUSART IP.
+ EUSART_Enable(eusart, eusartEnable);
+
+ // Configure the baudrate if auto baud detection is not used.
+ if (init->baudrate) {
+ EUSART_BaudrateSet(eusart, init->refFreq, init->baudrate);
+ }
+
+ // Finally enable the Rx and/or Tx channel (as specified).
+ EUSART_Enable(eusart, init->enable);
+ while (~EUSART_StatusGet(eusart) & (_EUSART_STATUS_RXIDLE_MASK | _EUSART_STATUS_TXIDLE_MASK)) {
+ }
+}
+
+#if defined(EUSART_PRESENT)
+/***************************************************************************//**
+ * Initializes the EUSART with synchronous common settings to high
+ * and low frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init A pointer to the initialization structure.
+ ******************************************************************************/
+static void EUSART_SyncInitCommon(EUSART_TypeDef *eusart,
+ EUSART_SpiInit_TypeDef const *init)
+{
+ void* advancedSetting_ptr = (void*)init->advancedSettings; // Used to avoid GCC over optimization.
+
+ // LF register about to be modified requires sync busy check.
+ if (eusart->EN) {
+ eusart_sync(eusart, _EUSART_SYNCBUSY_MASK);
+ }
+
+ // Initialize EUSART registers to hardware reset state.
+ EUSART_Reset(eusart);
+
+ // Configure global configuration register 2.
+ eusart->CFG2 = (eusart->CFG2 & ~(_EUSART_CFG2_MASTER_MASK
+ | _EUSART_CFG2_CLKPOL_MASK
+ | _EUSART_CFG2_CLKPHA_MASK
+ | _EUSART_CFG2_FORCELOAD_MASK))
+ | (uint32_t)(init->master)
+ | (uint32_t)(init->clockMode)
+ | (uint32_t)(EUSART_CFG2_FORCELOAD); // Force load feature enabled by default.
+
+ if (advancedSetting_ptr) {
+ // Configure global configuration register 2.
+ eusart->CFG2 = (eusart->CFG2 & ~(_EUSART_CFG2_FORCELOAD_MASK
+ | _EUSART_CFG2_AUTOCS_MASK
+ | _EUSART_CFG2_AUTOTX_MASK
+ | _EUSART_CFG2_CSINV_MASK
+ | _EUSART_CFG2_CLKPRSEN_MASK))
+ | (uint32_t)(init->advancedSettings->forceLoad << _EUSART_CFG2_FORCELOAD_SHIFT)
+ | (uint32_t)(init->advancedSettings->autoCsEnable << _EUSART_CFG2_AUTOCS_SHIFT)
+ | (uint32_t)(init->advancedSettings->autoTxEnable << _EUSART_CFG2_AUTOTX_SHIFT)
+ | (uint32_t)(init->advancedSettings->csPolarity)
+ | (uint32_t)(init->advancedSettings->prsClockEnable << _EUSART_CFG2_CLKPRSEN_SHIFT);
+
+ // Only applicable to EM2 (low frequency) capable EUSART instances.
+ eusart->CFG1 = (eusart->CFG1 & ~(_EUSART_CFG1_RXFIW_MASK
+ | _EUSART_CFG1_TXFIW_MASK))
+ | (uint32_t)(init->advancedSettings->RxFifoWatermark)
+ | (uint32_t)(init->advancedSettings->TxFifoWatermark)
+ | (uint32_t)(init->advancedSettings->dmaWakeUpOnRx << _EUSART_CFG1_RXDMAWU_SHIFT)
+ | (uint32_t)(init->advancedSettings->prsRxEnable << _EUSART_CFG1_RXPRSEN_SHIFT);
+ }
+
+ eusart->CFG0 = (eusart->CFG0 & ~(_EUSART_CFG0_SYNC_MASK
+ | _EUSART_CFG0_LOOPBK_MASK))
+ | (uint32_t)(_EUSART_CFG0_SYNC_SYNC)
+ | (uint32_t)(init->loopbackEnable);
+
+ if (advancedSetting_ptr) {
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->invertIO & (_EUSART_CFG0_RXINV_MASK | _EUSART_CFG0_TXINV_MASK);
+ eusart->CFG0 |= (uint32_t)init->advancedSettings->msbFirst << _EUSART_CFG0_MSBF_SHIFT;
+
+ // Configure global configurationTiming register.
+ eusart->TIMINGCFG = (eusart->TIMINGCFG & ~(_EUSART_TIMINGCFG_CSSETUP_MASK
+ | _EUSART_TIMINGCFG_CSHOLD_MASK
+ | _EUSART_TIMINGCFG_ICS_MASK
+ | _EUSART_TIMINGCFG_SETUPWINDOW_MASK))
+ | ((uint32_t)(init->advancedSettings->autoCsSetupTime << _EUSART_TIMINGCFG_CSSETUP_SHIFT)
+ & _EUSART_TIMINGCFG_CSSETUP_MASK)
+ | ((uint32_t)(init->advancedSettings->autoCsHoldTime << _EUSART_TIMINGCFG_CSHOLD_SHIFT)
+ & _EUSART_TIMINGCFG_CSHOLD_MASK)
+ | ((uint32_t)(init->advancedSettings->autoInterFrameTime << _EUSART_TIMINGCFG_ICS_SHIFT)
+ & _EUSART_TIMINGCFG_ICS_MASK)
+ | ((uint32_t)(init->advancedSettings->setupWindow << _EUSART_TIMINGCFG_SETUPWINDOW_SHIFT)
+ & _EUSART_TIMINGCFG_SETUPWINDOW_MASK)
+ ;
+ }
+
+ // Configure frame format
+ eusart->FRAMECFG = (eusart->FRAMECFG & ~(_EUSART_FRAMECFG_DATABITS_MASK))
+ | (uint32_t)(init->databits);
+
+ if (advancedSetting_ptr) {
+ eusart->DTXDATCFG = (init->advancedSettings->defaultTxData & _EUSART_DTXDATCFG_MASK);
+
+ if (init->advancedSettings->prsRxEnable) {
+ //Configure PRS channel as input data line for EUSART.
+ if (eusart == EUSART0) {
+ PRS->CONSUMER_EUSART0_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART0_RX_MASK);
+ }
+#if defined(EUSART1)
+ if (eusart == EUSART1) {
+ PRS->CONSUMER_EUSART1_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART1_RX_MASK);
+ }
+#endif
+#if defined(EUSART2)
+ if (eusart == EUSART2) {
+ PRS->CONSUMER_EUSART2_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART2_RX_MASK);
+ }
+#endif
+#if defined(EUSART3)
+ if (eusart == EUSART3) {
+ PRS->CONSUMER_EUSART3_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART3_RX_MASK);
+ }
+#endif
+#if defined(EUSART4)
+ if (eusart == EUSART4) {
+ PRS->CONSUMER_EUSART4_RX_SET = (init->advancedSettings->prsRxChannel & _PRS_CONSUMER_EUSART4_RX_MASK);
+ }
+#endif
+ }
+
+ if (init->advancedSettings->prsClockEnable) {
+ //Configure PRS channel as SCLK input for EUSART.
+ if (eusart == EUSART0) {
+ PRS->CONSUMER_EUSART0_CLK_SET = (init->advancedSettings->prsClockChannel & _PRS_CONSUMER_EUSART0_CLK_MASK);
+ }
+#if defined(EUSART1)
+ if (eusart == EUSART1) {
+ PRS->CONSUMER_EUSART1_CLK_SET = (init->advancedSettings->prsClockChannel & _PRS_CONSUMER_EUSART1_CLK_MASK);
+ }
+#endif
+#if defined(EUSART2)
+ if (eusart == EUSART2) {
+ PRS->CONSUMER_EUSART2_CLK_SET = (init->advancedSettings->prsClockChannel & _PRS_CONSUMER_EUSART2_CLK_MASK);
+ }
+#endif
+#if defined(EUSART3)
+ if (eusart == EUSART3) {
+ PRS->CONSUMER_EUSART3_CLK_SET = (init->advancedSettings->prsClockChannel & _PRS_CONSUMER_EUSART3_CLK_MASK);
+ }
+#endif
+#if defined(EUSART4)
+ if (eusart == EUSART4) {
+ PRS->CONSUMER_EUSART4_CLK_SET = (init->advancedSettings->prsClockChannel & _PRS_CONSUMER_EUSART4_CLK_MASK);
+ }
+#endif
+ }
+ }
+
+ // Set baudrate for synchronous operation mode.
+ EUSART_BaudrateSet(eusart, init->refFreq, init->bitRate);
+
+ // Enable EUSART IP.
+ EUSART_Enable(eusart, eusartEnable);
+
+ // Finally enable the Rx and/or Tx channel (as specified).
+ eusart_sync(eusart, _EUSART_SYNCBUSY_RXEN_MASK & _EUSART_SYNCBUSY_TXEN_MASK); // Wait for low frequency register synchronization.
+ eusart->CMD = (uint32_t)init->enable;
+ eusart_sync(eusart, _EUSART_SYNCBUSY_RXEN_MASK & _EUSART_SYNCBUSY_TXEN_MASK);
+ while (~EUSART_StatusGet(eusart) & (_EUSART_STATUS_RXIDLE_MASK | _EUSART_STATUS_TXIDLE_MASK)) {
+ }
+}
+#endif
+
+/***************************************************************************//**
+ * Calculate baudrate for a given reference frequency, clock division,
+ * and oversampling rate when the module is in UART mode.
+ *
+ * @param refFreq The EUSART reference clock frequency in Hz that will be used.
+ * @param clkdiv Clock division factor to be used.
+ * @param ovs Oversampling to be used.
+ *
+ * @return Computed baudrate from given settings.
+ ******************************************************************************/
+__STATIC_INLINE uint32_t EUSART_AsyncBaudrateCalc(uint32_t refFreq,
+ uint32_t clkdiv,
+ EUSART_OVS_TypeDef ovs)
+{
+ uint32_t oversample;
+ uint64_t divisor;
+ uint64_t factor;
+ uint64_t remainder;
+ uint64_t quotient;
+ uint32_t br;
+
+ // Out of bound clkdiv.
+ EFM_ASSERT(clkdiv <= _EUSART_CLKDIV_MASK);
+
+ // Mask out unused bits
+ clkdiv &= _EUSART_CLKDIV_MASK;
+
+ /* Use integer division to avoid forcing in float division
+ * utils and yet keep rounding effect errors to a minimum.
+ *
+ * Baudrate in is given by:
+ *
+ * br = fUARTn/(oversample * (1 + (CLKDIV / 256)))
+ * or
+ * br = (256 * fUARTn)/(oversample * (256 + CLKDIV))
+ *
+ * 256 factor of the dividend is reduced with a
+ * (part of) oversample part of the divisor.
+ */
+
+ switch (ovs) {
+ case eusartOVS16:
+ oversample = 1;
+ factor = 256 / 16;
+ break;
+
+ case eusartOVS8:
+ oversample = 1;
+ factor = 256 / 8;
+ break;
+
+ case eusartOVS6:
+ oversample = 3;
+ factor = 256 / 2;
+ break;
+
+ case eusartOVS4:
+ oversample = 1;
+ factor = 256 / 4;
+ break;
+
+ case eusartOVS0:
+ oversample = 1;
+ factor = 256;
+ break;
+
+ default:
+ return 0u;
+ break;
+ }
+
+ /*
+ * The basic problem with integer division in the above formula is that
+ * the dividend (factor * fUARTn) may become larger than a 32 bit
+ * integer. Yet we want to evaluate the dividend first before dividing
+ * to get as small rounding effects as possible. Too harsh restrictions
+ * should not be made on the maximum fUARTn value either.
+ *
+ * For division a/b,
+ *
+ * a = qb + r
+ *
+ * where q is the quotient and r is the remainder, both integers.
+ *
+ * The original baudrate formula can be rewritten as
+ *
+ * br = xa / b = x(qb + r)/b = xq + xr/b
+ *
+ * where x is 'factor', a is 'refFreq' and b is 'divisor', referring to
+ * variable names.
+ */
+
+ /*
+ * The divisor will never exceed max 32 bit value since
+ * clkdiv <= _EUSART_CLKDIV_MASK (currently 0x7FFFF8)
+ * and 'oversample' has been reduced to <= 3.
+ */
+ divisor = (uint64_t)(oversample * (256 + clkdiv));
+
+ quotient = refFreq / divisor;
+ remainder = refFreq % divisor;
+
+ // The factor <= 128 and since divisor >= 256, the below cannot exceed the maximum
+ // 32 bit value. However, factor * remainder can become larger than 32-bit
+ // because of the size of _EUSART_CLKDIV_DIV_MASK on some families.
+ br = (uint32_t) (factor * quotient);
+
+ /*
+ * The factor <= 128 and remainder < (oversample*(256 + clkdiv)), which
+ * means dividend (factor * remainder) worst case is
+ * 128 * (3 * (256 + _EUSART_CLKDIV_MASK)) = 0xC001_7400.
+ */
+ br += (uint32_t) ((factor * remainder) / divisor);
+
+ return br;
+}
+
+/***************************************************************************//**
+ * Perform EUSART Module disablement - resetting all internal flops/FSM.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_Disable(EUSART_TypeDef *eusart)
+{
+ if (eusart->EN & _EUSART_EN_EN_MASK) {
+ // This step should be skipped especially in Synchronous Slave mode when
+ // external SCLK is not running and CS is active
+#if defined(EUSART_PRESENT)
+ if (!(eusart->CFG0 & _EUSART_CFG0_SYNC_MASK) || (eusart->CFG2 & _EUSART_CFG2_MASTER_MASK))
+#endif
+ {
+ // General Programming Guideline to properly disable the module:
+ // 1a. Disable TX and RX using TXDIS and RXDIS cmd
+ eusart->CMD = EUSART_CMD_TXDIS | EUSART_CMD_RXDIS;
+ // 1b. Poll for EUSARTn_SYNCBUSY.TXDIS and EUSARTn_SYNCBUSY.RXDIS to go low;
+ eusart_sync(eusart, (EUSART_SYNCBUSY_TXDIS | EUSART_SYNCBUSY_RXDIS));
+ // 1c. Wait for EUSARTn_STATUS.TXENS and EUSARTn_STATUS.RXENS to go low
+ while (eusart->STATUS & (_EUSART_STATUS_TXENS_MASK | _EUSART_STATUS_RXENS_MASK)) {
+ }
+ }
+#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
+ eusart->CLKDIV = eusart->CLKDIV;
+ eusart_sync(eusart, _EUSART_SYNCBUSY_DIV_MASK);
+
+ // Read data until FIFO is emptied
+ // but taking care not to underflow the receiver
+ while (eusart->STATUS & EUSART_STATUS_RXFL) {
+ eusart->RXDATA;
+ }
+#endif
+
+ eusart->EN_CLR = EUSART_EN_EN;
+
+#if defined(_EUSART_EN_DISABLING_MASK)
+ // 2. Polling for EUSARTn_EN.DISABLING = 0.
+ while (eusart->EN & _EUSART_EN_DISABLING_MASK) {
+ }
+#endif
+ }
+}
+
+#endif /* defined(EUART_PRESENT) || defined(EUSART_PRESENT) */
diff --git a/mcu/efr/common/vendor/em_eusart.h b/mcu/efr/common/vendor/em_eusart.h
new file mode 100644
index 00000000..afe84d97
--- /dev/null
+++ b/mcu/efr/common/vendor/em_eusart.h
@@ -0,0 +1,1160 @@
+/***************************************************************************//**
+ * @file
+ * @brief Universal asynchronous receiver/transmitter (EUSART) peripheral API
+ *******************************************************************************
+ * # License
+ * Copyright 2019 Silicon Laboratories Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+#ifndef EM_EUSART_H
+#define EM_EUSART_H
+#include "em_device.h"
+#if defined(EUART_PRESENT) || defined(EUSART_PRESENT)
+#include "em_eusart_compat.h"
+#include
+
+/* *INDENT-OFF* */
+// *****************************************************************************
+/// @addtogroup eusart EUSART - Extended USART
+/// @brief Extended Universal Synchronous/Asynchronous Receiver/Transmitter
+///
+/// @li @ref eusart_intro
+/// @li @ref eusart_example
+/// @li @ref eusart_em2
+///
+///@n @section eusart_intro Introduction
+/// This module contains functions to control the Enhanced Universal Synchronous
+/// / Asynchronous Receiver / Transmitter controller(s) (EUSART) peripheral of Silicon
+/// Labs' 32-bit MCUs and SoCs. EUSART can be used as a UART and can,
+/// therefore, be connected to an external transceiver to communicate with
+/// another host using the serial link.
+///
+/// It supports full duplex asynchronous UART communication as well as RS-485,
+/// SPI, MicroWire, and 3-wire. It can also interface with ISO7816 Smart-Cards,
+/// and IrDA devices.
+///
+/// EUSART has a wide selection of operating modes, frame formats, and baud rates.
+/// All features are supported through the API of this module.
+///
+/// This module does not support DMA configuration. UARTDRV and SPIDRV drivers
+/// provide full support for DMA and more.
+///
+///@n @section eusart_example Example
+///
+/// EUSART Async TX example:
+/// @code{.c}
+/// {
+/// EUSART_UartInit_TypeDef init = EUSART_UART_INIT_DEFAULT_HF;
+///
+/// // Configure the clocks.
+/// CMU_ClockSelectSet(cmuClock_EUSART0CLK, cmuSelect_EM01GRPCCLK);
+/// CMU_ClockEnable(cmuClock_EUSART0CLK, true);
+/// // Initialize the EUSART
+/// EUSART_UartInitHf(EUSART0, &init);
+/// EUSART_Tx(EUSART0, data);
+/// }
+///
+/// @endcode
+///
+/// EUSART Sync SPI Transaction example:
+/// @code{.c}
+/// {
+/// EUSART_SpiInit_TypeDef init_master = EUSART_SPI_MASTER_INIT_DEFAULT_HF;
+///
+/// // Configure the clocks.
+/// CMU_ClockSelectSet(cmuClock_EM01GRPCCLK, cmuSelect_HFRCODPLL);
+/// CMU_ClockEnable(cmuClock_EUSART1, true);
+/// CMU_ClockEnable(cmuClock_GPIO, true);
+///
+/// //Configure the SPI ports
+/// GPIO_PinModeSet(sclk_port, sclk_pin, gpioModePushPull, 0);
+/// GPIO_PinModeSet(mosi_port, mosi_pin, gpioModePushPull, 0);
+/// GPIO_PinModeSet(mosi_port, miso_pin, gpioModeInput, 0);
+///
+/// // Connect EUSART to ports
+/// GPIO->EUSARTROUTE[EUSART_NUM(EUSART1)].TXROUTE = (mosi_port << _GPIO_EUSART_TXROUTE_PORT_SHIFT)
+/// | (mosi_pin << _GPIO_EUSART_TXROUTE_PIN_SHIFT);
+/// GPIO->EUSARTROUTE[EUSART_NUM(EUSART1)].RXROUTE = (miso_port << _GPIO_EUSART_RXROUTE_PORT_SHIFT)
+/// | (miso_pin << _GPIO_EUSART_RXROUTE_PIN_SHIFT);
+/// GPIO->EUSARTROUTE[EUSART_NUM(EUSART1)].SCLKROUTE = (sclk_port << _GPIO_EUSART_SCLKROUTE_PORT_SHIFT)
+/// | (sclk_pin << _GPIO_EUSART_SCLKROUTE_PIN_SHIFT);
+/// GPIO->EUSARTROUTE[EUSART_NUM(EUSART1)].ROUTEEN = GPIO_EUSART_ROUTEEN_TXPEN | GPIO_EUSART_ROUTEEN_SCLKPEN;
+///
+/// // Initialize the EUSART
+/// EUSART_SpiInit(EUSART1, &init_master);
+/// EUSART_Spi_TxRx(EUSART1, data);
+/// }
+///
+/// @endcode
+///@n @section eusart_em2 EM2 guidelines for non EM2-Capable instances
+///
+/// @note EUSART instances located in the PD1 power domain are non EM2-capable.
+/// The EUSART_EM2_CAPABLE() and EUSART_NOT_EM2_CAPABLE() macros can be used
+/// to determine whether or not a EUSART instance is EM2-Capable.
+///
+/// Follow theses steps when entering in EM2:
+/// -# Wait for the current transaction to complete with TXCIF interrupt
+/// -# Disable TX and RX using TXDIS and RXDIS cmd
+/// -# Poll for EUSARTn_SYNCBUSY.TXDIS and EUSARTn_SYNCBUSY.RXDIS to go low
+/// -# Wait for EUSARTn_STATUS.TXENS and EUSARTn_STATUS.RXENS to go low
+/// -# Disable SCLKPEN and CSPEN in GPIO if they were previously enabled
+/// -# Enter EM2
+///
+/// On wakeup from EM2, EUSART transmitter/receiver and relevant GPIO
+/// (SCLKPEN and CSPEN) must be re-enabled. For example:
+///
+/// @code{.c}
+/// {
+/// // Enable TX and RX
+/// EUSART_Enable(EUSART0, eusartEnable);
+/// BUS_RegMaskedWrite(&GPIO->EUSARTROUTE[EUSART_NUM(EUSART0)].ROUTEEN,
+/// _GPIO_EUSART_ROUTEEN_TXPEN_MASK | _GPIO_EUSART_ROUTEEN_SCLKPEN_MASK,
+/// GPIO_EUSART_ROUTEEN_TXPEN | GPIO_EUSART_ROUTEEN_SCLKPEN);
+/// }
+/// @endcode
+///
+/// @{
+// *****************************************************************************
+/* *INDENT-ON* */
+
+/*******************************************************************************
+ ******************************** ENUMS ************************************
+ ******************************************************************************/
+
+/// Enable selection.
+typedef enum {
+ /// Disable the peripheral.
+ eusartDisable = 0x0,
+
+ /// Enable receiver only, transmitter disabled.
+ eusartEnableRx = (EUSART_CMD_RXEN | EUSART_CMD_TXDIS),
+
+ /// Enable transmitter only, receiver disabled.
+ eusartEnableTx = (EUSART_CMD_TXEN | EUSART_CMD_RXDIS),
+
+ /// Enable both receiver and transmitter.
+ eusartEnable = (EUSART_CMD_RXEN | EUSART_CMD_TXEN)
+} EUSART_Enable_TypeDef;
+
+/// Data bit selection.
+typedef enum {
+ eusartDataBits7 = EUSART_FRAMECFG_DATABITS_SEVEN, ///< 7 data bits.
+ eusartDataBits8 = EUSART_FRAMECFG_DATABITS_EIGHT, ///< 8 data bits.
+ eusartDataBits9 = EUSART_FRAMECFG_DATABITS_NINE, ///< 9 data bits.
+#if defined(EUSART_PRESENT)
+ eusartDataBits10 = EUSART_FRAMECFG_DATABITS_TEN, ///< 10 data bits, SPI mode only.
+ eusartDataBits11 = EUSART_FRAMECFG_DATABITS_ELEVEN, ///< 11 data bits, SPI mode only.
+ eusartDataBits12 = EUSART_FRAMECFG_DATABITS_TWELVE, ///< 12 data bits, SPI mode only.
+ eusartDataBits13 = EUSART_FRAMECFG_DATABITS_THIRTEEN, ///< 13 data bits, SPI mode only.
+ eusartDataBits14 = EUSART_FRAMECFG_DATABITS_FOURTEEN, ///< 14 data bits, SPI mode only.
+ eusartDataBits15 = EUSART_FRAMECFG_DATABITS_FIFTEEN, ///< 15 data bits, SPI mode only.
+ eusartDataBits16 = EUSART_FRAMECFG_DATABITS_SIXTEEN, ///< 16 data bits, SPI mode only.
+#endif
+} EUSART_Databits_TypeDef;
+
+/// Parity selection.
+typedef enum {
+ eusartNoParity = EUSART_FRAMECFG_PARITY_NONE, ///< No parity.
+ eusartEvenParity = EUSART_FRAMECFG_PARITY_EVEN, ///< Even parity.
+ eusartOddParity = EUSART_FRAMECFG_PARITY_ODD ///< Odd parity.
+} EUSART_Parity_TypeDef;
+
+/// Stop bits selection.
+typedef enum {
+ eusartStopbits0p5 = EUSART_FRAMECFG_STOPBITS_HALF, ///< 0.5 stop bits.
+ eusartStopbits1p5 = EUSART_FRAMECFG_STOPBITS_ONEANDAHALF, ///< 1.5 stop bits.
+ eusartStopbits1 = EUSART_FRAMECFG_STOPBITS_ONE, ///< 1 stop bits.
+ eusartStopbits2 = EUSART_FRAMECFG_STOPBITS_TWO ///< 2 stop bits.
+} EUSART_Stopbits_TypeDef;
+
+/// Oversampling selection, used for asynchronous operation.
+typedef enum {
+ eusartOVS16 = EUSART_CFG0_OVS_X16, ///< 16x oversampling (normal).
+ eusartOVS8 = EUSART_CFG0_OVS_X8, ///< 8x oversampling.
+ eusartOVS6 = EUSART_CFG0_OVS_X6, ///< 6x oversampling.
+ eusartOVS4 = EUSART_CFG0_OVS_X4, ///< 4x oversampling.
+ eusartOVS0 = EUSART_CFG0_OVS_DISABLE ///< Oversampling disabled.
+} EUSART_OVS_TypeDef;
+
+/// HW flow control config.
+typedef enum {
+ eusartHwFlowControlNone = 0, ///< No HW Flow Control.
+ eusartHwFlowControlCts, ///< CTS HW Flow Control.
+ eusartHwFlowControlRts, ///< RTS HW Flow Control.
+ eusartHwFlowControlCtsAndRts ///< CTS and RTS HW Flow Control.
+} EUSART_HwFlowControl_TypeDef;
+
+/// Loopback enable.
+typedef enum {
+ eusartLoopbackEnable = EUSART_CFG0_LOOPBK, ///< Enable loopback.
+ eusartLoopbackDisable = _EUSART_CFG0_RESETVALUE ///< Disable loopback.
+} EUSART_LoopbackEnable_TypeDef;
+
+/// Majority vote enable.
+typedef enum {
+ eusartMajorityVoteEnable = EUSART_CFG0_MVDIS_DEFAULT, ///< Enable majority vote for 16x, 8x and 6x oversampling modes.
+ eusartMajorityVoteDisable = EUSART_CFG0_MVDIS ///< Disable majority vote for 16x, 8x and 6x oversampling modes.
+} EUSART_MajorityVote_TypeDef;
+
+/// Block reception enable.
+typedef enum {
+ eusartBlockRxEnable = EUSART_CMD_RXBLOCKEN, ///< Block reception enable, resulting in all incoming frames being discarded.
+ eusartBlockRxDisable = EUSART_CMD_RXBLOCKDIS ///< Block reception disable, resulting in all incoming frames being loaded into the RX FIFO.
+} EUSART_BlockRx_TypeDef;
+
+/// TX output tristate enable.
+typedef enum {
+ eusartTristateTxEnable = EUSART_CMD_TXTRIEN, ///< Tristates the transmitter output.
+ eusartTristateTxDisable = EUSART_CMD_TXTRIDIS ///< Disables tristating of the transmitter output.
+} EUSART_TristateTx_TypeDef;
+
+/// IrDA filter enable.
+typedef enum {
+ eusartIrDARxFilterEnable = EUSART_IRHFCFG_IRHFFILT_ENABLE, ///< Enable filter on demodulator.
+ eusartIrDARxFilterDisable = EUSART_IRHFCFG_IRHFFILT_DISABLE ///< Disable filter on demodulator.
+} EUSART_IrDARxFilterEnable_TypeDef;
+
+/// Pulse width selection for IrDA mode.
+typedef enum {
+ /// IrDA pulse width is 1/16 for OVS=X16 and 1/8 for OVS=X8
+ eusartIrDAPulseWidthOne = EUSART_IRHFCFG_IRHFPW_ONE,
+
+ /// IrDA pulse width is 2/16 for OVS=X16 and 2/8 for OVS=X8
+ eusartIrDAPulseWidthTwo = EUSART_IRHFCFG_IRHFPW_TWO,
+
+ /// IrDA pulse width is 3/16 for OVS=X16 and 3/8 for OVS=X8
+ eusartIrDAPulseWidthThree = EUSART_IRHFCFG_IRHFPW_THREE,
+
+ /// IrDA pulse width is 4/16 for OVS=X16 and 4/8 for OVS=X8
+ eusartIrDAPulseWidthFour = EUSART_IRHFCFG_IRHFPW_FOUR
+} EUSART_IrDAPulseWidth_Typedef;
+
+/// PRS trigger enable.
+typedef enum {
+ /// Disable trigger on both receiver and transmitter.
+ eusartPrsTriggerDisable = 0x0,
+
+ /// Enable receive trigger only, transmit disabled.
+ eusartPrsTriggerEnableRx = EUSART_TRIGCTRL_RXTEN,
+
+ /// Enable transmit trigger only, receive disabled.
+ eusartPrsTriggerEnableTx = EUSART_TRIGCTRL_TXTEN,
+
+ /// Enable trigger on both receive and transmit.
+ eusartPrsTriggerEnableRxTx = (EUSART_TRIGCTRL_RXTEN | EUSART_TRIGCTRL_TXTEN)
+} EUSART_PrsTriggerEnable_TypeDef;
+
+/// PRS Channel type.
+typedef uint8_t EUSART_PrsChannel_TypeDef;
+
+/// IO polarity selection.
+typedef enum {
+ /// Disable inversion on both RX and TX signals.
+ eusartInvertIODisable = (EUSART_CFG0_RXINV_DISABLE | EUSART_CFG0_TXINV_DISABLE),
+
+ /// Invert RX signal, before receiver.
+ eusartInvertRxEnable = EUSART_CFG0_RXINV_ENABLE,
+
+ /// Invert TX signal, after transmitter.
+ eusartInvertTxEnable = EUSART_CFG0_TXINV_ENABLE,
+
+ /// Enable trigger on both receive and transmit.
+ eusartInvertIOEnable = (EUSART_CFG0_RXINV_ENABLE | EUSART_CFG0_TXINV_ENABLE)
+} EUSART_InvertIO_TypeDef;
+
+#if defined(EUSART_PRESENT)
+/// Clock polarity/phase mode.
+typedef enum {
+ /// Clock idle low, sample on rising edge.
+ eusartClockMode0 = EUSART_CFG2_CLKPOL_IDLELOW | EUSART_CFG2_CLKPHA_SAMPLELEADING,
+
+ /// Clock idle low, sample on falling edge.
+ eusartClockMode1 = EUSART_CFG2_CLKPOL_IDLELOW | EUSART_CFG2_CLKPHA_SAMPLETRAILING,
+
+ /// Clock idle high, sample on falling edge.
+ eusartClockMode2 = EUSART_CFG2_CLKPOL_IDLEHIGH | EUSART_CFG2_CLKPHA_SAMPLELEADING,
+
+ /// Clock idle high, sample on rising edge.
+ eusartClockMode3 = EUSART_CFG2_CLKPOL_IDLEHIGH | EUSART_CFG2_CLKPHA_SAMPLETRAILING
+} EUSART_ClockMode_TypeDef;
+
+/// Chip select polarity.
+typedef enum {
+ /// Chip select active low.
+ eusartCsActiveLow = EUSART_CFG2_CSINV_AL,
+
+ /// Chip select active high.
+ eusartCsActiveHigh = EUSART_CFG2_CSINV_AH,
+} EUSART_CsPolarity_TypeDef;
+
+/// RX FIFO Interrupt ans Status Watermark.
+typedef enum {
+ eusartRxFiFoWatermark1Frame = EUSART_CFG1_RXFIW_ONEFRAME,
+ eusartRxFiFoWatermark2Frame = EUSART_CFG1_RXFIW_TWOFRAMES,
+ eusartRxFiFoWatermark3Frame = EUSART_CFG1_RXFIW_THREEFRAMES,
+ eusartRxFiFoWatermark4Frame = EUSART_CFG1_RXFIW_FOURFRAMES,
+#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 2)
+ eusartRxFiFoWatermark5Frame = EUSART_CFG1_RXFIW_FIVEFRAMES,
+ eusartRxFiFoWatermark6Frame = EUSART_CFG1_RXFIW_SIXFRAMES,
+ eusartRxFiFoWatermark7Frame = EUSART_CFG1_RXFIW_SEVENFRAMES,
+ eusartRxFiFoWatermark8Frame = EUSART_CFG1_RXFIW_EIGHTFRAMES,
+ eusartRxFiFoWatermark9Frame = EUSART_CFG1_RXFIW_NINEFRAMES,
+ eusartRxFiFoWatermark10Frame = EUSART_CFG1_RXFIW_TENFRAMES,
+ eusartRxFiFoWatermark11Frame = EUSART_CFG1_RXFIW_ELEVENFRAMES,
+ eusartRxFiFoWatermark12Frame = EUSART_CFG1_RXFIW_TWELVEFRAMES,
+ eusartRxFiFoWatermark13Frame = EUSART_CFG1_RXFIW_THIRTEENFRAMES,
+ eusartRxFiFoWatermark14Frame = EUSART_CFG1_RXFIW_FOURTEENFRAMES,
+ eusartRxFiFoWatermark15Frame = EUSART_CFG1_RXFIW_FIFTEENFRAMES,
+ eusartRxFiFoWatermark16Frame = EUSART_CFG1_RXFIW_SIXTEENFRAMES
+#endif
+} EUSART_RxFifoWatermark_TypeDef;
+
+/// TX FIFO Interrupt and Status Watermark.
+typedef enum {
+ eusartTxFiFoWatermark1Frame = EUSART_CFG1_TXFIW_ONEFRAME,
+ eusartTxFiFoWatermark2Frame = EUSART_CFG1_TXFIW_TWOFRAMES,
+ eusartTxFiFoWatermark3Frame = EUSART_CFG1_TXFIW_THREEFRAMES,
+ eusartTxFiFoWatermark4Frame = EUSART_CFG1_TXFIW_FOURFRAMES,
+#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 2)
+ eusartTxFiFoWatermark5Frame = EUSART_CFG1_TXFIW_FIVEFRAMES,
+ eusartTxFiFoWatermark6Frame = EUSART_CFG1_TXFIW_SIXFRAMES,
+ eusartTxFiFoWatermark7Frame = EUSART_CFG1_TXFIW_SEVENFRAMES,
+ eusartTxFiFoWatermark8Frame = EUSART_CFG1_TXFIW_EIGHTFRAMES,
+ eusartTxFiFoWatermark9Frame = EUSART_CFG1_TXFIW_NINEFRAMES,
+ eusartTxFiFoWatermark10Frame = EUSART_CFG1_TXFIW_TENFRAMES,
+ eusartTxFiFoWatermark11Frame = EUSART_CFG1_TXFIW_ELEVENFRAMES,
+ eusartTxFiFoWatermark12Frame = EUSART_CFG1_TXFIW_TWELVEFRAMES,
+ eusartTxFiFoWatermark13Frame = EUSART_CFG1_TXFIW_THIRTEENFRAMES,
+ eusartTxFiFoWatermark14Frame = EUSART_CFG1_TXFIW_FOURTEENFRAMES,
+ eusartTxFiFoWatermark15Frame = EUSART_CFG1_TXFIW_FIFTEENFRAMES,
+ eusartTxFiFoWatermark16Frame = EUSART_CFG1_TXFIW_SIXTEENFRAMES
+#endif
+} EUSART_TxFifoWatermark_TypeDef;
+
+#if defined(EUSART_DALICFG_DALIEN)
+/// DALI TX databits (8-32).
+typedef enum {
+ eusartDaliTxDataBits8 = EUSART_DALICFG_DALITXDATABITS_EIGHT, ///< Each frame contains 8 data bits.
+ eusartDaliTxDataBits9 = EUSART_DALICFG_DALITXDATABITS_NINE, ///< Each frame contains 9 data bits.
+ eusartDaliTxDataBits10 = EUSART_DALICFG_DALITXDATABITS_TEN, ///< Each frame contains 10 data bits.
+ eusartDaliTxDataBits11 = EUSART_DALICFG_DALITXDATABITS_ELEVEN, ///< Each frame contains 11 data bits.
+ eusartDaliTxDataBits12 = EUSART_DALICFG_DALITXDATABITS_TWELVE, ///< Each frame contains 12 data bits.
+ eusartDaliTxDataBits13 = EUSART_DALICFG_DALITXDATABITS_THIRTEEN, ///< Each frame contains 13 data bits.
+ eusartDaliTxDataBits14 = EUSART_DALICFG_DALITXDATABITS_FOURTEEN, ///< Each frame contains 14 data bits.
+ eusartDaliTxDataBits15 = EUSART_DALICFG_DALITXDATABITS_FIFTEEN, ///< Each frame contains 15 data bits.
+ eusartDaliTxDataBits16 = EUSART_DALICFG_DALITXDATABITS_SIXTEEN, ///< Each frame contains 16 data bits.
+ eusartDaliTxDataBits17 = EUSART_DALICFG_DALITXDATABITS_SEVENTEEN, ///< Each frame contains 17 data bits.
+ eusartDaliTxDataBits18 = EUSART_DALICFG_DALITXDATABITS_EIGHTEEN, ///< Each frame contains 18 data bits.
+ eusartDaliTxDataBits19 = EUSART_DALICFG_DALITXDATABITS_NINETEEN, ///< Each frame contains 19 data bits.
+ eusartDaliTxDataBits20 = EUSART_DALICFG_DALITXDATABITS_TWENTY, ///< Each frame contains 20 data bits.
+ eusartDaliTxDataBits21 = EUSART_DALICFG_DALITXDATABITS_TWENTYONE, ///< Each frame contains 21 data bits.
+ eusartDaliTxDataBits22 = EUSART_DALICFG_DALITXDATABITS_TWENTYTWO, ///< Each frame contains 22 data bits.
+ eusartDaliTxDataBits23 = EUSART_DALICFG_DALITXDATABITS_TWENTYEIGHT, ///< Each frame contains 23 data bits.
+ eusartDaliTxDataBits24 = EUSART_DALICFG_DALITXDATABITS_TWENTYFOUR, ///< Each frame contains 24 data bits.
+ eusartDaliTxDataBits25 = EUSART_DALICFG_DALITXDATABITS_TWENTYFIVE, ///< Each frame contains 25 data bits.
+ eusartDaliTxDataBits26 = EUSART_DALICFG_DALITXDATABITS_TWENTYSIX, ///< Each frame contains 26 data bits.
+ eusartDaliTxDataBits27 = EUSART_DALICFG_DALITXDATABITS_TWENTYSEVEN, ///< Each frame contains 27 data bits.
+ eusartDaliTxDataBits28 = EUSART_DALICFG_DALITXDATABITS_TWENTYEIGHT, ///< Each frame contains 28 data bits.
+ eusartDaliTxDataBits29 = EUSART_DALICFG_DALITXDATABITS_TWENTYNINE, ///< Each frame contains 29 data bits.
+ eusartDaliTxDataBits30 = EUSART_DALICFG_DALITXDATABITS_THIRTY, ///< Each frame contains 30 data bits.
+ eusartDaliTxDataBits31 = EUSART_DALICFG_DALITXDATABITS_THIRTYONE, ///< Each frame contains 31 data bits.
+ eusartDaliTxDataBits32 = EUSART_DALICFG_DALITXDATABITS_THIRTYTWO, ///< Each frame contains 32 data bits.
+} EUSART_DaliTxDatabits_TypeDef;
+
+/// DALI RX databits (8-32).
+typedef enum {
+ eusartDaliRxDataBits8 = EUSART_DALICFG_DALIRXDATABITS_EIGHT, ///< Each frame contains 8 data bits.
+ eusartDaliRxDataBits9 = EUSART_DALICFG_DALIRXDATABITS_NINE, ///< Each frame contains 9 data bits.
+ eusartDaliRxDataBits10 = EUSART_DALICFG_DALIRXDATABITS_TEN, ///< Each frame contains 10 data bits.
+ eusartDaliRxDataBits11 = EUSART_DALICFG_DALIRXDATABITS_ELEVEN, ///< Each frame contains 11 data bits.
+ eusartDaliRxDataBits12 = EUSART_DALICFG_DALIRXDATABITS_TWELVE, ///< Each frame contains 12 data bits.
+ eusartDaliRxDataBits13 = EUSART_DALICFG_DALIRXDATABITS_THIRTEEN, ///< Each frame contains 13 data bits.
+ eusartDaliRxDataBits14 = EUSART_DALICFG_DALIRXDATABITS_FOURTEEN, ///< Each frame contains 14 data bits.
+ eusartDaliRxDataBits15 = EUSART_DALICFG_DALIRXDATABITS_FIFTEEN, ///< Each frame contains 15 data bits.
+ eusartDaliRxDataBits16 = EUSART_DALICFG_DALIRXDATABITS_SIXTEEN, ///< Each frame contains 16 data bits.
+ eusartDaliRxDataBits17 = EUSART_DALICFG_DALIRXDATABITS_SEVENTEEN, ///< Each frame contains 17 data bits.
+ eusartDaliRxDataBits18 = EUSART_DALICFG_DALIRXDATABITS_EIGHTEEN, ///< Each frame contains 18 data bits.
+ eusartDaliRxDataBits19 = EUSART_DALICFG_DALIRXDATABITS_NINETEEN, ///< Each frame contains 19 data bits.
+ eusartDaliRxDataBits20 = EUSART_DALICFG_DALIRXDATABITS_TWENTY, ///< Each frame contains 20 data bits.
+ eusartDaliRxDataBits21 = EUSART_DALICFG_DALIRXDATABITS_TWENTYONE, ///< Each frame contains 21 data bits.
+ eusartDaliRxDataBits22 = EUSART_DALICFG_DALIRXDATABITS_TWENTYTWO, ///< Each frame contains 22 data bits.
+ eusartDaliRxDataBits23 = EUSART_DALICFG_DALIRXDATABITS_TWENTYEIGHT, ///< Each frame contains 23 data bits.
+ eusartDaliRxDataBits24 = EUSART_DALICFG_DALIRXDATABITS_TWENTYFOUR, ///< Each frame contains 24 data bits.
+ eusartDaliRxDataBits25 = EUSART_DALICFG_DALIRXDATABITS_TWENTYFIVE, ///< Each frame contains 25 data bits.
+ eusartDaliRxDataBits26 = EUSART_DALICFG_DALIRXDATABITS_TWENTYSIX, ///< Each frame contains 26 data bits.
+ eusartDaliRxDataBits27 = EUSART_DALICFG_DALIRXDATABITS_TWENTYSEVEN, ///< Each frame contains 27 data bits.
+ eusartDaliRxDataBits28 = EUSART_DALICFG_DALIRXDATABITS_TWENTYEIGHT, ///< Each frame contains 28 data bits.
+ eusartDaliRxDataBits29 = EUSART_DALICFG_DALIRXDATABITS_TWENTYNINE, ///< Each frame contains 29 data bits.
+ eusartDaliRxDataBits30 = EUSART_DALICFG_DALIRXDATABITS_THIRTY, ///< Each frame contains 30 data bits.
+ eusartDaliRxDataBits31 = EUSART_DALICFG_DALIRXDATABITS_THIRTYONE, ///< Each frame contains 31 data bits.
+ eusartDaliRxDataBits32 = EUSART_DALICFG_DALIRXDATABITS_THIRTYTWO, ///< Each frame contains 32 data bits.
+} EUSART_DaliRxDatabits_TypeDef;
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/*******************************************************************************
+ ******************************* STRUCTS ***********************************
+ ******************************************************************************/
+/// Advanced initialization structure.
+typedef struct {
+ /// Hardware flow control mode.
+ EUSART_HwFlowControl_TypeDef hwFlowControl;
+
+ /// Enable the collision Detection feature.
+ /// Internal (setting loopbackEnable) or external loopback must be done to use this feature.
+ bool collisionDetectEnable;
+
+ /// If true, data will be send with most significant bit first.
+ bool msbFirst;
+
+ /// Enable inversion of RX and/or TX signals.
+ EUSART_InvertIO_TypeDef invertIO;
+
+ /// Enable the automatic wake up from EM2 to EM1 for DMA RX operation.
+ bool dmaWakeUpOnRx;
+
+ /// Enable the automatic wake up from EM2 to EM1 for DMA TX operation.
+ bool dmaWakeUpOnTx;
+
+ /// Enable DMA requests blocking while framing or parity errors.
+ bool dmaHaltOnError;
+
+ /// Start frame that will enable RX operation. 0x00 Disable this feature.
+ uint8_t startFrame;
+
+ /// Enable automatic tristating of transmistter output when there is nothing to transmit.
+ bool txAutoTristate;
+
+ /// Enable EUSART capability to use a PRS channel as an input data line for the receiver.
+ /// The configured RX GPIO signal won't be routed to the EUSART receiver.
+ bool prsRxEnable;
+
+ /// PRS Channel used to transmit data from PRS to the EUSART.
+ EUSART_PrsChannel_TypeDef prsRxChannel;
+
+ /// Enable Multiprocessor mode. Address and data filtering using the 9th bit.
+ bool multiProcessorEnable;
+
+ /// Multiprocessor address bit value. If true, 9th bit of address frame must bit 1, 0 otherwise.
+ bool multiProcessorAddressBitHigh;
+} EUSART_AdvancedInit_TypeDef;
+
+/// Initialization structure.
+typedef struct {
+ /// Specifies whether TX and/or RX will be enabled when initialization completes.
+ EUSART_Enable_TypeDef enable;
+
+ /// EUSART reference clock assumed when configuring baud rate setup. Set
+ /// to 0 if using currently configured reference clock.
+ uint32_t refFreq;
+
+ /// Desired baud rate. If set to 0, Auto Baud feature is enabled and
+ /// the EUSART will wait for (0x55) frame to detect the Baudrate.
+ uint32_t baudrate;
+
+ /// Oversampling used.
+ EUSART_OVS_TypeDef oversampling;
+
+ /// Number of data bits in frame.
+ EUSART_Databits_TypeDef databits;
+
+ /// Parity mode to use.
+ EUSART_Parity_TypeDef parity;
+
+ /// Number of stop bits to use.
+ EUSART_Stopbits_TypeDef stopbits;
+
+ /// Majority Vote can be disabled for 16x, 8x and 6x oversampling modes.
+ EUSART_MajorityVote_TypeDef majorityVote;
+
+ /// Enable Loop Back configuration.
+ EUSART_LoopbackEnable_TypeDef loopbackEnable;
+
+ /// Advanced initialization structure pointer. It can be NULL.
+ EUSART_AdvancedInit_TypeDef *advancedSettings;
+} EUSART_UartInit_TypeDef;
+
+/// IrDA Initialization structure.
+typedef struct {
+ /// General EUSART initialization structure.
+ EUSART_UartInit_TypeDef init;
+
+ /// Enable the IrDA low frequency mode. Only RX operation are enabled.
+ bool irDALowFrequencyEnable;
+
+ /// Set to enable filter on IrDA demodulator.
+ EUSART_IrDARxFilterEnable_TypeDef irDARxFilterEnable;
+
+ /// Configure the pulse width generated by the IrDA modulator as a fraction
+ /// of the configured EUSART bit period.
+ EUSART_IrDAPulseWidth_Typedef irDAPulseWidth;
+} EUSART_IrDAInit_TypeDef;
+
+/// PRS Trigger initialization structure.
+typedef struct {
+ /// PRS to EUSART trigger mode.
+ EUSART_PrsTriggerEnable_TypeDef prs_trigger_enable;
+
+ /// PRS channel to be used to trigger auto transmission.
+ EUSART_PrsChannel_TypeDef prs_trigger_channel;
+} EUSART_PrsTriggerInit_TypeDef;
+
+#if defined(EUSART_PRESENT)
+/// SPI Advanced initialization structure.
+typedef struct {
+ /// Chip select polarity
+ EUSART_CsPolarity_TypeDef csPolarity;
+
+ /// Enable inversion of RX and/or TX signals.
+ EUSART_InvertIO_TypeDef invertIO;
+
+ /// Enable automatic chip select. CS is managed by the peripheral.
+ bool autoCsEnable;
+
+ /// If true, data will be send with most significant bit first.
+ bool msbFirst;
+
+ /// Auto CS setup time (before transmission) in baud cycles. Acceptable value ( 0 to 7 baud cycle).
+ uint8_t autoCsSetupTime;
+
+ /// Auto CS hold time (after transmission) in baud cycles. Acceptable value ( 0 to 7 baud cycle).
+ uint8_t autoCsHoldTime;
+
+ /// Inter-frame time in baud cycles. Acceptable value ( 0 to 7 baud cycle).
+ uint8_t autoInterFrameTime;
+
+ /// Enable AUTOTX mode. Transmits as long as the RX FIFO is not full.
+ /// Generates underflow interrupt if the TX FIFO is empty.
+ bool autoTxEnable;
+
+ /// Default transmitted data when the TXFIFO is empty.
+ uint16_t defaultTxData;
+
+ /// Enable the automatic wake up from EM2 to EM1 for DMA RX operation.
+ /// Only applicable to EM2 (low frequency) capable EUSART instances.
+ bool dmaWakeUpOnRx;
+
+ /// Enable EUSART capability to use a PRS channel as an input data line for the receiver.
+ /// The configured RX GPIO signal won't be routed to the EUSART receiver.
+ bool prsRxEnable;
+
+ /// PRS Channel used to transmit data from PRS to the EUSART.
+ EUSART_PrsChannel_TypeDef prsRxChannel;
+
+ /// Enable EUSART capability to use a PRS channel as an input SPI Clock.
+ /// Slave mode only.
+ bool prsClockEnable;
+
+ /// PRS Channel used to transmit SCLK from PRS to the EUSART.
+ EUSART_PrsChannel_TypeDef prsClockChannel;
+
+ /// Interrupt and status level of the Receive FIFO.
+ EUSART_RxFifoWatermark_TypeDef RxFifoWatermark;
+
+ /// Interrupt and status level of the Receive FIFO.
+ EUSART_TxFifoWatermark_TypeDef TxFifoWatermark;
+
+ /// Force load the first FIFO value.
+ bool forceLoad;
+
+ /// Setup window in bus clock cycles before the sampling edge of SCLK at word-boundary to avoid force load error.
+ uint8_t setupWindow;
+} EUSART_SpiAdvancedInit_TypeDef;
+
+/// SPI Initialization structure.
+typedef struct {
+ /// Specifies whether TX and/or RX will be enabled when initialization completes.
+ EUSART_Enable_TypeDef enable;
+
+ /// EUSART reference clock assumed when configuring baud rate setup. Set
+ /// to 0 if using currently configured reference clock.
+ uint32_t refFreq;
+
+ /// Desired bit rate in Hz.
+ /// Depending on EUSART instance clock, not all bitrates
+ /// are achievable as the divider is limited to 255.
+ uint32_t bitRate;
+
+ /// Number of data bits in frame.
+ EUSART_Databits_TypeDef databits;
+
+ /// Select to operate in master or slave mode.
+ bool master;
+
+ /// Clock polarity/phase mode.
+ EUSART_ClockMode_TypeDef clockMode;
+
+ /// Enable Loop Back configuration.
+ EUSART_LoopbackEnable_TypeDef loopbackEnable;
+
+ /// Advanced initialization structure pointer. It can be NULL.
+ EUSART_SpiAdvancedInit_TypeDef *advancedSettings;
+} EUSART_SpiInit_TypeDef;
+#endif /* EUSART_PRESENT */
+
+/// DALI Initialization structure.
+typedef struct {
+ /// General EUSART initialization structure.
+ EUSART_UartInit_TypeDef init;
+
+ /// Enable the DALI low frequency mode.
+ bool daliLowFrequencyEnable;
+
+#if defined(EUSART_DALICFG_DALIEN)
+ /// Number of TX data bits in frame.
+ EUSART_DaliTxDatabits_TypeDef TXdatabits;
+ /// Number of RX data bits in frame.
+ EUSART_DaliRxDatabits_TypeDef RXdatabits;
+#endif
+} EUSART_DaliInit_TypeDef;
+
+/// Default configuration for EUSART initialization structure in UART mode with high-frequency clock.
+#define EUSART_UART_INIT_DEFAULT_HF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 115200, /* 115200 bits/s. */ \
+ eusartOVS16, /* Oversampling x16. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ eusartNoParity, /* No parity. */ \
+ eusartStopbits1, /* 1 stop bit. */ \
+ eusartMajorityVoteEnable, /* Majority vote enabled. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+/// Default start frame configuration, i.e. feature disabled.
+#define EUSART_DEFAULT_START_FRAME 0x00u
+
+/// Default configuration for EUSART advanced initialization structure.
+#define EUSART_ADVANCED_INIT_DEFAULT \
+ { \
+ eusartHwFlowControlNone, /* Flow control disabled. */ \
+ false, /* Collision detection disabled. */ \
+ false, /* Data is sent with the least significant bit first. */ \
+ eusartInvertIODisable, /* RX and TX signal active high. */ \
+ false, /* No DMA wake up on reception. */ \
+ false, /* No DMA wake up on transmission. */ \
+ false, /* Halt DMA on error disabled. */ \
+ EUSART_DEFAULT_START_FRAME, /* No start frame. */ \
+ false, /* TX auto tristate disabled. */ \
+ false, /* Do not use PRS signal as RX signal.*/ \
+ (EUSART_PrsChannel_TypeDef) 0u, /* EUSART RX connected to prs channel 0. */ \
+ false, /* Multiprocessor mode disabled. */ \
+ false, /* Multiprocessor address bit : 0.*/ \
+ }
+
+/// Default configuration for EUSART initialization structure in UART mode with low-frequency clock.
+#define EUSART_UART_INIT_DEFAULT_LF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 9600, /* 9600 bits/s. */ \
+ eusartOVS0, /* Oversampling disabled. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ eusartNoParity, /* No parity. */ \
+ eusartStopbits1, /* 1 stop bit. */ \
+ eusartMajorityVoteDisable, /* Majority vote enabled. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in IrDA mode with high-frequency clock.
+#define EUSART_IRDA_INIT_DEFAULT_HF \
+ { \
+ EUSART_UART_INIT_DEFAULT_HF, /* Default high frequency configuration. */ \
+ false, /* Disable IrDA low frequency mode. */ \
+ eusartIrDARxFilterDisable, /* RX Filter disabled. */ \
+ eusartIrDAPulseWidthOne, /* Pulse width is set to 1/16. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in IrDA mode with low-frequency clock.
+#define EUSART_IRDA_INIT_DEFAULT_LF \
+ { \
+ { \
+ eusartEnableRx, /* Enable RX when initialization completed (TX not allowed). */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 9600, /* 9600 bits/s. */ \
+ eusartOVS0, /* Oversampling disabled. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ eusartNoParity, /* No parity. */ \
+ eusartStopbits1, /* 1 stop bit. */ \
+ eusartMajorityVoteDisable, /* Majority vote enabled. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }, \
+ true, /* Enable IrDA low frequency mode. */ \
+ eusartIrDARxFilterDisable, /* RX Filter disabled. */ \
+ eusartIrDAPulseWidthOne, /* Pulse width is set to 1. */ \
+ }
+
+#if defined(EUSART_PRESENT)
+/// Default advanced configuration for EUSART initialization structure in SPI mode with high-frequency clock.
+#define EUSART_SPI_ADVANCED_INIT_DEFAULT \
+ { \
+ eusartCsActiveLow, /* CS active low. */ \
+ eusartInvertIODisable, /* RX and TX signal active High. */ \
+ true, /* AutoCS enabled. */ \
+ false, /* Data is sent with the least significant bit first. */ \
+ 0u, /* CS setup time is 0 baud cycles */ \
+ 0u, /* CS hold time is 0 baud cycles */ \
+ 0u, /* Inter-frame time is 0 baud cycles */ \
+ false, /* AutoTX disabled. */ \
+ 0x0000, /* Default transmitted data is 0. */ \
+ false, /* No DMA wake up on reception. */ \
+ false, /* Do not use PRS signal as RX signal. */ \
+ (EUSART_PrsChannel_TypeDef) 0u, /* EUSART RX tied to prs channel 0. */ \
+ false, /* Do not use PRS signal as SCLK signal. */ \
+ (EUSART_PrsChannel_TypeDef) 1u, /* EUSART SCLCK tied to prs channel 1. */ \
+ eusartRxFiFoWatermark1Frame, /* RXFL status/IF set when RX FIFO has at least one frame in it */ \
+ eusartTxFiFoWatermark1Frame, /* TXFL status/IF set when TX FIFO has space for at least one more frame */ \
+ true, /* The first byte sent by the slave won't be the default value if a byte is made available \
+ after chip select is asserted. */ \
+ 0x04u, /* Setup window before the sampling edge of SCLK at word-boundary to avoid force load error. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in SPI master mode with high-frequency clock.
+#define EUSART_SPI_MASTER_INIT_DEFAULT_HF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 10000000, /* 10 Mbits/s. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ true, /* Master mode enabled. */ \
+ eusartClockMode0, /* Clock idle low, sample on rising edge. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in SPI slave mode with high-frequency clock.
+#define EUSART_SPI_SLAVE_INIT_DEFAULT_HF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 10000000, /* 10 Mbits/s. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ false, /* Master mode enabled. */ \
+ eusartClockMode0, /* Clock idle low, sample on rising edge. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+#if defined(EUSART_DALICFG_DALIEN)
+/// Default configuration for EUSART initialization structure in DALI mode with high-frequency clock.
+/// Default configuration for EUSART advanced initialization structure.
+#define EUSART_ADVANCED_DALI_INIT_DEFAULT \
+ { \
+ eusartHwFlowControlNone, /* Flow control disabled. */ \
+ false, /* Collision detection disabled. */ \
+ true, /* Data is sent with the most significant bit first. */ \
+ eusartInvertIODisable, /* RX and TX signal active high. */ \
+ false, /* No DMA wake up on reception. */ \
+ false, /* No DMA wake up on transmission. */ \
+ false, /* Halt DMA on error disabled. */ \
+ EUSART_DEFAULT_START_FRAME, /* No start frame. */ \
+ false, /* TX auto tristate disabled. */ \
+ false, /* Do not use PRS signal as RX signal.*/ \
+ (EUSART_PrsChannel_TypeDef) 0u, /* EUSART RX connected to prs channel 0. */ \
+ false, /* Multiprocessor mode disabled. */ \
+ false, /* Multiprocessor address bit : 0.*/ \
+ }
+
+/// Default configuration for EUSART initialization structure in DALI mode with high-frequency clock.
+#define EUSART_UART_DALI_INIT_DEFAULT_HF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 1200, /* 1200 bits/s. */ \
+ eusartOVS16, /* Oversampling x16. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ eusartNoParity, /* No parity. */ \
+ eusartStopbits1, /* 1 stop bit. */ \
+ eusartMajorityVoteEnable, /* Majority vote enabled. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in DALI mode with low-frequency clock.
+#define EUSART_UART_DALI_INIT_DEFAULT_LF \
+ { \
+ eusartEnable, /* Enable RX/TX when initialization completed. */ \
+ 0, /* Use current configured reference clock for configuring baud rate.*/ \
+ 1200, /* 1200 bits/s. */ \
+ eusartOVS0, /* Oversampling disabled. */ \
+ eusartDataBits8, /* 8 data bits. */ \
+ eusartNoParity, /* No parity. */ \
+ eusartStopbits1, /* 1 stop bit. */ \
+ eusartMajorityVoteDisable, /* Majority vote enabled. */ \
+ eusartLoopbackDisable, /* Loop back disabled. */ \
+ NULL, /* Default advanced settings. */ \
+ }
+
+/// Default configuration for EUSART initialization structure in DALI mode with high-frequency clock.
+#define EUSART_DALI_INIT_DEFAULT_HF \
+ { \
+ EUSART_UART_DALI_INIT_DEFAULT_HF, \
+ false, /* Disable DALI low frequency mode. */ \
+ eusartDaliTxDataBits16, /* TX 16 data bits. */ \
+ eusartDaliRxDataBits8, /* RX 8 data bits. */ \
+ } \
+
+/// Default configuration for EUSART initialization structure in DALI mode with low-frequency clock.
+#define EUSART_DALI_INIT_DEFAULT_LF \
+ { \
+ EUSART_UART_DALI_INIT_DEFAULT_LF, \
+ true, /* Enable DALI low frequency mode. */ \
+ eusartDaliTxDataBits16, /* TX 16 data bits. */ \
+ eusartDaliRxDataBits8, /* RX 8 data bits. */ \
+ } \
+
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/*******************************************************************************
+ ***************************** PROTOTYPES **********************************
+ ******************************************************************************/
+
+/***************************************************************************//**
+ * Initialize EUSART when used in UART mode with the high frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init A pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_UartInitHf(EUSART_TypeDef *eusart, const EUSART_UartInit_TypeDef *init);
+
+/***************************************************************************//**
+ * Initialize EUSART when used in UART mode with the low frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init A pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_UartInitLf(EUSART_TypeDef *eusart, const EUSART_UartInit_TypeDef *init);
+
+/***************************************************************************//**
+ * Initialize EUSART when used in IrDA mode with the high or low
+ * frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param irdaInit A pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_IrDAInit(EUSART_TypeDef *eusart,
+ const EUSART_IrDAInit_TypeDef *irdaInit);
+
+#if defined(EUSART_PRESENT)
+/***************************************************************************//**
+ * Initialize EUSART when used in SPI mode.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init A pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_SpiInit(EUSART_TypeDef *eusart, const EUSART_SpiInit_TypeDef *init);
+
+#if defined(EUSART_DALICFG_DALIEN)
+/***************************************************************************//**
+ * Initialize EUSART when used in DALI mode with the high or low
+ * frequency clock.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param daliInit A pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_DaliInit(EUSART_TypeDef *eusart,
+ const EUSART_DaliInit_TypeDef *daliInit);
+
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/***************************************************************************//**
+ * Configure EUSART to its reset state.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ ******************************************************************************/
+void EUSART_Reset(EUSART_TypeDef *eusart);
+
+/***************************************************************************//**
+ * Enable/disable EUSART receiver and/or transmitter.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param enable Select the status for the receiver and transmitter.
+ ******************************************************************************/
+void EUSART_Enable(EUSART_TypeDef *eusart, EUSART_Enable_TypeDef enable);
+
+/***************************************************************************//**
+ * Receive one 8 bit frame, (or part of 9 bit frame).
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @note This function is normally used to receive one frame when operating with
+ * frame length of 8 bits. See EUSART_RxExt() for reception of 9 bit frames.
+ * Notice that possible parity/stop bits are not considered a part of the
+ * specified frame bit length.
+ * @note This function will stall if buffer is empty until data is received.
+ *
+ * @return Data received.
+ ******************************************************************************/
+uint8_t EUSART_Rx(EUSART_TypeDef *eusart);
+
+/***************************************************************************//**
+ * Receive one 8-16 bit frame with extended information.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @note This function is normally used to receive one frame and additional RX
+ * status information.
+ * @note This function will stall if buffer is empty until data is received.
+ *
+ * @return Data received and receive status.
+ ******************************************************************************/
+uint16_t EUSART_RxExt(EUSART_TypeDef *eusart);
+
+/***************************************************************************//**
+ * Transmit one frame.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param data Data to transmit.
+ *
+ * @note Depending on the frame length configuration, 8 (least significant) bits
+ * from @p data are transmitted. If the frame length is 9, 8 bits are
+ * transmitted from @p data. See EUSART_TxExt() for transmitting 9 bit frame
+ * with full control of all 9 bits.
+ * @note This function will stall if the 4 frame FIFO is full, until the buffer
+ * becomes available.
+ ******************************************************************************/
+void EUSART_Tx(EUSART_TypeDef *eusart, uint8_t data);
+
+/***************************************************************************//**
+ * Transmit one 8-9 bit frame with extended control.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param data Data to transmit.
+ *
+ * @note Possible parity/stop bits in asynchronous mode are not
+ * considered part of a specified frame bit length.
+ * @note This function will stall if buffer is full until the buffer becomes
+ * available.
+ ******************************************************************************/
+void EUSART_TxExt(EUSART_TypeDef *eusart, uint16_t data);
+
+#if defined(EUSART_PRESENT)
+/***************************************************************************//**
+ * Transmit one 8-16 bit frame and return received data.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param data Data to transmit.
+ *
+ * @return Data received and receive status.
+ *
+ * @note SPI master mode only.
+ * @note This function will stall if the TX buffer is full until the buffer becomes
+ * available.
+ ******************************************************************************/
+uint16_t EUSART_Spi_TxRx(EUSART_TypeDef *eusart, uint16_t data);
+
+#if defined(EUSART_DALICFG_DALIEN)
+/***************************************************************************//**
+ * Transmit one DALI frame.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param data Data to transmit.
+ *
+ * @note Depending on the TXdatabits configuration, N (least significant) bits
+ * from @p data are transmitted.
+ * @note This function will stall if the 16 frame FIFO is full, until the buffer
+ * becomes available.
+ ******************************************************************************/
+void EUSART_Dali_Tx(EUSART_TypeDef *eusart, uint32_t data);
+
+/***************************************************************************//**
+ * Receive one 8-32 bit DALI frame.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @note This function is normally used to receive one DALI frame (RXdatabits).
+ * @note This function will stall if the 16 frame FIFO is empty until new
+ * data is received.
+ *
+ * @return Data received. Depending on the RXdatabits configuration, N
+ * (least significant) bits are returned.
+ ******************************************************************************/
+uint32_t EUSART_Dali_Rx(EUSART_TypeDef *eusart);
+#endif /* EUSART_DALICFG_DALIEN */
+#endif /* EUSART_PRESENT */
+
+/***************************************************************************//**
+ * Configure the baudrate (or as close as possible to a specified baudrate).
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param refFreq The EUSART reference clock frequency in Hz that will be used.
+ * If set to 0, the currently configured peripheral clock is
+ * used.
+ * @param baudrate A baudrate to try to achieve.
+ ******************************************************************************/
+void EUSART_BaudrateSet(EUSART_TypeDef *eusart,
+ uint32_t refFreq,
+ uint32_t baudrate);
+
+/***************************************************************************//**
+ * Get the current baudrate.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @return The current baudrate.
+ ******************************************************************************/
+uint32_t EUSART_BaudrateGet(EUSART_TypeDef *eusart);
+
+/***************************************************************************//**
+ * Enable/Disable reception operation until the configured start frame is
+ * received.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param enable Select the receiver blocking status.
+ ******************************************************************************/
+void EUSART_RxBlock(EUSART_TypeDef *eusart,
+ EUSART_BlockRx_TypeDef enable);
+
+/***************************************************************************//**
+ * Enable/Disable the tristating of the transmitter output.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param enable Select the transmitter tristate status.
+ ******************************************************************************/
+void EUSART_TxTristateSet(EUSART_TypeDef *eusart,
+ EUSART_TristateTx_TypeDef enable);
+
+/***************************************************************************//**
+ * Initialize the automatic enabling of transmissions and/or reception using
+ * the PRS as a trigger.
+ * @note
+ * Initialize EUSART with sl_eusart_initHf() or sl_eusart_initLf() before
+ * enabling the PRS trigger.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ * @param init Pointer to the initialization structure.
+ ******************************************************************************/
+void EUSART_PrsTriggerEnable(EUSART_TypeDef *eusart,
+ const EUSART_PrsTriggerInit_TypeDef *init);
+
+/***************************************************************************//**
+ * Get EUSART STATUS register.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @return STATUS register value.
+ ******************************************************************************/
+__STATIC_INLINE uint32_t EUSART_StatusGet(EUSART_TypeDef *eusart)
+{
+ return eusart->STATUS;
+}
+
+/***************************************************************************//**
+ * Clear one or more pending EUSART interrupts.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @param flags Pending EUSART interrupt source to clear. Use a bitwise logic OR
+ * combination of valid interrupt flags for EUSART module
+ * (EUSART_IF_nnn).
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_IntClear(EUSART_TypeDef *eusart, uint32_t flags)
+{
+ eusart->IF_CLR = flags;
+}
+
+/***************************************************************************//**
+ * Disable one or more EUSART interrupts.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @param flags Pending EUSART interrupt source to clear. Use a bitwise logic OR
+ * combination of valid interrupt flags for EUSART module
+ * (EUSART_IF_nnn).
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_IntDisable(EUSART_TypeDef *eusart, uint32_t flags)
+{
+ eusart->IEN_CLR = flags;
+}
+
+/***************************************************************************//**
+ * Enable one or more EUSART interrupts.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @param flags Pending EUSART interrupt source to clear. Use a bitwise logic OR
+ * combination of valid interrupt flags for EUSART module
+ * (EUSART_IF_nnn).
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_IntEnable(EUSART_TypeDef *eusart, uint32_t flags)
+{
+ eusart->IEN_SET = flags;
+}
+
+/***************************************************************************//**
+ * Get pending EUSART interrupt flags.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @return Pending EUSART interrupt sources.
+ ******************************************************************************/
+__STATIC_INLINE uint32_t EUSART_IntGet(EUSART_TypeDef *eusart)
+{
+ return eusart->IF;
+}
+
+/***************************************************************************//**
+ * Get enabled and pending EUSART interrupt flags.
+ * Useful for handling more interrupt sources in the same interrupt handler.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @return Pending and enabled EUSART interrupt sources.
+ ******************************************************************************/
+__STATIC_INLINE uint32_t EUSART_IntGetEnabled(EUSART_TypeDef *eusart)
+{
+ uint32_t tmp;
+
+ /* Store EUSARTx->IEN in temporary variable in order to define explicit order
+ * of volatile accesses. */
+ tmp = eusart->IEN;
+
+ /* Bitwise AND of pending and enabled interrupts */
+ return eusart->IF & tmp;
+}
+
+/***************************************************************************//**
+ * Set one or more pending EUSART interrupts from SW.
+ *
+ * @param eusart Pointer to the EUSART peripheral register block.
+ *
+ * @param flags Interrupt source(s) to set to pending. Use a bitwise logic OR
+ * combination of valid interrupt flags for EUSART module
+ * (EUSART_IF_nnn).
+ ******************************************************************************/
+__STATIC_INLINE void EUSART_IntSet(EUSART_TypeDef *eusart, uint32_t flags)
+{
+ eusart->IF_SET = flags;
+}
+
+/** @} (end addtogroup eusart) */
+#endif /* defined(EUART_PRESENT) || defined(EUSART_PRESENT) */
+#endif /* EM_EUSART_H */
diff --git a/mcu/efr/common/vendor/em_eusart_compat.h b/mcu/efr/common/vendor/em_eusart_compat.h
new file mode 100644
index 00000000..50822e2e
--- /dev/null
+++ b/mcu/efr/common/vendor/em_eusart_compat.h
@@ -0,0 +1,218 @@
+/***************************************************************************//**
+ * @file
+ * @brief EUSART Compatibility Header
+ *******************************************************************************
+ * # License
+ * Copyright 2020 Silicon Laboratories Inc. www.silabs.com
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+#ifndef EM_EUSART_COMPAT_H
+#define EM_EUSART_COMPAT_H
+
+#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
+
+#define EUSART_IF_TXCIF EUSART_IF_TXC
+#define _EUSART_IF_TXCIF_SHIFT _EUSART_IF_TXC_SHIFT
+#define _EUSART_IF_TXCIF_MASK _EUSART_IF_TXC_MASK
+#define _EUSART_IF_TXCIF_DEFAULT _EUSART_IF_TXC_DEFAULT
+#define EUSART_IF_TXCIF_DEFAULT EUSART_IF_TXC_DEFAULT
+
+#define EUSART_IF_TXFLIF EUSART_IF_TXFL
+#define _EUSART_IF_TXFLIF_SHIFT _EUSART_IF_TXFL_SHIFT
+#define _EUSART_IF_TXFLIF_MASK _EUSART_IF_TXFL_MASK
+#define _EUSART_IF_TXFLIF_DEFAULT _EUSART_IF_TXFL_DEFAULT
+#define EUSART_IF_TXFLIF_DEFAULT EUSART_IF_TXFL_DEFAULT
+
+#define EUSART_IF_RXFLIF EUSART_IF_RXFL
+#define _EUSART_IF_RXFLIF_SHIFT _EUSART_IF_RXFL_SHIFT
+#define _EUSART_IF_RXFLIF_MASK _EUSART_IF_RXFL_MASK
+#define _EUSART_IF_RXFLIF_DEFAULT _EUSART_IF_RXFL_DEFAULT
+#define EUSART_IF_RXFLIF_DEFAULT EUSART_IF_RXFL_DEFAULT
+
+#define EUSART_IF_RXFULLIF EUSART_IF_RXFULL
+#define _EUSART_IF_RXFULLIF_SHIFT _EUSART_IF_RXFULL_SHIFT
+#define _EUSART_IF_RXFULLIF_MASK _EUSART_IF_RXFULL_MASK
+#define _EUSART_IF_RXFULLIF_DEFAULT _EUSART_IF_RXFULL_DEFAULT
+#define EUSART_IF_RXFULLIF_DEFAULT EUSART_IF_RXFULL_DEFAULT
+
+#define EUSART_IF_RXOFIF EUSART_IF_RXOF
+#define _EUSART_IF_RXOFIF_SHIFT _EUSART_IF_RXOF_SHIFT
+#define _EUSART_IF_RXOFIF_MASK _EUSART_IF_RXOF_MASK
+#define _EUSART_IF_RXOFIF_DEFAULT _EUSART_IF_RXOF_DEFAULT
+#define EUSART_IF_RXOFIF_DEFAULT EUSART_IF_RXOF_DEFAULT
+
+#define EUSART_IF_RXUFIF EUSART_IF_RXUF
+#define _EUSART_IF_RXUFIF_SHIFT _EUSART_IF_RXUF_SHIFT
+#define _EUSART_IF_RXUFIF_MASK _EUSART_IF_RXUF_MASK
+#define _EUSART_IF_RXUFIF_DEFAULT _EUSART_IF_RXUF_DEFAULT
+#define EUSART_IF_RXUFIF_DEFAULT EUSART_IF_RXUF_DEFAULT
+
+#define EUSART_IF_TXOFIF EUSART_IF_TXOF
+#define _EUSART_IF_TXOFIF_SHIFT _EUSART_IF_TXOF_SHIFT
+#define _EUSART_IF_TXOFIF_MASK _EUSART_IF_TXOF_MASK
+#define _EUSART_IF_TXOFIF_DEFAULT _EUSART_IF_TXOF_DEFAULT
+#define EUSART_IF_TXOFIF_DEFAULT EUSART_IF_TXOF_DEFAULT
+
+#define EUSART_IF_PERRIF EUSART_IF_PERR
+#define _EUSART_IF_PERRIF_SHIFT _EUSART_IF_PERR_SHIFT
+#define _EUSART_IF_PERRIF_MASK _EUSART_IF_PERR_MASK
+#define _EUSART_IF_PERRIF_DEFAULT _EUSART_IF_PERR_DEFAULT
+#define EUSART_IF_PERRIF_DEFAULT EUSART_IF_PERR_DEFAULT
+
+#define EUSART_IF_FERRIF EUSART_IF_FERR
+#define _EUSART_IF_FERRIF_SHIFT _EUSART_IF_FERR_SHIFT
+#define _EUSART_IF_FERRIF_MASK _EUSART_IF_FERR_MASK
+#define _EUSART_IF_FERRIF_DEFAULT _EUSART_IF_FERR_DEFAULT
+#define EUSART_IF_FERRIF_DEFAULT EUSART_IF_FERR_DEFAULT
+
+#define EUSART_IF_MPAFIF EUSART_IF_MPAF
+#define _EUSART_IF_MPAFIF_SHIFT _EUSART_IF_MPAF_SHIFT
+#define _EUSART_IF_MPAFIF_MASK _EUSART_IF_MPAF_MASK
+#define _EUSART_IF_MPAFIF_DEFAULT _EUSART_IF_MPAF_DEFAULT
+#define EUSART_IF_MPAFIF_DEFAULT EUSART_IF_MPAF_DEFAULT
+
+#define EUSART_IF_CCFIF EUSART_IF_CCF
+#define _EUSART_IF_CCFIF_SHIFT _EUSART_IF_CCF_SHIFT
+#define _EUSART_IF_CCFIF_MASK _EUSART_IF_CCF_MASK
+#define _EUSART_IF_CCFIF_DEFAULT _EUSART_IF_CCF_DEFAULT
+#define EUSART_IF_CCFIF_DEFAULT EUSART_IF_CCF_DEFAULT
+
+#define EUSART_IF_TXIDLEIF EUSART_IF_TXIDLE
+#define _EUSART_IF_TXIDLEIF_SHIFT _EUSART_IF_TXIDLE_SHIFT
+#define _EUSART_IF_TXIDLEIF_MASK _EUSART_IF_TXIDLE_MASK
+#define _EUSART_IF_TXIDLEIF_DEFAULT _EUSART_IF_TXIDLE_DEFAULT
+#define EUSART_IF_TXIDLEIF_DEFAULT EUSART_IF_TXIDLE_DEFAULT
+
+#define EUSART_IF_STARTFIF EUSART_IF_STARTF
+#define _EUSART_IF_STARTFIF_SHIFT _EUSART_IF_STARTF_SHIFT
+#define _EUSART_IF_STARTFIF_MASK _EUSART_IF_STARTF_MASK
+#define _EUSART_IF_STARTFIF_DEFAULT _EUSART_IF_STARTF_DEFAULT
+#define EUSART_IF_STARTFIF_DEFAULT EUSART_IF_STARTF_DEFAULT
+
+#define EUSART_IF_SIGFIF EUSART_IF_SIGF
+#define _EUSART_IF_SIGFIF_SHIFT _EUSART_IF_SIGF_SHIFT
+#define _EUSART_IF_SIGFIF_MASK _EUSART_IF_SIGF_MASK
+#define _EUSART_IF_SIGFIF_DEFAULT _EUSART_IF_SIGF_DEFAULT
+#define EUSART_IF_SIGFIF_DEFAULT EUSART_IF_SIGF_DEFAULT
+
+#define EUSART_IF_AUTOBAUDDONEIF EUSART_IF_AUTOBAUDDONE
+#define _EUSART_IF_AUTOBAUDDONEIF_SHIFT _EUSART_IF_AUTOBAUDDONE_SHIFT
+#define _EUSART_IF_AUTOBAUDDONEIF_MASK _EUSART_IF_AUTOBAUDDONE_MASK
+#define _EUSART_IF_AUTOBAUDDONEIF_DEFAULT _EUSART_IF_AUTOBAUDDONE_DEFAULT
+#define EUSART_IF_AUTOBAUDDONEIF_DEFAULT EUSART_IF_AUTOBAUDDONE_DEFAULT
+
+#define EUSART_IEN_TXCIEN EUSART_IEN_TXC
+#define _EUSART_IEN_TXCIEN_SHIFT _EUSART_IEN_TXC_SHIFT
+#define _EUSART_IEN_TXCIEN_MASK _EUSART_IEN_TXC_MASK
+#define _EUSART_IEN_TXCIEN_DEFAULT _EUSART_IEN_TXC_DEFAULT
+#define EUSART_IEN_TXCIEN_DEFAULT EUSART_IEN_TXC_DEFAULT
+
+#define EUSART_IEN_TXFLIEN EUSART_IEN_TXFL
+#define _EUSART_IEN_TXFLIEN_SHIFT _EUSART_IEN_TXFL_SHIFT
+#define _EUSART_IEN_TXFLIEN_MASK _EUSART_IEN_TXFL_MASK
+#define _EUSART_IEN_TXFLIEN_DEFAULT _EUSART_IEN_TXFL_DEFAULT
+#define EUSART_IEN_TXFLIEN_DEFAULT EUSART_IEN_TXFL_DEFAULT
+
+#define EUSART_IEN_RXFLIEN EUSART_IEN_RXFL
+#define _EUSART_IEN_RXFLIEN_SHIFT _EUSART_IEN_RXFL_SHIFT
+#define _EUSART_IEN_RXFLIEN_MASK _EUSART_IEN_RXFL_MASK
+#define _EUSART_IEN_RXFLIEN_DEFAULT _EUSART_IEN_RXFL_DEFAULT
+#define EUSART_IEN_RXFLIEN_DEFAULT EUSART_IEN_RXFL_DEFAULT
+
+#define EUSART_IEN_RXFULLIEN EUSART_IEN_RXFULL
+#define _EUSART_IEN_RXFULLIEN_SHIFT _EUSART_IEN_RXFULL_SHIFT
+#define _EUSART_IEN_RXFULLIEN_MASK _EUSART_IEN_RXFULL_MASK
+#define _EUSART_IEN_RXFULLIEN_DEFAULT _EUSART_IEN_RXFULL_DEFAULT
+#define EUSART_IEN_RXFULLIEN_DEFAULT EUSART_IEN_RXFULL_DEFAULT
+
+#define EUSART_IEN_RXOFIEN EUSART_IEN_RXOF
+#define _EUSART_IEN_RXOFIEN_SHIFT _EUSART_IEN_RXOF_SHIFT
+#define _EUSART_IEN_RXOFIEN_MASK _EUSART_IEN_RXOF_MASK
+#define _EUSART_IEN_RXOFIEN_DEFAULT _EUSART_IEN_RXOF_DEFAULT
+#define EUSART_IEN_RXOFIEN_DEFAULT EUSART_IEN_RXOF_DEFAULT
+
+#define EUSART_IEN_RXUFIEN EUSART_IEN_RXUF
+#define _EUSART_IEN_RXUFIEN_SHIFT _EUSART_IEN_RXUF_SHIFT
+#define _EUSART_IEN_RXUFIEN_MASK _EUSART_IEN_RXUF_MASK
+#define _EUSART_IEN_RXUFIEN_DEFAULT _EUSART_IEN_RXUF_DEFAULT
+#define EUSART_IEN_RXUFIEN_DEFAULT EUSART_IEN_RXUF_DEFAULT
+
+#define EUSART_IEN_TXOFIEN EUSART_IEN_TXOF
+#define _EUSART_IEN_TXOFIEN_SHIFT _EUSART_IEN_TXOF_SHIFT
+#define _EUSART_IEN_TXOFIEN_MASK _EUSART_IEN_TXOF_MASK
+#define _EUSART_IEN_TXOFIEN_DEFAULT _EUSART_IEN_TXOF_DEFAULT
+#define EUSART_IEN_TXOFIEN_DEFAULT EUSART_IEN_TXOF_DEFAULT
+
+#define EUSART_IEN_PERRIEN EUSART_IEN_PERR
+#define _EUSART_IEN_PERRIEN_SHIFT _EUSART_IEN_PERR_SHIFT
+#define _EUSART_IEN_PERRIEN_MASK _EUSART_IEN_PERR_MASK
+#define _EUSART_IEN_PERRIEN_DEFAULT _EUSART_IEN_PERR_DEFAULT
+#define EUSART_IEN_PERRIEN_DEFAULT EUSART_IEN_PERR_DEFAULT
+
+#define EUSART_IEN_FERRIEN EUSART_IEN_FERR
+#define _EUSART_IEN_FERRIEN_SHIFT _EUSART_IEN_FERR_SHIFT
+#define _EUSART_IEN_FERRIEN_MASK _EUSART_IEN_FERR_MASK
+#define _EUSART_IEN_FERRIEN_DEFAULT _EUSART_IEN_FERR_DEFAULT
+#define EUSART_IEN_FERRIEN_DEFAULT EUSART_IEN_FERR_DEFAULT
+
+#define EUSART_IEN_MPAFIEN EUSART_IEN_MPAF
+#define _EUSART_IEN_MPAFIEN_SHIFT _EUSART_IEN_MPAF_SHIFT
+#define _EUSART_IEN_MPAFIEN_MASK _EUSART_IEN_MPAF_MASK
+#define _EUSART_IEN_MPAFIEN_DEFAULT _EUSART_IEN_MPAF_DEFAULT
+#define EUSART_IEN_MPAFIEN_DEFAULT EUSART_IEN_MPAF_DEFAULT
+
+#define EUSART_IEN_CCFIEN EUSART_IEN_CCF
+#define _EUSART_IEN_CCFIEN_SHIFT _EUSART_IEN_CCF_SHIFT
+#define _EUSART_IEN_CCFIEN_MASK _EUSART_IEN_CCF_MASK
+#define _EUSART_IEN_CCFIEN_DEFAULT _EUSART_IEN_CCF_DEFAULT
+#define EUSART_IEN_CCFIEN_DEFAULT EUSART_IEN_CCF_DEFAULT
+
+#define EUSART_IEN_TXIDLEIEN EUSART_IEN_TXIDLE
+#define _EUSART_IEN_TXIDLEIEN_SHIFT _EUSART_IEN_TXIDLE_SHIFT
+#define _EUSART_IEN_TXIDLEIEN_MASK _EUSART_IEN_TXIDLE_MASK
+#define _EUSART_IEN_TXIDLEIEN_DEFAULT _EUSART_IEN_TXIDLE_DEFAULT
+#define EUSART_IEN_TXIDLEIEN_DEFAULT EUSART_IEN_TXIDLE_DEFAULT
+
+#define EUSART_IEN_STARTFIEN EUSART_IEN_STARTF
+#define _EUSART_IEN_STARTFIEN_SHIFT _EUSART_IEN_STARTF_SHIFT
+#define _EUSART_IEN_STARTFIEN_MASK _EUSART_IEN_STARTF_MASK
+#define _EUSART_IEN_STARTFIEN_DEFAULT _EUSART_IEN_STARTF_DEFAULT
+#define EUSART_IEN_STARTFIEN_DEFAULT EUSART_IEN_STARTF_DEFAULT
+
+#define EUSART_IEN_SIGFIEN EUSART_IEN_SIGF
+#define _EUSART_IEN_SIGFIEN_SHIFT _EUSART_IEN_SIGF_SHIFT
+#define _EUSART_IEN_SIGFIEN_MASK _EUSART_IEN_SIGF_MASK
+#define _EUSART_IEN_SIGFIEN_DEFAULT _EUSART_IEN_SIGF_DEFAULT
+#define EUSART_IEN_SIGFIEN_DEFAULT EUSART_IEN_SIGF_DEFAULT
+
+#define EUSART_IEN_AUTOBAUDDONEIEN EUSART_IEN_AUTOBAUDDONE
+#define _EUSART_IEN_AUTOBAUDDONEIEN_SHIFT _EUSART_IEN_AUTOBAUDDONE_SHIFT
+#define _EUSART_IEN_AUTOBAUDDONEIEN_MASK _EUSART_IEN_AUTOBAUDDONE_MASK
+#define _EUSART_IEN_AUTOBAUDDONEIEN_DEFAULT _EUSART_IEN_AUTOBAUDDONE_DEFAULT
+#define EUSART_IEN_AUTOBAUDDONEIEN_DEFAULT EUSART_IEN_AUTOBAUDDONE_DEFAULT
+
+#endif // _SILICON_LABS_32B_SERIES_2_CONFIG_2
+
+#endif
diff --git a/mcu/efr/efr32/config.mk b/mcu/efr/efr32/config.mk
index 1e1ce43c..7c8c98b1 100644
--- a/mcu/efr/efr32/config.mk
+++ b/mcu/efr/efr32/config.mk
@@ -60,7 +60,7 @@ else ifeq ($(MCU)$(MCU_SUB)$(MCU_MEM_VAR),efr32xg22xxxxf512)
HW_MAGIC=0B
HW_VARIANT_ID=0B
endif
- CFLAGS += -DEFR32MG22 -DEFR32MG22C224F512IM32
+ CFLAGS += -DEFR32MG22 -DEFR32MG22C224F512IM40
CFLAGS += -DARM_MATH_ARMV8MML
CFLAGS += -mfloat-abi=hard -mfpu=fpv5-sp-d16
# Mcu instruction set
diff --git a/mcu/efr/efr32/hal/board_usart.h b/mcu/efr/efr32/hal/board_usart.h
index f05fe479..b9807100 100644
--- a/mcu/efr/efr32/hal/board_usart.h
+++ b/mcu/efr/efr32/hal/board_usart.h
@@ -83,9 +83,9 @@
#error USART ID must be 0 or 1
#endif // BOARD_USART_ID
#define BOARD_USART_ROUTE BOARD_USARTROUTE.RXROUTE = BOARD_USART_RX_PIN << _GPIO_USART_RXROUTE_PIN_SHIFT | \
- BOARD_USART_GPIO_PORT << _GPIO_USART_RXROUTE_PORT_SHIFT; \
+ BOARD_USART_RX_PORT << _GPIO_USART_RXROUTE_PORT_SHIFT; \
BOARD_USARTROUTE.TXROUTE = BOARD_USART_TX_PIN << _GPIO_USART_RXROUTE_PIN_SHIFT | \
- BOARD_USART_GPIO_PORT << _GPIO_USART_RXROUTE_PORT_SHIFT
+ BOARD_USART_TX_PORT << _GPIO_USART_RXROUTE_PORT_SHIFT
#define BOARD_USART_PINS BOARD_USARTROUTE.ROUTEEN = GPIO_USART_ROUTEEN_RXPEN | \
GPIO_USART_ROUTEEN_TXPEN
#define BOARD_USART_CLR_IRQ_ALL BOARD_USART->IF_CLR = _USART_IF_MASK
diff --git a/mcu/efr/efr32/hal/button.c b/mcu/efr/efr32/hal/button.c
deleted file mode 100644
index e782edda..00000000
--- a/mcu/efr/efr32/hal/button.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/* Copyright 2019 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file button.c
- * \brief Board-specific button module for efr32
- */
-
-#include "button.h"
-#include "mcu.h"
-#include "board.h"
-#include "api.h"
-
-
-#ifdef BOARD_BUTTON_PIN_LIST
-
-/*
- * The selected board has buttons
- */
-
-#ifndef BOARD_DEBOUNCE_TIME_MS
-/** \brief Debounce time of button in ms. It can be overwritten from board.h */
-#define BOARD_DEBOUNCE_TIME_MS 100
-#endif
-
-#ifndef BOARD_BUTTON_ACTIVE_LOW
-/** \brief Is button active low. It can be overwritten from board.h */
-#define BOARD_BUTTON_ACTIVE_LOW true
-#endif
-
-#ifndef BOARD_BUTTON_INTERNAL_PULL
-/** \brief Does the driver needs to activate internal pull-up/down.
- * If true; pull-up (down) is enabled if BOARD_BUTTON_ACTIVE_LOW is
- * true (false). It can be overwritten from board.h
- */
-#define BOARD_BUTTON_INTERNAL_PULL true
-#endif
-
-#ifndef BOARD_BUTTON_USE_EVEN_INT
-/** \brief Use even (or odd) ext int. It can be overwritten from board.h */
-#define BOARD_BUTTON_USE_EVEN_INT true
-#endif
-
-/** \brief Each button use a GPIOTE channel Define first one */
-#define GPIOTE_START_CHANNEL 0
-
-/** \brief GPIO port and pin number */
-typedef struct
-{
- uint8_t ext_int;
- uint8_t port;
- uint8_t pin;
-} button_gpio_t;
-
-/** \brief Board-dependent Button number to pin mapping */
-static const button_gpio_t m_pin_map[] = BOARD_BUTTON_PIN_LIST;
-
-/** \brief Compute number of buttons on the board */
-#define BOARD_BUTTON_NUMBER (sizeof(m_pin_map) / sizeof(m_pin_map[0]))
-
-typedef struct
-{
- // Callback when button pressed
- on_button_event_cb on_pressed;
- // Callback when button released
- on_button_event_cb on_released;
- // Used for debounce
- app_lib_time_timestamp_hp_t last_button_event;
- // True if button GPIO is active low
- bool active_low;
-} button_internal_t;
-
-/** \brief Table to manage the button list */
-static button_internal_t m_button_conf[BOARD_BUTTON_NUMBER];
-
-static void button_interrupt_handler(void);
-
-static void button_enable_interrupt(uint8_t ext_int,
- uint8_t port,
- uint8_t pin,
- bool enable)
-{
- bool high_reg = ext_int >= 8;
- uint8_t shift = (ext_int & 7) * 4;
- uint32_t mask = ~((uint32_t)0xf << shift);
- uint32_t set = 0;
-
- // Select port
- set = enable ? (uint32_t)port << shift : 0;
- if (high_reg)
- {
-#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- GPIO->EXTIPSELH = (GPIO->EXTIPSELH & mask) | set;
-#endif
- }
- else
- {
- GPIO->EXTIPSELL = (GPIO->EXTIPSELL & mask) | set;
- }
-
- // Select pin
- set = enable ? (uint32_t)(pin & 3) << shift : 0;
- if (high_reg)
- {
-#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- GPIO->EXTIPINSELH = (GPIO->EXTIPINSELH & mask) | set;
-#endif
- }
- else
- {
- GPIO->EXTIPINSELL = (GPIO->EXTIPINSELL & mask) | set;
- }
-
- // Set rising and falling edge sensitivity
- shift = ext_int;
- mask = ~((uint32_t)1 << shift);
- set = enable ? (uint32_t)1 << shift : 0;
- GPIO->EXTIRISE = (GPIO->EXTIRISE & mask) | set;
- GPIO->EXTIFALL = (GPIO->EXTIFALL & mask) | set;
-
- //Clear external interrupt flag
-#if defined(_SILICON_LABS_32B_SERIES_1)
- GPIO->IFC = (uint32_t)1 << shift;
-#else
- GPIO->IF_CLR = (uint32_t)1 << shift;
-#endif
-
- // Enable or disable external interrupt
- GPIO->IEN = (GPIO->IEN & mask) | set;
-}
-
-void Button_init(void)
-{
- // Enable clocks
-#if defined(_SILICON_LABS_32B_SERIES_1)
- CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
-#elif !defined (EFR32MG21)
- CMU->CLKEN0_SET = CMU_CLKEN0_GPIO;
-#endif
-
- // Get current timestamp
- app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
-
- // Configure button GPIOs
- for (uint8_t i = 0; i < BOARD_BUTTON_NUMBER; i++)
- {
- // Set button configuration
- m_button_conf[i].on_pressed = NULL;
- m_button_conf[i].on_released = NULL;
- m_button_conf[i].last_button_event = now;
- m_button_conf[i].active_low = BOARD_BUTTON_ACTIVE_LOW;
-
- // Enable the Pull-Up/Down on Buttons.
- if (BOARD_BUTTON_INTERNAL_PULL)
- {
- // Set pin mode: input enabled with filter, DOUT sets pull dir.
- hal_gpio_set_mode(m_pin_map[i].port,
- m_pin_map[i].pin,
- GPIO_MODE_IN_PP);
-
- if (m_button_conf[i].active_low)
- {
- hal_gpio_set(m_pin_map[i].port, m_pin_map[i].pin);
- }
- else
- {
- hal_gpio_clear(m_pin_map[i].port, m_pin_map[i].pin);
- }
- }
- else
- {
- // Default config: Input No Pull, DOUT enables filter.
- hal_gpio_set_mode(m_pin_map[i].port,
- m_pin_map[i].pin,
- GPIO_MODE_IN_OD_NOPULL);
- hal_gpio_set(m_pin_map[i].port, m_pin_map[i].pin);
- }
- }
-
- // Enable even or odd external interrupts
- lib_system->enableAppIrq(
- false,
- BOARD_BUTTON_USE_EVEN_INT ? GPIO_EVEN_IRQn : GPIO_ODD_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_LO,
- button_interrupt_handler);
-}
-
-button_res_e Button_getState(uint8_t button_id, bool * state_p)
-{
- if (button_id >= BOARD_BUTTON_NUMBER)
- {
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
- }
-
- uint32_t b = hal_gpio_get(m_pin_map[button_id].port,
- m_pin_map[button_id].pin);
-
- if (m_button_conf[button_id].active_low)
- {
- b ^= 0x01;
- }
-
- *state_p = (b != 0);
-
- return BUTTON_RES_OK;
-}
-
-button_res_e Button_register_for_event(uint8_t button_id,
- button_event_e event,
- on_button_event_cb cb)
-{
- if ((button_id >= BOARD_BUTTON_NUMBER)
- || (event != BUTTON_PRESSED && event != BUTTON_RELEASED ))
- {
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
- }
-
- Sys_enterCriticalSection();
-
- if (event == BUTTON_PRESSED)
- {
- m_button_conf[button_id].on_pressed = cb;
- }
- else
- {
- m_button_conf[button_id].on_released = cb;
- }
-
- // Enable interrupt if at least one event registered, disable otherwise
- button_enable_interrupt(m_pin_map[button_id].ext_int,
- m_pin_map[button_id].port,
- m_pin_map[button_id].pin,
- m_button_conf[button_id].on_pressed ||
- m_button_conf[button_id].on_released);
-
- Sys_exitCriticalSection();
-
- return BUTTON_RES_OK;
-}
-
-uint8_t Button_get_number(void)
-{
- return BOARD_BUTTON_NUMBER;
-}
-
-static void button_interrupt_handler(void)
-{
- app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
-
- // Check all possible sources
- for (uint8_t i = 0; i < BOARD_BUTTON_NUMBER; i++)
- {
- // Read external interrupt flag
- if ((GPIO->IF & (((uint32_t)1) << m_pin_map[i].ext_int)) != 0)
- {
- if (lib_time->getTimeDiffUs(now, m_button_conf[i].last_button_event)
- > (BOARD_DEBOUNCE_TIME_MS * 1000))
- {
- // Button is pressed if gpio is in active state
- bool pressed = hal_gpio_get(m_pin_map[i].port,
- m_pin_map[i].pin);
- if (m_button_conf[i].active_low)
- {
- pressed = !pressed;
- }
- m_button_conf[i].last_button_event = now;
-
- if (m_button_conf[i].on_pressed && pressed)
- {
- m_button_conf[i].on_pressed(i, BUTTON_PRESSED);
- }
- else if (m_button_conf[i].on_released && !pressed)
- {
- m_button_conf[i].on_released(i, BUTTON_RELEASED);
- }
- }
-
- // Clear external interrupt flag
-#if defined(_SILICON_LABS_32B_SERIES_1)
- GPIO->IFC = (uint32_t)1 << m_pin_map[i].ext_int;
-#else
- GPIO->IF_CLR = (uint32_t)1 << m_pin_map[i].ext_int;
-#endif
- }
- }
-}
-
-#else // BOARD_BUTTON_PIN_LIST
-
-/*
- * The selected board has no buttons
- *
- * As some example apps support such boards but also provide extra features
- * when a board has buttons, the button driver has this dummy implementation
- * to simplify the build process.
- */
-
-void Button_init(void)
-{
- // Do nothing
-}
-
-button_res_e Button_getState(uint8_t button_id, bool * state_p)
-{
- (void) button_id;
- *state_p = false;
-
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
-}
-
-uint8_t Button_get_number(void)
-{
- return 0;
-}
-
-button_res_e Button_register_for_event(uint8_t button_id,
- button_event_e event,
- on_button_event_cb cb)
-{
- (void) button_id;
- (void) event;
- (void) cb;
-
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
-}
-
-#endif // BOARD_BUTTON_PIN_LIST
diff --git a/mcu/efr/efr32/hal/eusart.c b/mcu/efr/efr32/hal/eusart.c
new file mode 100644
index 00000000..ba5e847a
--- /dev/null
+++ b/mcu/efr/efr32/hal/eusart.c
@@ -0,0 +1,286 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+#include
+#include
+#include
+
+#include "hal_api.h"
+#include "board.h"
+#include "api.h"
+#include "gpio.h"
+#include "em_eusart.h"
+#include "em_cmu.h"
+
+#define BUFFER_SIZE 512u
+#include "ringbuffer.h"
+static volatile ringbuffer_t m_usart_tx_buffer;
+
+static volatile serial_rx_callback_f m_rx_callback;
+static volatile uint32_t m_enabled;
+static volatile bool m_tx_active;
+
+void __attribute__((__interrupt__)) EUSART_RX_IRQHandler(void);
+void __attribute__((__interrupt__)) EUSART_TX_IRQHandler(void);
+
+bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
+{
+ EUSART_UartInit_TypeDef EUSART_init = EUSART_UART_INIT_DEFAULT_HF;
+
+#ifdef BOARD_GPIO_ID_VCOM_ENABLE
+ const gpio_out_cfg_t usart_vcom_enable_cfg =
+ {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH
+ };
+
+ // Enable vcom
+ Gpio_outputSetCfg(BOARD_GPIO_ID_VCOM_ENABLE, &usart_vcom_enable_cfg);
+#endif
+
+ (void)flow_control;
+
+ // Module variables
+ Ringbuffer_reset(m_usart_tx_buffer);
+ m_rx_callback = NULL;
+ m_tx_active = false;
+ m_enabled = 0;
+
+ // Disable for RX
+ Sys_disableAppIrq(EUSART0_RX_IRQn);
+ Sys_clearFastAppIrq(EUSART0_RX_IRQn);
+ // Disable for TX
+ Sys_disableAppIrq(EUSART0_TX_IRQn);
+ Sys_clearFastAppIrq(EUSART0_TX_IRQn);
+
+ CMU_ClockEnable(cmuClock_EUSART0, true);
+
+ // EUSART0 clock is connected to the HFXO (through the EM01GRPCCLK clock group)
+ CMU_ClockSelectSet(cmuClock_EM01GRPCCLK, cmuSelect_HFXO);
+ CMU_ClockSelectSet(cmuClock_EUSART0, cmuSelect_EM01GRPCCLK);
+
+ // EUSART0 is using a high frequency clock (HFXO),
+ // so that it can support high baudrates (e.g. 115200 bauds)
+ EUSART_init.enable = eusartDisable;
+ EUSART_init.baudrate = baudrate;
+ EUSART_init.oversampling = EUSART_CFG0_OVS_X4;
+ EUSART_UartInitHf(EUSART0, &EUSART_init);
+
+ // Set UART TX GPIO
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN);
+ // Set UART RX GPIO
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN);
+
+
+ GPIO->EUSARTROUTE[0].ROUTEEN = GPIO_EUSART_ROUTEEN_TXPEN;
+ GPIO->EUSARTROUTE[0].TXROUTE = (BOARD_USART_TX_PORT << _GPIO_EUSART_TXROUTE_PORT_SHIFT) | (BOARD_USART_TX_PIN << _GPIO_EUSART_TXROUTE_PIN_SHIFT);
+ GPIO->EUSARTROUTE[0].RXROUTE = (BOARD_USART_RX_PORT << _GPIO_EUSART_RXROUTE_PORT_SHIFT) | (BOARD_USART_RX_PIN << _GPIO_EUSART_RXROUTE_PIN_SHIFT);
+
+ EUSART_IntDisable(EUSART0, _EUSART_IF_MASK);
+ EUSART_IntClear(EUSART0, _EUSART_IF_MASK);
+
+ // APP IRQ
+ Sys_clearFastAppIrq(EUSART0_TX_IRQn);
+ Sys_enableFastAppIrq(EUSART0_TX_IRQn,
+ APP_LIB_SYSTEM_IRQ_PRIO_HI,
+ EUSART_TX_IRQHandler);
+
+ EUSART_Enable(EUSART0, eusartEnableTx);
+
+ CMU_ClockEnable(cmuClock_EUSART0, false);
+
+ return true;
+}
+
+void Usart_setEnabled(bool enabled)
+{
+ Sys_enterCriticalSection();
+ if(enabled)
+ {
+ // Detect if someone is enabling UART but not disabling it ever
+ if(m_enabled == 0)
+ {
+ // Enable clock
+ CMU_ClockEnable(cmuClock_EUSART0, true);
+ // Disable deep sleep
+ DS_Disable(DS_SOURCE_USART);
+ // Set output
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN,
+ GPIO_MODE_OUT_PP);
+ }
+ m_enabled++;
+ }
+ else
+ {
+ if (m_enabled > 0)
+ {
+ m_enabled--;
+ }
+ if(m_enabled == 0)
+ {
+ // Set light pullup
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN,
+ GPIO_MODE_IN_PULL);
+ hal_gpio_set(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN);
+ // Enable deep sleep
+ DS_Enable(DS_SOURCE_USART);
+ // Disable clock
+ CMU_ClockEnable(cmuClock_EUSART0, false);
+ }
+ }
+ Sys_exitCriticalSection();
+}
+
+void Usart_receiverOn(void)
+{
+ EUSART_Enable(EUSART0, eusartEnable);
+}
+
+void Usart_receiverOff(void)
+{
+ EUSART_Enable(EUSART0, eusartEnableTx);
+}
+
+bool Usart_setFlowControl(uart_flow_control_e flow)
+{
+ (void)flow;
+ return false;
+}
+
+uint32_t Usart_sendBuffer(const void * buffer, uint32_t length)
+{
+ bool empty = false;
+ uint32_t size_in = length;
+ uint8_t * data_out = (uint8_t *)buffer;
+ Sys_enterCriticalSection();
+
+ // Return if the ring buffer cannot contain the bytes to be transmitted
+ if (Ringbuffer_free(m_usart_tx_buffer) < length)
+ {
+ size_in = 0;
+ }
+ else
+ {
+ empty = (Ringbuffer_usage(m_usart_tx_buffer) == 0);
+ while(length--)
+ {
+ Ringbuffer_getHeadByte(m_usart_tx_buffer) = *data_out++;
+ Ringbuffer_incrHead(m_usart_tx_buffer, 1);
+ }
+ if (empty)
+ {
+ Usart_setEnabled(true);
+ EUSART_IntEnable(EUSART0, EUSART_IF_TXC);
+ while ((EUSART_StatusGet(EUSART0) & EUSART_STATUS_TXFL) && (Ringbuffer_usage(m_usart_tx_buffer) != 0))
+ {
+ EUSART_Tx(EUSART0, Ringbuffer_getTailByte(m_usart_tx_buffer));
+ Ringbuffer_incrTail(m_usart_tx_buffer, 1);
+ }
+ m_tx_active = true;
+ }
+ }
+ Sys_exitCriticalSection();
+ return size_in;
+}
+
+void Usart_enableReceiver(serial_rx_callback_f rx_callback)
+{
+ Sys_enterCriticalSection();
+ // Set callback
+ m_rx_callback = rx_callback;
+ // Enable clock
+ CMU_ClockEnable(cmuClock_EUSART0, true);
+ if(rx_callback)
+ {
+ Sys_enableFastAppIrq(EUSART0_RX_IRQn,
+ APP_LIB_SYSTEM_IRQ_PRIO_HI,
+ EUSART_RX_IRQHandler);
+
+ EUSART_IntEnable(EUSART0, EUSART_IF_RXFL);
+
+ // Set light pull-up resistor
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN,
+ GPIO_MODE_IN_PULL);
+ hal_gpio_set(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN);
+ }
+ else
+ {
+ Sys_disableAppIrq(EUSART0_RX_IRQn);
+
+ EUSART_IntDisable(EUSART0, EUSART_IF_RXFL);
+
+ // Disable input & input pull-up resistor
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN);
+ }
+ EUSART_IntClear(EUSART0, EUSART_IF_RXFL);
+ CMU_ClockEnable(cmuClock_EUSART0, false);
+ Sys_clearFastAppIrq(EUSART0_RX_IRQn);
+ Sys_exitCriticalSection();
+}
+
+uint32_t Usart_getMTUSize(void)
+{
+ return BUFFER_SIZE;
+}
+
+void Usart_flush(void)
+{
+ volatile uint32_t timeout = 20000;
+ while(m_tx_active && timeout > 0)
+ {
+ timeout--;
+ }
+}
+
+void __attribute__((__interrupt__)) EUSART_RX_IRQHandler(void)
+{
+ // Data received
+ uint16_t ch = EUSART0->RXDATA;
+ // RXFULL must be explicitly cleared
+ EUSART_IntClear(EUSART0, EUSART_IF_RXFL);
+
+ if (m_rx_callback != NULL)
+ {
+ m_rx_callback((uint8_t *) &ch, 1);
+ }
+}
+
+void __attribute__((__interrupt__)) EUSART_TX_IRQHandler(void)
+{
+ EUSART_IntClear(EUSART0, EUSART_IF_TXC);
+
+ if (Ringbuffer_usage(m_usart_tx_buffer) == 0)
+ {
+ // when buffer becomes empty, reset indexes
+ EUSART_IntDisable(EUSART0, EUSART_IF_TXC);
+ Usart_setEnabled(false);
+ m_tx_active = false;
+ return;
+ }
+
+ while ((EUSART_StatusGet(EUSART0) & EUSART_STATUS_TXFL) && (Ringbuffer_usage(m_usart_tx_buffer) != 0))
+ {
+ EUSART_Tx(EUSART0, Ringbuffer_getTailByte(m_usart_tx_buffer));
+ Ringbuffer_incrTail(m_usart_tx_buffer, 1);
+ }
+}
diff --git a/mcu/efr/efr32/hal/gpio.c b/mcu/efr/efr32/hal/gpio.c
new file mode 100644
index 00000000..72924962
--- /dev/null
+++ b/mcu/efr/efr32/hal/gpio.c
@@ -0,0 +1,606 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file gpio.c
+ * \brief Board-specific GPIO functions for efr32.
+ * \attention Should be compatible with the gpio.h interface.
+ */
+
+#include "gpio.h"
+#include "mcu.h"
+#include "board.h"
+#include "api.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+
+/*
+ * If some GPIOs are mapped
+ *
+ * Note:
+ * If BOARD_GPIO_PIN_LIST is not defined,
+ * then the dummy functions defined in the gpio_weak.c file will be used instead
+ */
+#ifdef BOARD_GPIO_PIN_LIST
+
+/** \brief Interrupt identified as free (meaning it is available) */
+#define IT_FREE (0x1F) // must be greater than GPIO_EXTINTNO_MAX
+
+/** \brief GPIO external interrupt number */
+typedef uint8_t gpio_it_t;
+
+/** \brief GPIO direction */
+typedef enum
+{
+ /** input direction */
+ DIR_INPUT,
+ /** output direction */
+ DIR_OUTPUT
+} direction_e;
+
+/** \brief GPIO internal configuration */
+typedef struct
+{
+ /** GPIO direction (either input or output) */
+ direction_e direction : 1;
+ /** Callback called on GPIO events. Only used on input GPIO */
+ gpio_in_event_e event_cfg : 2;
+ /** GPIO interrupt number. Only used on input GPIO */
+ gpio_it_t it : 5; // bitsize = 5 to hold interrupt number (see GPIO_EXTINTNO_MAX) and IT_FREE value
+} gpio_cfg_t;
+
+/** \brief GPIO id to GPIO pin map (array index: GPIO id ; array value: GPIO port & pin) */
+static const struct
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+} m_id_to_pin_map[] = BOARD_GPIO_PIN_LIST;
+
+/** \brief Compute number of GPIOs that are mapped (= total number of used GPIOs) */
+#define BOARD_GPIO_NUMBER (sizeof(m_id_to_pin_map) / sizeof(m_id_to_pin_map[0]))
+
+/** \brief GPIO id to GPIO internal config map (array index: GPIO id ; array value: GPIO internal config) */
+static gpio_cfg_t m_id_to_cfg_map[BOARD_GPIO_NUMBER];
+
+/** \brief GPIO id to GPIO event callback map (array index: GPIO id ; array value: GPIO event callback) */
+static gpio_in_event_cb_f m_id_to_event_cb_map[BOARD_GPIO_NUMBER];
+
+/** \brief Has the library been initialized */
+static bool m_initialized = false;
+
+/**
+ * \brief Check if the pin numbers of the mapped GPIOs are valid (if they exist on the MCU)
+ * \return True if all the pin numbers are valid ; False otherwise
+ */
+static bool check_pins(void);
+
+/**
+ * \brief Configure mode (e.g.: pull-down) of input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] in_cfg
+ * GPIO input configuration
+ */
+static void input_set_cfg_mode(gpio_id_t id, const gpio_in_cfg_t *in_cfg);
+
+/**
+ * \brief Configure interrupt of input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] in_cfg
+ * GPIO input configuration
+ * \return Return code of operation
+ */
+static gpio_res_e input_set_cfg_irq(gpio_id_t id, const gpio_in_cfg_t *in_cfg);
+
+/** \brief Initialize GPIOs interrupts */
+static void input_init_irq(void);
+
+/**
+ * \brief Allocate a interrupt number to a GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[out] it
+ * Returned interrupt number
+ * \return Return code of operation
+ */
+static gpio_res_e alloc_it(gpio_id_t id, gpio_it_t *it);
+
+/**
+ * \brief Free a interrupt number allocated to a GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[out] it
+ * Freed interrupt number
+ * \return Return code of operation
+ */
+static void free_it(gpio_id_t id, gpio_it_t *it);
+
+/**
+ * \brief Check if the given interrupt number is already in use or if it is free
+ * \param it
+ * interrupt number to check
+ * \return True if the given interrupt number is free ; False otherwise (meaning it is already in use)
+ */
+static bool is_it_free(gpio_it_t it);
+
+/** \brief function called when a GPIO interrupt is raised. Used to generate the appropriate GPIO event */
+static void gpio_event_handle(void);
+
+/** \brief Enable GPIO clock */
+static inline void enable_gpio_clock(void)
+{
+#if defined(_SILICON_LABS_32B_SERIES_1)
+ CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
+#elif !defined (EFR32MG21)
+ CMU->CLKEN0_SET = CMU_CLKEN0_GPIO;
+#endif
+}
+
+gpio_res_e Gpio_init(void)
+{
+ gpio_id_t id;
+ const gpio_in_cfg_t in_cfg =
+ {
+ .event_cb = NULL,
+ .event_cfg = GPIO_IN_EVENT_NONE,
+ .in_mode_cfg = GPIO_IN_DISABLED
+ };
+
+ if (m_initialized)
+ {
+ /* return if GPIO initialization has already been performed */
+ return GPIO_RES_OK;
+ }
+ if (!check_pins())
+ {
+ return GPIO_RES_INVALID_PIN;
+ }
+
+ Sys_enterCriticalSection();
+
+ enable_gpio_clock();
+ /* Configure each mapped GPIOs to a default configuration */
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ input_set_cfg_mode(id, &in_cfg);
+ /* set interrupt number as unused/free */
+ m_id_to_cfg_map[id].it = IT_FREE;
+ /* Store direction and part of configuration that is used internally */
+ m_id_to_event_cb_map[id] = in_cfg.event_cb;
+ m_id_to_cfg_map[id].direction = DIR_INPUT;
+ m_id_to_cfg_map[id].event_cfg = in_cfg.event_cfg;
+ }
+ input_init_irq();
+
+ Sys_exitCriticalSection();
+
+ m_initialized = true;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_inputSetCfg(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ gpio_res_e res;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || in_cfg == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ Sys_enterCriticalSection();
+
+ input_set_cfg_mode(id, in_cfg);
+ res = input_set_cfg_irq(id, in_cfg);
+ if (res != GPIO_RES_OK)
+ {
+ Sys_exitCriticalSection();
+ return res;
+ }
+ /* Store direction and part of configuration that is used internally */
+ m_id_to_event_cb_map[id] = in_cfg->event_cb;
+ m_id_to_cfg_map[id].direction = DIR_INPUT;
+ m_id_to_cfg_map[id].event_cfg = in_cfg->event_cfg;
+
+ Sys_exitCriticalSection();
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_inputRead(gpio_id_t id, gpio_level_e *level)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+ bool read_val;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || level == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_INPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, &port, &pin);
+ read_val = (GPIO_PinInGet(port, pin) != 0);
+ *level = read_val ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputSetCfg(gpio_id_t id, const gpio_out_cfg_t *out_cfg)
+{
+ GPIO_Mode_TypeDef mode;
+ gpio_port_t port;
+ gpio_pin_t pin;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || out_cfg == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ /*
+ * convert board independant operating mode enum,
+ * to board specific operating mode enum
+ */
+ switch (out_cfg->out_mode_cfg)
+ {
+ case GPIO_OUT_MODE_PUSH_PULL:
+ mode = gpioModePushPull;
+ break;
+ case GPIO_OUT_MODE_OPEN_DRAIN:
+ mode = gpioModeWiredAndFilter;
+ break;
+ case GPIO_OUT_MODE_OPEN_DRAIN_WITH_PULL_UP:
+ mode = gpioModeWiredAndPullUpFilter;
+ break;
+ default:
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ Sys_enterCriticalSection();
+
+ Gpio_getPin(id, &port, &pin);
+ GPIO_PinModeSet(port, pin, mode, (out_cfg->level_default != GPIO_LEVEL_LOW));
+ /* Store direction */
+ m_id_to_cfg_map[id].direction = DIR_OUTPUT;
+
+ Sys_exitCriticalSection();
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputWrite(gpio_id_t id, gpio_level_e level)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, &port, &pin);
+ if (level == GPIO_LEVEL_HIGH)
+ {
+ GPIO_PinOutSet(port, pin);
+ }
+ else
+ {
+ GPIO_PinOutClear(port, pin);
+ }
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputToggle(gpio_id_t id)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, &port, &pin);
+ GPIO_PinOutToggle(port, pin);
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputRead(gpio_id_t id, gpio_level_e *level)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+ bool read_val;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || level == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, &port, &pin);
+ read_val = GPIO_PinOutGet(port, pin) != 0;
+ *level = read_val ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_getPin(gpio_id_t id, gpio_port_t *port, gpio_pin_t *pin)
+{
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ if (port)
+ {
+ *port = m_id_to_pin_map[id].port;
+ }
+ if (pin)
+ {
+ *pin = m_id_to_pin_map[id].pin;
+ }
+
+ return GPIO_RES_OK;
+}
+
+uint8_t Gpio_getNumber(void)
+{
+ return BOARD_GPIO_NUMBER;
+}
+
+static bool check_pins(void)
+{
+ gpio_id_t id;
+ gpio_port_t port;
+ gpio_pin_t pin;
+
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ Gpio_getPin(id, &port, &pin);
+ if (!GPIO_PORT_PIN_VALID(port, pin))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void input_set_cfg_mode(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+ GPIO_Mode_TypeDef efr_mode;
+ bool out;
+
+ /*
+ * convert board independant mode enum,
+ * to board specific mode enum
+ */
+ switch (in_cfg->in_mode_cfg)
+ {
+ case GPIO_IN_DISABLED:
+ efr_mode = gpioModeDisabled;
+ /* set "out" to 0 to disable pull-up */
+ out = false;
+ break;
+ case GPIO_IN_PULL_NONE:
+ efr_mode = gpioModeInput;
+ /* set "out" to 1 to enable filter */
+ out = true;
+ break;
+ case GPIO_IN_PULL_DOWN:
+ efr_mode = gpioModeInputPullFilter;
+ /* "out" determines pull direction (0 -> pull-down) */
+ out = false;
+ break;
+ case GPIO_IN_PULL_UP:
+ efr_mode = gpioModeInputPullFilter;
+ /* "out" determines pull direction (1 -> pull-up) */
+ out = true;
+ break;
+ }
+ Gpio_getPin(id, &port, &pin);
+ GPIO_PinModeSet(port, pin, efr_mode, out);
+}
+
+static gpio_res_e input_set_cfg_irq(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ gpio_port_t port;
+ gpio_pin_t pin;
+ gpio_it_t it;
+ gpio_res_e res;
+
+ /* if no event on this GPIO, ... */
+ if (in_cfg->event_cfg == GPIO_IN_EVENT_NONE)
+ {
+ /* ...then free/unalloc its interrupt number */
+ free_it(id, &it);
+ }
+ /* else if any event on this GPIO, ... */
+ else
+ {
+ /* ...then allocate an interrupt number to the GPIO */
+ res = alloc_it(id, &it);
+ if (res != GPIO_RES_OK)
+ {
+ return res;
+ }
+ }
+
+ /* update the interrupt registers, if got a valid interrupt number */
+ if (it != IT_FREE)
+ {
+ Gpio_getPin(id, &port, &pin);
+ GPIO_ExtIntConfig(port,
+ pin,
+ it,
+ IS_RISING_EDGE(in_cfg->event_cfg),
+ IS_FALLING_EDGE(in_cfg->event_cfg),
+ in_cfg->event_cfg != GPIO_IN_EVENT_NONE);
+ }
+ return GPIO_RES_OK;
+}
+
+static void input_init_irq(void)
+{
+ GPIO_IntDisable(_GPIO_IEN_MASK & 0x0000FFFF);
+ lib_system->enableAppIrq(true, GPIO_EVEN_IRQn, APP_LIB_SYSTEM_IRQ_PRIO_LO, gpio_event_handle);
+ lib_system->enableAppIrq(true, GPIO_ODD_IRQn, APP_LIB_SYSTEM_IRQ_PRIO_LO, gpio_event_handle);
+ lib_system->clearPendingFastAppIrq(GPIO_EVEN_IRQn);
+ lib_system->clearPendingFastAppIrq(GPIO_ODD_IRQn);
+}
+
+static gpio_res_e alloc_it(gpio_id_t id, gpio_it_t *it)
+{
+ gpio_pin_t pin;
+ gpio_it_t it_tmp, it_min, it_max;
+ bool it_found = false;
+
+ /*
+ * if an interrupt number was already allocated for this GPIO,
+ * then just return it.
+ */
+ it_tmp = m_id_to_cfg_map[id].it;
+ if (it_tmp != IT_FREE)
+ {
+ *it = it_tmp;
+ return GPIO_RES_OK;
+ }
+
+ /*
+ * Refer to chapter "Edge Interrupt Generation" in the MCU reference manual
+ * for an explanation about the interrupt number allocation mechanism
+ *
+ * Example:
+ * GPIO pin = Px5. in group Px[4:7] -> so one interrupt in the EXTI[4-7] interrupt group can be used.
+ */
+ Gpio_getPin(id, NULL, &pin);
+ it_min = SL_FLOOR(pin, 4);
+ it_max = SL_FLOOR(pin, 4) + 3;
+
+ /* Browse the interrupt group, and allocate the first interrupt that is free */
+ for (it_tmp = it_min; it_tmp <= it_max; it_tmp++)
+ {
+ if (is_it_free(it_tmp))
+ {
+ m_id_to_cfg_map[id].it = it_tmp;
+ *it = it_tmp;
+ it_found = true;
+ break;
+ }
+ }
+ return it_found ? GPIO_RES_OK : GPIO_RES_NO_FREE_IT;
+}
+
+static void free_it(gpio_id_t id, gpio_it_t *it)
+{
+ *it = m_id_to_cfg_map[id].it;
+ m_id_to_cfg_map[id].it = IT_FREE;
+}
+
+static bool is_it_free(gpio_it_t it)
+{
+ gpio_id_t id;
+
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ if (m_id_to_cfg_map[id].it == it)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void gpio_event_handle(void)
+{
+ gpio_id_t id;
+ gpio_it_t it;
+ bool it_raised;
+ gpio_level_e level;
+ gpio_in_event_cb_f event_cb;
+ gpio_in_event_e event_cfg;
+ gpio_in_event_e event;
+
+ /* for each GPIO */
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ /* get the interrupt number of the GPIO */
+ it = m_id_to_cfg_map[id].it;
+ if (it == IT_FREE)
+ {
+ continue;
+ }
+
+ /* check if the GPIO interrupt flag is set */
+ it_raised = (GPIO_IntGet() & (((uint32_t) 1) << it)) != 0;
+ if (it_raised)
+ {
+ Gpio_inputRead(id, &level);
+ /* get stored/internal config */
+ event_cb = m_id_to_event_cb_map[id];
+ event_cfg = m_id_to_cfg_map[id].event_cfg;
+ /*
+ * Invoke user handler only if the pin level
+ * matches its polarity configuration.
+ */
+ if (event_cb &&
+ ((IS_RISING_EDGE(event_cfg) && IS_FALLING_EDGE(event_cfg)) ||
+ (level == GPIO_LEVEL_HIGH && IS_RISING_EDGE(event_cfg)) ||
+ (level == GPIO_LEVEL_LOW && IS_FALLING_EDGE(event_cfg))))
+ {
+ event = (level == GPIO_LEVEL_HIGH) ? GPIO_IN_EVENT_RISING_EDGE : GPIO_IN_EVENT_FALLING_EDGE;
+ event_cb(id, event);
+ }
+
+ /* clear the GPIO interrupt flag */
+ GPIO_IntClear((uint32_t) 1 << it);
+ }
+ }
+}
+
+#endif // BOARD_GPIO_PIN_LIST
diff --git a/mcu/efr/efr32/hal/led.c b/mcu/efr/efr32/hal/led.c
deleted file mode 100644
index 25cf978b..00000000
--- a/mcu/efr/efr32/hal/led.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* Copyright 2019 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file led.c
- * \brief Board-specific LED functions for efr32
- */
-
-#include "led.h"
-#include "mcu.h"
-#include "board.h"
-
-#ifdef BOARD_LED_PIN_LIST
-
-/*
- * The selected board has LEDs
- */
-
-#ifndef BOARD_LED_ACTIVE_LOW
-/** \brief Are LEDs active low. It can be overwritten from board.h */
-#define BOARD_LED_ACTIVE_LOW false
-#endif
-
-typedef struct
-{
- uint8_t port;
- uint8_t pin;
-} led_gpio_t;
-
-/** \brief Board-dependent LED number to pin mapping */
-static const led_gpio_t pin_map[] = BOARD_LED_PIN_LIST;
-
-/** \brief Compute number of leds on the board */
-#define NUMBER_OF_LEDS (sizeof(pin_map) / sizeof(pin_map[0]))
-
-static void led_configure(uint8_t led_id)
-{
- led_gpio_t led = pin_map[led_id];
- if (led.pin > 15 || led.port > GPIO_PORT_MAX)
- {
- return;
- }
-
-#if defined(_SILICON_LABS_32B_SERIES_1)
- /* Enable clocks */
- CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
-#elif !defined (EFR32MG21)
- CMU->CLKEN0_SET = CMU_CLKEN0_GPIO;
-#endif
-
- /* Set pin mode */
- hal_gpio_set_mode(led.port,
- led.pin,
- GPIO_MODE_OUT_PP);
-
- /* Off by default */
-#if BOARD_LED_ACTIVE_LOW
- hal_gpio_set(led.port, led.pin);
-#else // BOARD_LED_ACTIVE_LOW
- hal_gpio_clear(led.port, led.pin);
-#endif // BOARD_LED_ACTIVE_LOW
-}
-
-void Led_init(void)
-{
- for (uint8_t i = 0; i < NUMBER_OF_LEDS; i++)
- {
- // Set up LED GPIO
- led_configure(i);
- }
-}
-
-bool Led_get(uint8_t led_id)
-{
- if (led_id >= NUMBER_OF_LEDS)
- {
- return LED_RES_INVALID_ID;
- }
- led_gpio_t led = pin_map[led_id];
- if (led.pin > 15 || led.port > GPIO_PORT_MAX)
- {
- return LED_RES_INVALID_ID;
- }
-
-#if BOARD_LED_ACTIVE_LOW
- return (hal_gpio_get(led.port, led.pin) == 0);
-#else //BOARD_LED_ACTIVE_HIGH
- return (hal_gpio_get(led.port, led.pin) != 0);
-#endif // BOARD_LED_ACTIVE_LOW
-}
-
-led_res_e Led_set(uint8_t led_id, bool state)
-{
- if (led_id >= NUMBER_OF_LEDS)
- {
- return LED_RES_INVALID_ID;
- }
-
- led_gpio_t led = pin_map[led_id];
- if (led.pin > 15 || led.port > GPIO_PORT_MAX)
- {
- return LED_RES_INVALID_ID;
- }
-
-#if BOARD_LED_ACTIVE_LOW
- if (state)
- {
- hal_gpio_clear(led.port, led.pin);
- }
- else
- {
- hal_gpio_set(led.port, led.pin);
- }
-#else // BOARD_LED_ACTIVE_LOW
- if (state)
- {
- hal_gpio_set(led.port, led.pin);
- }
- else
- {
- hal_gpio_clear(led.port, led.pin);
- }
-#endif // BOARD_LED_ACTIVE_LOW
-
- return LED_RES_OK;
-}
-
-led_res_e Led_toggle(uint8_t led_id)
-{
- if (led_id >= NUMBER_OF_LEDS)
- {
- return LED_RES_INVALID_ID;
- }
-
- led_gpio_t led = pin_map[led_id];
-
- if (led.pin > 15 || led.port > GPIO_PORT_MAX)
- {
- return LED_RES_INVALID_ID;
- }
-
- hal_gpio_toggle(led.port, led.pin);
-
- return LED_RES_OK;
-}
-
-uint8_t Led_getNumber(void)
-{
- return NUMBER_OF_LEDS;
-}
-
-#else // BOARD_LED_PIN_LIST
-
-/*
- * The selected board has no LEDs
- *
- * As some example apps support such boards but also provide extra status
- * information when a board has LEDs, the LED driver has this dummy
- * implementation to simplify the build process.
- */
-
-void Led_init(void)
-{
- // Do nothing
-}
-
-led_res_e Led_set(uint8_t led_id, bool state)
-{
- (void) led_id;
- (void) state;
-
- // Invalid LED number
- return LED_RES_INVALID_ID;
-}
-
-led_res_e Led_toggle(uint8_t led_id)
-{
- (void) led_id;
-
- // Invalid LED number
- return LED_RES_INVALID_ID;
-}
-
-uint8_t Led_getNumber(void)
-{
- return 0;
-}
-
-#endif // BOARD_LED_PIN_LIST
diff --git a/mcu/efr/efr32/hal/makefile b/mcu/efr/efr32/hal/makefile
index 0e9b585b..f2d26100 100644
--- a/mcu/efr/efr32/hal/makefile
+++ b/mcu/efr/efr32/hal/makefile
@@ -4,7 +4,16 @@ EFR32_VENDOR_PREFIX :=$(MCU_COMMON)/vendor/
# Add include path for nrf52 specific HAL header files
INCLUDES += -I$(EFR32_HAL_PREFIX)
+ifeq ($(HAL_GPIO), yes)
+SRCS += $(EFR32_HAL_PREFIX)gpio.c
+SRCS += $(EFR32_VENDOR_PREFIX)em_core.c
+endif
+
ifeq ($(HAL_UART), yes)
+ifeq ($(MCU_SUB), xg23)
+SRCS += $(EFR32_HAL_PREFIX)eusart.c
+SRCS += $(EFR32_VENDOR_PREFIX)em_eusart.c
+else
ifeq ($(UART_USE_DMA), yes)
SRCS += $(EFR32_HAL_PREFIX)usart_dma.c \
$(EFR32_VENDOR_PREFIX)em_ldma.c \
@@ -12,8 +21,9 @@ SRCS += $(EFR32_HAL_PREFIX)usart_dma.c \
else
SRCS += $(EFR32_HAL_PREFIX)usart.c
endif
-SRCS += $(EFR32_VENDOR_PREFIX)em_usart.c \
- $(EFR32_VENDOR_PREFIX)$(HAL_SYSTEM_C)
+SRCS += $(EFR32_VENDOR_PREFIX)em_usart.c
+endif
+SRCS += $(EFR32_VENDOR_PREFIX)$(HAL_SYSTEM_C)
endif
ifeq ($(HAL_I2C), yes)
@@ -31,14 +41,6 @@ INCLUDES += -I$(EFR32_VENDOR_PREFIX)rail_lib/chip/efr32/efr32xg2x
INCLUDES += -I$(EFR32_VENDOR_PREFIX)rail_lib/common
endif
-ifeq ($(HAL_BUTTON), yes)
-SRCS += $(EFR32_HAL_PREFIX)button.c
-endif
-
-ifeq ($(HAL_LED), yes)
-SRCS += $(EFR32_HAL_PREFIX)led.c
-endif
-
ifeq ($(HAL_VOLTAGE), yes)
ifneq (,$(filter $(MCU_SUB), xg21 xg22))
SRCS += $(EFR32_VENDOR_PREFIX)em_iadc.c \
@@ -54,6 +56,23 @@ ifeq ($(HAL_PRS), yes)
SRCS += $(EFR32_VENDOR_PREFIX)em_prs.c
endif
+ifeq ($(HAL_SPI), yes)
+ifneq (,$(filter $(MCU_SUB), xg22 xg23))
+SRCS += $(EFR32_HAL_PREFIX)spi.c
+ifeq ($(MCU_SUB), xg23)
+SRCS += $(EFR32_VENDOR_PREFIX)em_usart.c \
+ $(EFR32_VENDOR_PREFIX)$(HAL_SYSTEM_C)
+else
+ifneq ($(HAL_UART), yes)
+SRCS += $(EFR32_VENDOR_PREFIX)em_usart.c \
+ $(EFR32_VENDOR_PREFIX)$(HAL_SYSTEM_C)
+endif
+endif
+else
+$(error Board $(target_board) doesn't support SPI (xg22 or xg23 only))
+endif
+endif
+
SRCS += $(EFR32_HAL_PREFIX)ds.c \
$(EFR32_HAL_PREFIX)power.c \
$(EFR32_HAL_PREFIX)hal.c \
diff --git a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg12_19dBm.h b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg12_19dBm.h
index e7c9fbec..5b723cae 100644
--- a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg12_19dBm.h
+++ b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg12_19dBm.h
@@ -10,7 +10,7 @@
const app_lib_radio_cfg_power_t power_table_efr32xg12_19dBm =
{
.rx_current = 100, // 10 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg21_20dbm.h b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg21_20dbm.h
index 6bf85d68..3f240ffa 100644
--- a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg21_20dbm.h
+++ b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg21_20dbm.h
@@ -15,7 +15,7 @@
const app_lib_radio_cfg_power_t power_table_efr32xg21_20dBm =
{
.rx_current = 880, // 8.8 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_13dbm.h b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_13dbm.h
index f5edf889..4e6df2e6 100644
--- a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_13dbm.h
+++ b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_13dbm.h
@@ -14,7 +14,7 @@
const app_lib_radio_cfg_power_t power_table_efr32xg23_13dBm =
{
.rx_current = 69, // 6.9 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_16dbm.h b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_16dbm.h
index 5b18b088..47da4290 100644
--- a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_16dbm.h
+++ b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_16dbm.h
@@ -14,7 +14,7 @@
const app_lib_radio_cfg_power_t power_table_efr32xg23_16dBm =
{
.rx_current = 69, // 6.9 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_20dbm.h b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_20dbm.h
index bdd9304e..e6dfb33b 100644
--- a/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_20dbm.h
+++ b/mcu/efr/efr32/hal/radio/radio_power_table_efr32xg23_20dbm.h
@@ -14,7 +14,7 @@
const app_lib_radio_cfg_power_t power_table_efr32xg23_20dBm =
{
.rx_current = 69, // 6.9 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/efr/efr32/hal/spi.c b/mcu/efr/efr32/hal/spi.c
new file mode 100644
index 00000000..155bdd3e
--- /dev/null
+++ b/mcu/efr/efr32/hal/spi.c
@@ -0,0 +1,394 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+#include
+#include
+#include
+
+#include "hal_api.h"
+#include "board.h"
+#include "api.h"
+#include "spi.h"
+
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_usart.h"
+
+// References:
+// [1] EFR32xG23 Wireless SoC Reference Manual
+// https://www.silabs.com/documents/public/reference-manuals/efr32xg23-rm.pdf
+
+#ifndef BOARD_SPI
+#error "Please define the required SPI definition in your board.h (BOARD_SPI,…)"
+#endif
+
+#define SPI_EXTFLASH_BAUDRATE 8000000
+
+// Dummy byte for SPI transfer
+#define DUMMY_BYTE 0xFF
+
+/** Internal transfer description */
+typedef struct
+{
+ spi_xfer_t * client_xfer; //< Transfer asked by client
+ spi_on_transfer_done_cb_f cb; //< Callback to call at end of transfer
+ bool free; //< False if transfer ongoing
+ volatile bool done; //< Is transfer done
+} internal_xfer_desc;
+
+/** Current tansfer ongoing. Only one transfer supported in this implementation */
+static internal_xfer_desc m_current_xfer;
+
+/** Is SPI module initialized */
+static bool m_spi_initialized = false;
+
+/***************************************************************************//**
+ * @brief Configure different SPI gpios (MOSI, MISO, SCLK and CS)
+ * @param[in] mode
+ * SPI chosen mode \ref spi_mode_e
+ ******************************************************************************/
+static void spidrv_configure_gpios(spi_mode_e mode)
+{
+ // Pin configuration: refer to doc [1] section 24.3.1 Pin Configuration
+ // Setup the MOSI pin (TX), PUSHPULL mode
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_MOSI_PORT,
+ BOARD_SPI_EXTFLASH_MOSI_PIN,
+ GPIO_MODE_OUT_PP);
+ hal_gpio_clear(BOARD_SPI_EXTFLASH_MOSI_PORT, BOARD_SPI_EXTFLASH_MOSI_PIN);
+
+ // Setup the MISO pin (RX), INPUT mode
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_MISO_PORT,
+ BOARD_SPI_EXTFLASH_MISO_PIN,
+ GPIO_MODE_IN_OD_NOPULL);
+ hal_gpio_clear(BOARD_SPI_EXTFLASH_MISO_PORT, BOARD_SPI_EXTFLASH_MISO_PIN);
+
+ // Setup the SCLK pin, PUSHPULL mode:
+ // - serial mode 0 and 1 => SCLK idle low
+ // - serial mode 2 and 3 => SCLK idle high)
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_SCKL_PORT,
+ BOARD_SPI_EXTFLASH_SCKL_PIN,
+ GPIO_MODE_OUT_PP);
+ if (SPI_MODE_LOW_FIRST == mode || SPI_MODE_LOW_SECOND == mode)
+ {
+ hal_gpio_clear(BOARD_SPI_EXTFLASH_SCKL_PORT,
+ BOARD_SPI_EXTFLASH_SCKL_PIN);
+ }
+ else
+ {
+ hal_gpio_set(BOARD_SPI_EXTFLASH_SCKL_PORT,
+ BOARD_SPI_EXTFLASH_SCKL_PIN);
+ }
+}
+
+/***************************************************************************//**
+ * @brief Release different SPI GPIOs (MOSI, MISO, SCLK and CS)
+ ******************************************************************************/
+static void spidrv_release_gpios(void)
+{
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_MOSI_PORT,
+ BOARD_SPI_EXTFLASH_MOSI_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_MISO_PORT,
+ BOARD_SPI_EXTFLASH_MISO_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_set_mode(BOARD_SPI_EXTFLASH_SCKL_PORT,
+ BOARD_SPI_EXTFLASH_SCKL_PIN,
+ GPIO_MODE_DISABLED);
+}
+
+/***************************************************************************//**
+ * @brief Convert configuration parameters
+ * @param[in] p_in
+ * SPI driver API configuration parameters \ref spi_conf_t
+ * @param[out] p_out
+ * EFR32 xG2x USART configuration parameters
+ * \ref USART_InitSync_TypeDef
+ * @return true if input parameters are valid, false otherwise
+ ******************************************************************************/
+static bool spidrv_convert_parameters(spi_conf_t * in_p,
+ USART_InitSync_TypeDef * out_p)
+{
+ switch (in_p->mode)
+ {
+ //< Low Polarity, First Clock edge
+ case SPI_MODE_LOW_FIRST:
+ out_p->clockMode = usartClockMode0;
+ break;
+ //< Low Polarity, Second Clock edge
+ case SPI_MODE_LOW_SECOND:
+ out_p->clockMode = usartClockMode1;
+ break;
+ //< High Polarity, First Clock edge
+ case SPI_MODE_HIGH_FIRST:
+ out_p->clockMode = usartClockMode2;
+ break;
+ //< High Polarity, Second Clock edge
+ case SPI_MODE_HIGH_SECOND:
+ out_p->clockMode = usartClockMode3;
+ break;
+ default:
+ return false;
+ }
+
+ switch (in_p->bit_order)
+ {
+ //< Most Significant Bit first
+ case SPI_ORDER_MSB:
+ out_p->msbf = true;
+ break;
+ //< Less Significant Bit first
+ case SPI_ORDER_LSB:
+ out_p->msbf = false;
+ break;
+ default:
+ return false;
+ }
+
+ if (! in_p->clock)
+ {
+ return false;
+ }
+ out_p->baudrate = in_p->clock;
+
+ return true;
+}
+
+/***************************************************************************//**
+ * @brief Enable USART clock
+ * @param[in] p_in
+ * SPI driver API configuration parameters \ref spi_conf_t
+ * @param[out] p_out
+ * EFR32 xG2x USART configuration parameters
+ * \ref USART_InitSync_TypeDef
+ * @return true if input parameters are valid, false otherwise
+ ******************************************************************************/
+static void enable_usart_clock(void)
+{
+ DS_Disable(DS_SOURCE_USART);
+ CMU->CLKEN0_SET = CMU_CLKEN0_USART0;
+}
+
+/***************************************************************************//**
+ * @brief Disable USART clock
+ * @param[in] p_in
+ * SPI driver API configuration parameters \ref spi_conf_t
+ * @param[out] p_out
+ * EFR32 xG2x USART configuration parameters
+ * \ref USART_InitSync_TypeDef
+ * @return true if input parameters are valid, false otherwise
+ ******************************************************************************/
+static void disable_usart_clock(void)
+{
+ CMU->CLKEN0_CLR = CMU_CLKEN0_USART0;
+ DS_Enable(DS_SOURCE_USART);
+}
+
+/***************************************************************************//**
+ * @brief
+ * Initialize SPI i.e. USART block for synchronous mode.
+ *
+ * @details
+ * This function will configure basic settings to operate in
+ * synchronous mode.
+ *
+ * @param[in] conf_p
+ * A pointer to the SPI configuration parameters \ref spi_conf_t
+ *
+ * @return
+ * \ref SPI_RES_OK if initialization is ok, an error code otherwise
+ * Refer to \ref spi_res_e for other result codes
+ ******************************************************************************/
+spi_res_e SPI_init(spi_conf_t * conf_p)
+{
+ if (m_spi_initialized)
+ {
+ return SPI_RES_ALREADY_INITIALIZED;
+ }
+
+ // Check and convert input parameters
+ USART_InitSync_TypeDef USART_init = USART_INITSYNC_DEFAULT;
+ USART_init.enable = usartDisable;
+ if (! conf_p || false == spidrv_convert_parameters(conf_p, &USART_init))
+ {
+ return SPI_RES_INVALID_CONFIG;
+ }
+
+ // Enable GPIO clock
+ CMU->CLKEN0_SET = CMU_CLKEN0_GPIO;
+
+ // Configure GPIO
+ spidrv_configure_gpios(conf_p->mode);
+
+ // Enable USART clock during the configuration
+ enable_usart_clock();
+
+ // Configure UART in sync mode
+ USART_InitSync(BOARD_SPI, &USART_init);
+
+ // Set UART routes
+ // Refer to doc [1], sections:
+ // - 24.6.192 GPIO_USART0_TXROUTE - TX Port/Pin Select
+ // - 24.6.190 GPIO_USART0_RXROUTE - RX Port/Pin Select
+ // - 24.6.191 GPIO_USART0_CLKROUTE - SCLK Port/Pin Select
+ BOARD_SPIROUTE.TXROUTE =
+ (BOARD_SPI_EXTFLASH_MOSI_PORT << _GPIO_USART_TXROUTE_PORT_SHIFT) |
+ (BOARD_SPI_EXTFLASH_MOSI_PIN << _GPIO_USART_TXROUTE_PIN_SHIFT);
+
+ BOARD_SPIROUTE.RXROUTE =
+ (BOARD_SPI_EXTFLASH_MISO_PORT << _GPIO_USART_RXROUTE_PORT_SHIFT) |
+ (BOARD_SPI_EXTFLASH_MISO_PIN << _GPIO_USART_RXROUTE_PIN_SHIFT);
+
+ BOARD_SPIROUTE.CLKROUTE =
+ (BOARD_SPI_EXTFLASH_SCKL_PORT << _GPIO_USART_CLKROUTE_PORT_SHIFT) |
+ (BOARD_SPI_EXTFLASH_SCKL_PIN << _GPIO_USART_CLKROUTE_PIN_SHIFT);
+
+ // Enable the routes
+ // Refer to doc [1] 24.6.186 GPIO_USART0_ROUTEEN - USART0 Pin Enable
+ BOARD_SPIROUTE.ROUTEEN = GPIO_USART_ROUTEEN_TXPEN |
+ GPIO_USART_ROUTEEN_RXPEN |
+ GPIO_USART_ROUTEEN_CLKPEN;
+
+
+ // Enable data transmission and reception
+ // Refer to doc [1] section 20.5.3 USART_CTRL - Control Register
+ BOARD_SPI->CMD = USART_CMD_RXEN | USART_CMD_TXEN;
+
+ // Configuration done: disable USART clock
+ disable_usart_clock();
+
+ // Initialize the transfer structure
+ memset(&m_current_xfer, 0x00, sizeof(m_current_xfer));
+ m_current_xfer.free = true;
+
+ m_spi_initialized = true;
+
+ return SPI_RES_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ * Deinitialize SPI
+ *
+ * @return
+ * \ref SPI_RES_OK if initialization is ok, an error code otherwise
+ * Refer to \ref spi_res_e for other result codes
+ ******************************************************************************/
+ spi_res_e SPI_close(void)
+{
+ if (! m_spi_initialized)
+ {
+ return SPI_RES_NOT_INITIALIZED;
+ }
+
+ // Enable USART clock
+ enable_usart_clock();
+
+ // Reser USART registers to their default configuration
+ USART_Reset(BOARD_SPI);
+
+ // Disable USART clock
+ disable_usart_clock();
+
+ // Disable the routes
+ BOARD_SPIROUTE.RXROUTE = _GPIO_USART_RXROUTE_RESETVALUE;
+ BOARD_SPIROUTE.TXROUTE = _GPIO_USART_TXROUTE_RESETVALUE;
+ BOARD_SPIROUTE.CLKROUTE = _GPIO_USART_CLKROUTE_RESETVALUE;
+ BOARD_SPIROUTE.ROUTEEN = _GPIO_USART_ROUTEEN_RESETVALUE;
+
+ // Set all GPIOs as default configuration
+ spidrv_release_gpios();
+
+ m_spi_initialized = false;
+
+ return SPI_RES_OK;
+}
+
+/***************************************************************************//**
+ * @brief
+ * SPI_transfer
+ *
+ * @details
+ *
+ * @param[in] xfer_p
+ * A pointer to the structure describing a SPI transfer \ref spi_xfer_t
+ * @param[in] cb
+ * Callback to be called when the transfer is done
+ *
+ * @return
+ * \ref SPI_RES_OK if the transfer is ok, an error code otherwise
+ * Refer to \ref spi_res_e for other result codes
+ ******************************************************************************/
+spi_res_e SPI_transfer(spi_xfer_t * xfer_p,
+ spi_on_transfer_done_cb_f cb)
+{
+ uint32_t i;
+
+ if (! m_spi_initialized)
+ {
+ return SPI_RES_NOT_INITIALIZED;
+ }
+
+ // Check if a transfer is already ongoing
+ if (! m_current_xfer.free)
+ {
+ return SPI_RES_BUSY;
+ }
+
+ // Check transfer
+ if (((xfer_p->write_ptr != NULL) && (xfer_p->write_size == 0)) ||
+ ((xfer_p->write_ptr == NULL) && (xfer_p->write_size != 0)) ||
+ ((xfer_p->read_ptr != NULL) && (xfer_p->read_size == 0)) ||
+ ((xfer_p->read_ptr == NULL) && (xfer_p->read_size != 0)))
+ {
+ return SPI_RES_INVALID_XFER;
+ }
+
+ // We just support synchronous transfers
+ if (NULL != cb)
+ {
+ return SPI_RES_INVALID_XFER;
+ }
+
+ // Enable USART clock
+ enable_usart_clock();
+
+ // Setup the transfer
+ m_current_xfer.free = false;
+ m_current_xfer.client_xfer = xfer_p;
+ m_current_xfer.done = false;
+ m_current_xfer.cb = NULL;
+
+ // Send the command
+ for (i = 0; i < m_current_xfer.client_xfer->write_size; i++)
+ {
+ uint8_t rsp;
+ rsp = USART_SpiTransfer(BOARD_SPI,
+ m_current_xfer.client_xfer->write_ptr[i]);
+ if (i < m_current_xfer.client_xfer->read_size)
+ {
+ m_current_xfer.client_xfer->read_ptr[i] = rsp;
+ }
+ }
+
+ // Read the data if requested
+ if (m_current_xfer.client_xfer->read_size >
+ m_current_xfer.client_xfer->write_size)
+ {
+ for (i = m_current_xfer.client_xfer->write_size;
+ i < m_current_xfer.client_xfer->read_size; i++)
+ {
+ m_current_xfer.client_xfer->read_ptr[i] =
+ USART_SpiTransfer(BOARD_SPI, DUMMY_BYTE);
+ }
+ }
+
+ m_current_xfer.done = true;
+ m_current_xfer.free = true;
+
+ // Disable clocks
+ disable_usart_clock();
+
+ return SPI_RES_OK;
+}
diff --git a/mcu/efr/efr32/hal/usart.c b/mcu/efr/efr32/hal/usart.c
index d3ab7504..f0e46719 100644
--- a/mcu/efr/efr32/hal/usart.c
+++ b/mcu/efr/efr32/hal/usart.c
@@ -12,6 +12,7 @@
#include "board.h"
#include "board_usart.h"
#include "api.h"
+#include "gpio.h"
#include "em_cmu.h"
#include "em_gpio.h"
@@ -38,6 +39,14 @@ void __attribute__((__interrupt__)) USART_TX_IRQHandler(void);
bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
{
+#ifdef BOARD_GPIO_ID_VCOM_ENABLE
+ const gpio_out_cfg_t usart_vcom_enable_cfg =
+ {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH
+ };
+#endif
+
#ifdef BOARD_USART_FORCE_BAUDRATE
// Some hardware only support a given speed, so override the chosen baudrate
baudrate = BOARD_USART_FORCE_BAUDRATE;
@@ -47,33 +56,10 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
// Enable GPIO clock
BOARD_USART_ENABLE_GPIO_CLK;
-#ifdef BOARD_USART_VCOM_PORT
+#ifdef BOARD_GPIO_ID_VCOM_ENABLE
// Enable vcom
- hal_gpio_set_mode(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN);
- hal_gpio_set_mode(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN,
- GPIO_MODE_OUT_PP);
- hal_gpio_set(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN);
+ Gpio_outputSetCfg(BOARD_GPIO_ID_VCOM_ENABLE, &usart_vcom_enable_cfg);
#endif
-
- // uart_tx_pin
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
- BOARD_USART_TX_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
- BOARD_USART_TX_PIN);
- // uart_rx_pin
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
- BOARD_USART_RX_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
- BOARD_USART_RX_PIN);
-
// Module variables
Ringbuffer_reset(m_usart_tx_buffer);
m_rx_callback = NULL;
@@ -98,6 +84,19 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
USART_init.hwFlowControl = usartHwFlowControlNone;
USART_InitAsync(BOARD_USART, &USART_init);
+ // Set UART TX GPIO
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN);
+ // Set UART RX GPIO
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN);
+
// Set UART route
BOARD_USART_ROUTE;
@@ -136,7 +135,7 @@ void Usart_setEnabled(bool enabled)
// Disable deep sleep
DS_Disable(DS_SOURCE_USART);
// Set output
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN,
GPIO_MODE_OUT_PP);
}
@@ -151,10 +150,10 @@ void Usart_setEnabled(bool enabled)
if(m_enabled == 0)
{
// Set light pullup
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN,
GPIO_MODE_IN_PULL);
- hal_gpio_set(BOARD_USART_GPIO_PORT,
+ hal_gpio_set(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN);
// Enable deep sleep
DS_Enable(DS_SOURCE_USART);
@@ -225,22 +224,22 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
USART_RX_IRQHandler);
BUS_RegBitWrite(&(BOARD_USART->IEN), _USART_IEN_RXDATAV_SHIFT, 1);
// Set light pull-up resistor
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN,
GPIO_MODE_IN_PULL);
- hal_gpio_set(BOARD_USART_GPIO_PORT,
+ hal_gpio_set(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN);
-
}
else
{
Sys_disableAppIrq(BOARD_UART_RX_IRQn);
BUS_RegBitWrite(&(BOARD_USART->IEN), _USART_IEN_RXDATAV_SHIFT, 0);
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ // Disable input & input pull-up resistor
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN,
GPIO_MODE_DISABLED);
- // Disable pull-up for disabled GPIO:s
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
+ // Disable pull-up for disabled GPIO
+ hal_gpio_clear(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN);
}
// Clear all interrupts
diff --git a/mcu/efr/efr32/hal/usart_dma.c b/mcu/efr/efr32/hal/usart_dma.c
index 357844d8..1f2c8682 100644
--- a/mcu/efr/efr32/hal/usart_dma.c
+++ b/mcu/efr/efr32/hal/usart_dma.c
@@ -11,6 +11,7 @@
#include "board.h"
#include "board_usart.h"
#include "api.h"
+#include "gpio.h"
#include "em_cmu.h"
#include "em_gpio.h"
@@ -66,6 +67,14 @@ static LDMA_Descriptor_t m_tx_dma_descriptor[3];
bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
{
+#ifdef BOARD_GPIO_ID_VCOM_ENABLE
+ const gpio_out_cfg_t usart_vcom_enable_cfg =
+ {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH
+ };
+#endif
+
#ifdef BOARD_USART_FORCE_BAUDRATE
// Some hardware only support a given speed, so override the chosen baudrate
baudrate = BOARD_USART_FORCE_BAUDRATE;
@@ -75,33 +84,11 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
// Enable GPIO clock
BOARD_USART_ENABLE_GPIO_CLK;
-#ifdef BOARD_USART_VCOM_PORT
+#ifdef BOARD_GPIO_ID_VCOM_ENABLE
// Enable vcom
- hal_gpio_set_mode(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN);
- hal_gpio_set_mode(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN,
- GPIO_MODE_OUT_PP);
- hal_gpio_set(BOARD_USART_VCOM_PORT,
- BOARD_USART_VCOM_PIN);
+ Gpio_outputSetCfg(BOARD_GPIO_ID_VCOM_ENABLE, &usart_vcom_enable_cfg);
#endif
- // uart_tx_pin
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
- BOARD_USART_TX_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
- BOARD_USART_TX_PIN);
- // uart_rx_pin
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
- BOARD_USART_RX_PIN,
- GPIO_MODE_DISABLED);
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
- BOARD_USART_RX_PIN);
-
// Module variables
m_rx_callback = NULL;
m_enabled = 0;
@@ -122,6 +109,19 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
USART_init.hwFlowControl = usartHwFlowControlNone;
USART_InitAsync(BOARD_USART, &USART_init);
+ // Set UART TX GPIO
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_TX_PORT,
+ BOARD_USART_TX_PIN);
+ // Set UART RX GPIO
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN,
+ GPIO_MODE_DISABLED);
+ hal_gpio_clear(BOARD_USART_RX_PORT,
+ BOARD_USART_RX_PIN);
+
// Set UART route
BOARD_USART_ROUTE;
@@ -180,7 +180,7 @@ void Usart_setEnabled(bool enabled)
// Disable deep sleep
DS_Disable(DS_SOURCE_USART);
// Set output
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN,
GPIO_MODE_OUT_PP);
}
@@ -197,10 +197,10 @@ void Usart_setEnabled(bool enabled)
wait_end_of_tx();
// Set light pullup
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN,
GPIO_MODE_IN_PULL);
- hal_gpio_set(BOARD_USART_GPIO_PORT,
+ hal_gpio_set(BOARD_USART_TX_PORT,
BOARD_USART_TX_PIN);
// Enable deep sleep
DS_Enable(DS_SOURCE_USART);
@@ -502,22 +502,21 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
BUS_RegBitWrite(&(BOARD_USART->IEN), _USART_IEN_TCMP1_SHIFT, 1);
// Set light pull-up resistor
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN,
GPIO_MODE_IN_PULL);
- hal_gpio_set(BOARD_USART_GPIO_PORT,
+ hal_gpio_set(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN);
-
}
else
{
Sys_disableAppIrq(BOARD_UART_RX_IRQn);
BUS_RegBitWrite(&(BOARD_USART->IEN), _USART_IEN_TCMP1_SHIFT, 0);
- hal_gpio_set_mode(BOARD_USART_GPIO_PORT,
+ hal_gpio_set_mode(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN,
GPIO_MODE_DISABLED);
- // Disable pull-up for disabled GPIO:s
- hal_gpio_clear(BOARD_USART_GPIO_PORT,
+ // Disable pull-up for disabled GPIO
+ hal_gpio_clear(BOARD_USART_RX_PORT,
BOARD_USART_RX_PIN);
}
diff --git a/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_app.ini b/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_app.ini
index 919ba8e9..c596982c 100644
--- a/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_wp.ini b/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_wp.ini
index 47b63fa0..51e55551 100644
--- a/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg12pxxxf1024_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 2048 ; Size of individually erasable block, in bytes: 2 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000105 ; Area ID: HWM_EFR32_SP_2 | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_app.ini b/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_app.ini
index b3b4fd15..d083fe30 100644
--- a/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_wp.ini b/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_wp.ini
index d16523e2..101d1578 100644
--- a/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg12pxxxf512_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 2048 ; Size of individually erasable block, in bytes: 2 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000107 ; Area ID: HWM_EFR32_512K_SP_2 | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_app.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_app.ini
index 4008b1c9..b14f3a68 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_wp.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_wp.ini
index debea180..3f2761b9 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf1024_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 8192 ; Size of individually erasable block, in bytes: 8 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x1000010A ; Area ID: HW_VARIANT_ID=0A | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_app.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_app.ini
index 6aa013fb..bc1a3696 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_wp.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_wp.ini
index e7105dff..c36d6ad1 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf512_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 8192 ; Size of individually erasable block, in bytes: 8 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x1000010C ; Area ID: HW_VARIANT_ID=0C | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_app.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_app.ini
index f9e10e20..aace3349 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_wp.ini b/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_wp.ini
index 2a775003..3a747e7b 100644
--- a/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg21xxxxf768_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 8192 ; Size of individually erasable block, in bytes: 8 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x1000010D ; Area ID: HW_VARIANT_ID=0D | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_app.ini b/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_app.ini
index 1c6b2c3c..92bc74ff 100644
--- a/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_wp.ini b/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_wp.ini
index 0b2d7a48..9e4a7222 100644
--- a/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg22xxxxf512_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 8192 ; Size of individually erasable block, in bytes: 8 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x1000010B ; Area ID: HWM_EFR32XG22 | 0x10000100
diff --git a/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_app.ini b/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_app.ini
index 19cffad8..532e0a5c 100644
--- a/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_app.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_wp.ini b/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_wp.ini
index 73d78293..ad2f27d6 100644
--- a/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_wp.ini
+++ b/mcu/efr/efr32/ini_files/efr32xg23xxxxf512_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 8192 ; Size of individually erasable block, in bytes: 8 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000113 ; Area ID: HW_VARIANT_ID=13 | 0x10000100
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf1024.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf1024.ld
index 01497a6b..788fae75 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf1024.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf1024.ld
@@ -63,6 +63,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -79,6 +80,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf512.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf512.ld
index 423cffb3..28d9a6f0 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf512.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg12pxxxf512.ld
@@ -63,6 +63,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -79,6 +80,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf1024.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf1024.ld
index fb7c6709..166c6c08 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf1024.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf1024.ld
@@ -62,6 +62,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -78,6 +79,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf512.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf512.ld
index 98da469e..f88b234a 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf512.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf512.ld
@@ -62,6 +62,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -78,6 +79,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf768.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf768.ld
index 764afca1..be50c214 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf768.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg21xxxxf768.ld
@@ -62,6 +62,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -78,6 +79,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg22xxxxf512.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg22xxxxf512.ld
index c3c49595..89435aa5 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg22xxxxf512.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg22xxxxf512.ld
@@ -22,8 +22,8 @@ MEMORY
{
BOOTLOADER (rx) : ORIGIN = 0x00000000, LENGTH = 16K - 1K
BLCONFIG (rx) : ORIGIN = 0x00000000 + 15K, LENGTH = 1K
- BL_STATIC (rwx) : ORIGIN = 0x20000000 + 24, LENGTH = 512 - 24
- RAM (rwx) : ORIGIN = 0x20000000 + 512, LENGTH = 32K - 512
+ BL_STATIC (rwx) : ORIGIN = 0x20000000 + 24, LENGTH = 1K - 24
+ RAM (rwx) : ORIGIN = 0x20000000 + 1K, LENGTH = 32K - 1K
INVALID (rwx) : ORIGIN = 0xFFFFFFFF, LENGTH = 0
}
@@ -62,6 +62,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -78,6 +79,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/efr/efr32/linker/gcc_bl_efr32xg23xxxxf512.ld b/mcu/efr/efr32/linker/gcc_bl_efr32xg23xxxxf512.ld
index 969b3af2..18820e6a 100644
--- a/mcu/efr/efr32/linker/gcc_bl_efr32xg23xxxxf512.ld
+++ b/mcu/efr/efr32/linker/gcc_bl_efr32xg23xxxxf512.ld
@@ -62,6 +62,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -78,6 +79,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/hal_api/button.h b/mcu/hal_api/button/button.h
similarity index 88%
rename from mcu/hal_api/button.h
rename to mcu/hal_api/button/button.h
index 33ea6e9e..7dc73028 100644
--- a/mcu/hal_api/button.h
+++ b/mcu/hal_api/button/button.h
@@ -8,6 +8,10 @@
* \file button.h
* \brief Board-independent button functions
*/
+
+#ifndef BUTTON_H_
+#define BUTTON_H_
+
#include
#include
@@ -28,6 +32,10 @@ typedef enum
BUTTON_RES_OK = 0,
/** Button id is invalid */
BUTTON_RES_INVALID_ID = 1,
+ /** Function parameter is invalid */
+ BUTTON_RES_INVALID_PARAM = 2,
+ /** Button initialization has not been performed */
+ BUTTON_RES_UNINITIALIZED = 3
} button_res_e;
/**
@@ -75,3 +83,5 @@ button_res_e Button_getState(uint8_t button_id,
* \brief Get number of buttons
*/
uint8_t Button_get_number(void);
+
+#endif /* BUTTON_H_ */
diff --git a/mcu/hal_api/gpio/gpio.h b/mcu/hal_api/gpio/gpio.h
new file mode 100644
index 00000000..6d9f7aee
--- /dev/null
+++ b/mcu/hal_api/gpio/gpio.h
@@ -0,0 +1,237 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file gpio.h
+ * \brief Board-independent GPIO functions.
+ */
+
+#ifndef GPIO_H_
+#define GPIO_H_
+
+#include
+
+/** \brief GPIO identification number */
+typedef uint8_t gpio_id_t;
+
+/** \brief GPIO port number */
+typedef uint8_t gpio_port_t;
+
+/** \brief GPIO pin number */
+typedef uint8_t gpio_pin_t;
+
+/** \brief List of return code */
+typedef enum
+{
+ /** Operation is successful */
+ GPIO_RES_OK = 0,
+ /** GPIO iniatialization has not been performed */
+ GPIO_RES_UNINITIALIZED = 1,
+ /** GPIO HAL is not implemented. Weak definitions are used instead */
+ GPIO_RES_NOT_IMPLEMENTED = 2,
+ /** Invalid parameter(s) */
+ GPIO_RES_INVALID_PARAM = 3,
+ /** Invalid pin number */
+ GPIO_RES_INVALID_PIN = 4,
+ /** Invalid GPIO direction */
+ GPIO_RES_INVALID_DIRECTION = 5,
+ /** No free external interrupt: all of them are already in use. Note: Only used on SiLabs/EFR32 boards */
+ GPIO_RES_NO_FREE_IT = 6
+} gpio_res_e;
+
+/** \brief GPIO logical level */
+typedef enum
+{
+ /** The GPIO is low */
+ GPIO_LEVEL_LOW,
+ /** The GPIO is high */
+ GPIO_LEVEL_HIGH
+} gpio_level_e;
+
+/**
+ * \brief GPIO pull configuration
+ * \note Used for input GPIOs
+ */
+typedef enum
+{
+ /** input disabled */
+ GPIO_IN_DISABLED,
+ /** No pull (floating if no external pull-up or pull-down) */
+ GPIO_IN_PULL_NONE,
+ /** Pull-down */
+ GPIO_IN_PULL_DOWN,
+ /** Pull-up */
+ GPIO_IN_PULL_UP
+} gpio_in_mode_cfg_e;
+
+/**
+ * \brief GPIO operating mode configuration
+ * \note Used for output GPIOs
+ */
+typedef enum
+{
+ /** Push-pull */
+ GPIO_OUT_MODE_PUSH_PULL,
+ /** Open-drain */
+ GPIO_OUT_MODE_OPEN_DRAIN,
+ /** Open-drain with pull-up */
+ GPIO_OUT_MODE_OPEN_DRAIN_WITH_PULL_UP
+} gpio_out_mode_cfg_e;
+
+/**
+ * \brief GPIO event.
+ * \note Used for input GPIOs
+ */
+typedef enum
+{
+ /** No event */
+ GPIO_IN_EVENT_NONE = 0,
+ /** Rising edge event */
+ GPIO_IN_EVENT_RISING_EDGE = 1U << 0U,
+ /** Falling edge event */
+ GPIO_IN_EVENT_FALLING_EDGE = 1U << 1U,
+} gpio_in_event_e;
+
+/** \brief Check if event has its rising edge bit set */
+#define IS_RISING_EDGE(event) ((event & GPIO_IN_EVENT_RISING_EDGE) == GPIO_IN_EVENT_RISING_EDGE)
+/** \brief Check if event has its falling edge bit set */
+#define IS_FALLING_EDGE(event) ((event & GPIO_IN_EVENT_FALLING_EDGE) == GPIO_IN_EVENT_FALLING_EDGE)
+
+/**
+ * \brief Callback structure for a GPIO event
+ * \param id
+ * Id of the GPIO which raised the event
+ * \param event
+ * Event raised
+ */
+typedef void (*gpio_in_event_cb_f)(gpio_id_t id, gpio_in_event_e event);
+
+/** \brief GPIO input configuration */
+typedef struct
+{
+ /** Callback called on GPIO events */
+ gpio_in_event_cb_f event_cb;
+ /**
+ * Event configuration.
+ * Use | (OR) operator to detect both rising and falling edges.
+ * e.g.: .event_cfg = (GPIO_IN_EVENT_RISING_EDGE | GPIO_IN_EVENT_FALLING_EDGE)
+ */
+ gpio_in_event_e event_cfg : 2;
+ /** Pull configuration (e.g.: Pull-down) */
+ gpio_in_mode_cfg_e in_mode_cfg : 2;
+} gpio_in_cfg_t;
+
+/** \brief GPIO output configuration */
+typedef struct
+{
+ /** Operating mode configuration (e.g.: Push-pull) */
+ gpio_out_mode_cfg_e out_mode_cfg : 2;
+ /** GPIO default logical level (e.g.: Low) */
+ gpio_level_e level_default : 1;
+} gpio_out_cfg_t;
+
+/**
+ * \brief Initialize GPIO module
+ *
+ * Example on use:
+ * @code
+ * void App_init(const app_global_functions_t * functions)
+ * {
+ * ...
+ * // Set up GPIOs first
+ * Gpio_init();
+ * ...
+ * Gpio_inputSetCfg(GPIO_INPUT_ID, &in_cfg);
+ * ...
+ * Gpio_outputSetCfg(GPIO_OUTPUT_ID, &out_cfg);
+ * ...
+ * }
+ * @endcode
+ */
+gpio_res_e Gpio_init(void);
+
+/**
+ * \brief Configure a GPIO as an input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] in_cfg
+ * GPIO input configuration
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_inputSetCfg(gpio_id_t id, const gpio_in_cfg_t *in_cfg);
+
+/**
+ * \brief Read the GPIO input level
+ * \note The GPIO should be configured as an input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[out] level
+ * Returned GPIO level (low or high)
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_inputRead(gpio_id_t id, gpio_level_e *level);
+
+/**
+ * \brief Configure a GPIO as an output GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] out_cfg
+ * GPIO output configuration
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_outputSetCfg(gpio_id_t id, const gpio_out_cfg_t *out_cfg);
+
+/**
+ * \brief Write GPIO output level
+ * \note The GPIO should be configured as an output GPIO
+ * \param id
+ * Id of the GPIO
+ * \param level
+ * GPIO level (low or high) to write
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_outputWrite(gpio_id_t id, gpio_level_e level);
+
+/**
+ * \brief Toggle GPIO output level
+ * \note The GPIO should be configured as an output GPIO
+ * \param id
+ * Id of the GPIO
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_outputToggle(gpio_id_t id);
+
+/**
+ * \brief Read the GPIO output level
+ * \note The GPIO should be configured as an output GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[out] level
+ * Returned GPIO level (low or high)
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_outputRead(gpio_id_t id, gpio_level_e *level);
+
+/**
+ * \brief Get the GPIO port and pin numbers of the given GPIO id
+ * \param id
+ * Id of the GPIO
+ * \param[out] port
+ * Returned GPIO port number
+ * \param[out] pin
+ * Returned GPIO pin number
+ *
+ * \return Return code of operation
+ */
+gpio_res_e Gpio_getPin(gpio_id_t id, gpio_port_t *port, gpio_pin_t *pin);
+
+/**
+ * \brief Get the number of GPIOs
+ * \return Number of GPIOs
+ */
+uint8_t Gpio_getNumber(void);
+
+#endif /* GPIO_H_ */
diff --git a/mcu/hal_api/hal_init.c b/mcu/hal_api/hal_init.c
new file mode 100644
index 00000000..5714987a
--- /dev/null
+++ b/mcu/hal_api/hal_init.c
@@ -0,0 +1,37 @@
+/* Copyright 2021 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+#include "hal_init.h"
+
+// HAL drivers are considered in use if their associated interface (.h)
+// file is in the include list. It could be done with a dedicated C flag
+// but it would have the same effect
+
+#if __has_include("gpio.h")
+#include "gpio.h"
+#endif
+
+#if __has_include("button.h")
+#include "button.h"
+#endif
+
+#if __has_include("led.h")
+#include "led.h"
+#endif
+
+void Hal_init(void)
+{
+#if __has_include("gpio.h")
+ Gpio_init();
+#endif
+
+#if __has_include("button.h")
+ Button_init();
+#endif
+
+#if __has_include("led.h")
+ Led_init();
+#endif
+}
diff --git a/mcu/hal_api/hal_init.h b/mcu/hal_api/hal_init.h
new file mode 100644
index 00000000..25b38798
--- /dev/null
+++ b/mcu/hal_api/hal_init.h
@@ -0,0 +1,15 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+#ifndef HAL_INIT_H_
+#define HAL_INIT_H_
+
+/**
+ * \brief HAL drivers initialization
+ */
+void Hal_init(void);
+
+#endif /* HAL_INIT_H_ */
diff --git a/mcu/hal_api/led.h b/mcu/hal_api/led/led.h
similarity index 92%
rename from mcu/hal_api/led.h
rename to mcu/hal_api/led/led.h
index cdfce138..b5714039 100644
--- a/mcu/hal_api/led.h
+++ b/mcu/hal_api/led/led.h
@@ -8,6 +8,10 @@
* \file led.h
* \brief Board-independent LED functions
*/
+
+#ifndef LED_H_
+#define LED_H_
+
#include
#include
@@ -20,6 +24,8 @@ typedef enum
LED_RES_OK = 0,
/** Led id is invalid */
LED_RES_INVALID_ID = 1,
+ /** LED iniatialization has not been performed */
+ LED_RES_UNINITIALIZED = 2
} led_res_e;
/**
@@ -87,3 +93,5 @@ led_res_e Led_toggle(uint8_t led_id);
* \return The number of leds available
*/
uint8_t Led_getNumber(void);
+
+#endif /* LED_H_ */
diff --git a/mcu/hal_api/makefile b/mcu/hal_api/makefile
index 2ef6c81d..c3639dcb 100644
--- a/mcu/hal_api/makefile
+++ b/mcu/hal_api/makefile
@@ -1,6 +1,18 @@
-CFLAGS += -I$(HAL_API_PATH)
+INCLUDES += -I$(HAL_API_PATH)
+
+SRCS += $(HAL_API_PATH)hal_init.c
# include drivers
-#MCU_PREFIX := $(MCU_PATH)$(MCU_FAMILY)/$(MCU)/
-#include $(MCU_PREFIX)hal/makefile
-include $(MCU_PATH)$(MCU_FAMILY)/makefile
\ No newline at end of file
+include $(MCU_PATH)$(MCU_FAMILY)/makefile
+
+ifeq ($(HAL_BUTTON), yes)
+INCLUDES += -I$(HAL_API_PATH)button
+endif
+
+ifeq ($(HAL_LED), yes)
+INCLUDES += -I$(HAL_API_PATH)led
+endif
+
+ifeq ($(HAL_GPIO), yes)
+INCLUDES += -I$(HAL_API_PATH)gpio
+endif
diff --git a/mcu/hal_api/spi.h b/mcu/hal_api/spi.h
index ef505bb2..6e7c1b8f 100644
--- a/mcu/hal_api/spi.h
+++ b/mcu/hal_api/spi.h
@@ -42,9 +42,9 @@ typedef struct
typedef struct
{
uint8_t * write_ptr; //< Pointer to bytes to write (Must be NULL for pure read)
- uint8_t write_size; //< Number of bytes to write (Must be 0 for pure read)
+ size_t write_size; //< Number of bytes to write (Must be 0 for pure read)
uint8_t * read_ptr; //< Pointer to store bytes to read (Must be NULL for pure write)
- uint8_t read_size; //< Number of bytes to read (Must be 0 for pure write)
+ size_t read_size; //< Number of bytes to read (Must be 0 for pure write)
uint32_t custom; //< Custom param (can be used to implement state machine)
} spi_xfer_t;
diff --git a/mcu/nrf/common/hal/button.c b/mcu/nrf/common/hal/button.c
deleted file mode 100644
index ef2ec5d9..00000000
--- a/mcu/nrf/common/hal/button.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* Copyright 2018 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file button.c
- * \brief Board-specific button module for nrf52
- */
-
-#include "button.h"
-#include "mcu.h"
-#include "board.h"
-#include "api.h"
-
-
-#ifdef BOARD_BUTTON_PIN_LIST
-
-/*
- * The selected board has buttons
- */
-
-#ifndef BOARD_DEBOUNCE_TIME_MS
-/** \brief Debounce time of button in ms. It can be overwritten from board.h */
-#define BOARD_DEBOUNCE_TIME_MS 100
-#endif
-
-#ifndef BOARD_BUTTON_ACTIVE_LOW
-/** \brief Is button active low. It can be overwritten from board.h */
-#define BOARD_BUTTON_ACTIVE_LOW true
-#endif
-
-#ifndef BOARD_BUTTON_INTERNAL_PULL
-/** \brief Does the driver needs to activate internal pull-up/down.
- * If true; pull-up (down) is enabled if BOARD_BUTTON_ACTIVE_LOW is
- * true (false). It can be overwritten from board.h
- */
-#define BOARD_BUTTON_INTERNAL_PULL true
-#endif
-
-/** \brief Each button use a GPIOTE channel Define first one */
-#define GPIOTE_START_CHANNEL 0
-
-/** \brief Board-dependent Button number to pin mapping */
-static const uint8_t pin_map[] = BOARD_BUTTON_PIN_LIST;
-
-/** \brief Compute number of button on the board */
-#define BOARD_BUTTON_NUMBER (sizeof(pin_map) / sizeof(pin_map[0]))
-
-static void gpiote_interrupt_handler(void);
-
-typedef enum
-{
- NO_INTERRUPT,
- ON_PRESSED_ONLY,
- ON_RELEASED_ONLY,
- ON_PRESSED_AND_RELEASED
-} button_interrupt_type_e;
-
-typedef struct
-{
- // Callback when button pressed
- on_button_event_cb on_pressed;
- // Callback when button released
- on_button_event_cb on_released;
- // Used for debounce
- app_lib_time_timestamp_hp_t last_button_event;
- uint8_t gpio;
- uint8_t channel;
- bool active_low;
-} button_internal_t;
-
-/** \brief Table to manage the button list */
-static button_internal_t m_button_conf[BOARD_BUTTON_NUMBER];
-
-/* Button events and sense truth table
- *
- * Type : interrupt type see button_interrupt_type_e
- * N:No_it, P:pressed_only, R:released_only, PR:pressed&released
- * act_low: Button is active low
- * Pin: IO state (Low or High)
- * Sense: Value to configure in sense register
- *
- * Type | act_low | Pin | Sense
- * N | X | X | Disabled
- *
- * P | Y | X | Low
- * P | N | X | High
- *
- * R | Y | X | High
- * R | N | X | Low
- *
- * PR | X | H | Low
- * PR | X | L | Low
- *
- */
-static void button_enable_interrupt(uint8_t button_id,
- button_interrupt_type_e type)
-{
- bool is_sense_low = false;
-
- switch(type)
- {
- case NO_INTERRUPT:
- {
- //Disable SENSE
- NRF_GPIO->PIN_CNF[m_button_conf[button_id].gpio] = 0;
- NRF_GPIO->LATCH = 1 << m_button_conf[button_id].gpio;
-
- // Check if port IRQ must be masked
- for (uint8_t i = 0; i < BOARD_BUTTON_NUMBER; i++)
- {
- if (m_button_conf[i].on_pressed ||
- m_button_conf[i].on_released)
- {
- // At least one line still enabled
- return;
- }
- }
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENCLR_PORT_Msk;
- return;
- }
- case ON_PRESSED_ONLY:
- {
- is_sense_low = m_button_conf[button_id].active_low;
- break;
- }
- case ON_RELEASED_ONLY:
- {
- is_sense_low = !m_button_conf[button_id].active_low;
- break;
- }
- case ON_PRESSED_AND_RELEASED:
- {
- is_sense_low =
- nrf_gpio_pin_read(m_button_conf[button_id].gpio) == 0 ?
- false : true;
- break;
- }
- }
-
- // Configure interrupt (type != NO_INTERRUPT)
-
- //Disable IRQ
- NRF_GPIO->PIN_CNF[m_button_conf[button_id].gpio] &=
- ~(GPIO_PIN_CNF_SENSE_Msk);
-
- if(is_sense_low)
- {
- NRF_GPIO->PIN_CNF[m_button_conf[button_id].gpio] |=
- (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos);
- }
- else
- {
- NRF_GPIO->PIN_CNF[m_button_conf[button_id].gpio] |=
- (GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos);
- }
- // Clear the line before enabling IRQ
- NRF_GPIO->LATCH = 1 << m_button_conf[button_id].gpio;
- NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
-}
-
-void Button_init(void)
-{
- app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
-
- for (uint8_t i = 0; i < BOARD_BUTTON_NUMBER; i ++)
- {
- m_button_conf[i].gpio = pin_map[i];
- m_button_conf[i].channel = GPIOTE_START_CHANNEL + i;
- m_button_conf[i].on_pressed = NULL;
- m_button_conf[i].on_released = NULL;
- m_button_conf[i].last_button_event = now;
- m_button_conf[i].active_low = BOARD_BUTTON_ACTIVE_LOW;
-
- // Enable the Pull-Up/Down on Buttons (Input; Pull; SENSE:Disabled)
- if (BOARD_BUTTON_INTERNAL_PULL)
- {
- uint32_t pull;
-
- if (BOARD_BUTTON_ACTIVE_LOW)
- {
- pull = (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos);
- }
- else
- {
- pull = (GPIO_PIN_CNF_PULL_Pulldown << GPIO_PIN_CNF_PULL_Pos);
- }
- NRF_GPIO->PIN_CNF[m_button_conf[i].gpio] = pull;
- }
- else
- {
- // Default config (Input; No Pull; SENSE:Disabled).
- NRF_GPIO->PIN_CNF[m_button_conf[i].gpio] = 0;
- }
- }
-
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENCLR_PORT_Msk;
- NRF_GPIOTE->EVENTS_PORT = 0;
-
- // Enable interrupt
- lib_system->clearPendingFastAppIrq(GPIOTE_IRQn);
- lib_system->enableAppIrq(true,
- GPIOTE_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_LO,
- gpiote_interrupt_handler);
-}
-
-button_res_e Button_getState(uint8_t button_id, bool * state_p)
-{
- if (button_id >= BOARD_BUTTON_NUMBER)
- {
- // Invalid button number, just answer not pressed
- return BUTTON_RES_INVALID_ID;
- }
-
- *state_p = ((nrf_gpio_pin_read(m_button_conf[button_id].gpio) != 0)
- != m_button_conf[button_id].active_low);
-
- return BUTTON_RES_OK;
-}
-
-button_res_e Button_register_for_event(uint8_t button_id,
- button_event_e event,
- on_button_event_cb cb)
-{
- button_interrupt_type_e type;
-
- if ((button_id >= BOARD_BUTTON_NUMBER)
- || (event != BUTTON_PRESSED && event != BUTTON_RELEASED ))
- {
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
- }
-
- Sys_enterCriticalSection();
-
- if (event == BUTTON_PRESSED)
- {
- m_button_conf[button_id].on_pressed = cb;
- }
- else
- {
- m_button_conf[button_id].on_released = cb;
- }
-
- if (m_button_conf[button_id].on_pressed &&
- m_button_conf[button_id].on_released)
- {
- type = ON_PRESSED_AND_RELEASED;
- }
- else if (m_button_conf[button_id].on_pressed)
- {
- type = ON_PRESSED_ONLY;
- }
- else if (m_button_conf[button_id].on_released)
- {
- type = ON_RELEASED_ONLY;
- }
- else
- {
- type = NO_INTERRUPT;
- }
-
- button_enable_interrupt(button_id, type);
-
- Sys_exitCriticalSection();
-
- return BUTTON_RES_OK;
-}
-
-uint8_t Button_get_number(void)
-{
- return BOARD_BUTTON_NUMBER;
-}
-
-static void gpiote_interrupt_handler(void)
-{
- app_lib_time_timestamp_hp_t now = lib_time->getTimestampHp();
-
- if (NRF_GPIOTE->EVENTS_PORT == 0)
- {
- return;
- }
-
- NRF_GPIOTE->EVENTS_PORT = 0;
- // read any event from peripheral to flush the write buffer:
- EVENT_READBACK = NRF_GPIOTE->EVENTS_PORT;
-
- // Check all possible sources
- for (uint8_t i = 0; i < BOARD_BUTTON_NUMBER; i ++)
- {
- uint8_t pin = m_button_conf[i].gpio;
- if (NRF_GPIO->LATCH & (1 << pin))
- {
- if (lib_time->getTimeDiffUs(now,
- m_button_conf[i].last_button_event)
- > (BOARD_DEBOUNCE_TIME_MS * 1000))
- {
- bool pressed;
- Button_getState(i, &pressed);
- m_button_conf[i].last_button_event = now;
-
- if (m_button_conf[i].on_pressed && pressed)
- {
- // Call callback
- m_button_conf[i].on_pressed(i, BUTTON_PRESSED);
- }
- else if (m_button_conf[i].on_released && !pressed)
- {
- //Call callback
- m_button_conf[i].on_released(i, BUTTON_RELEASED);
- }
-
- // Change SENSE polarity
- if (m_button_conf[i].on_pressed &&
- m_button_conf[i].on_released)
- {
- NRF_GPIO->PIN_CNF[pin] &= ~(GPIO_PIN_CNF_SENSE_Msk);
- if (nrf_gpio_pin_read(pin) == 0)
- {
- NRF_GPIO->PIN_CNF[pin] |=
- (GPIO_PIN_CNF_SENSE_High << GPIO_PIN_CNF_SENSE_Pos);
- }
- else
- {
- NRF_GPIO->PIN_CNF[pin] |=
- (GPIO_PIN_CNF_SENSE_Low << GPIO_PIN_CNF_SENSE_Pos);
- }
- }
- }
- // Clear the line
- NRF_GPIO->LATCH = 1 << pin;
- }
- }
-}
-
-#else // BOARD_BUTTON_PIN_LIST
-
-/*
- * The selected board has no buttons
- *
- * As some example apps support such boards but also provide extra features
- * when a board has buttons, the button driver has this dummy implementation
- * to simplify the build process.
- */
-
-void Button_init(void)
-{
- // Do nothing
-}
-
-button_res_e Button_getState(uint8_t button_id, bool * state_p)
-{
- (void) button_id;
- *state_p = false;
-
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
-}
-
-uint8_t Button_get_number(void)
-{
- return 0;
-}
-
-button_res_e Button_register_for_event(uint8_t button_id,
- button_event_e event,
- on_button_event_cb cb)
-{
- (void) button_id;
- (void) event;
- (void) cb;
-
- // Invalid button number
- return BUTTON_RES_INVALID_ID;
-}
-
-#endif // BOARD_BUTTON_PIN_LIST
diff --git a/mcu/nrf/common/hal/gpio.c b/mcu/nrf/common/hal/gpio.c
new file mode 100644
index 00000000..51d60ab0
--- /dev/null
+++ b/mcu/nrf/common/hal/gpio.c
@@ -0,0 +1,522 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file gpio.c
+ * \brief Board-specific GPIO functions for nrf52.
+ * \attention Should be compatible with the gpio.h interface.
+ */
+
+#include "gpio.h"
+#include "mcu.h"
+#include "board.h"
+#include "api.h"
+
+/*
+ * If some GPIOs are mapped
+ *
+ * Note:
+ * If BOARD_GPIO_PIN_LIST is not defined,
+ * then the dummy functions defined in the gpio_weak.c file will be used instead
+ */
+#ifdef BOARD_GPIO_PIN_LIST
+
+/** \brief GPIO direction */
+typedef enum
+{
+ /** input direction */
+ DIR_INPUT,
+ /** output direction */
+ DIR_OUTPUT
+} direction_e;
+
+/** \brief GPIO internal configuration */
+typedef struct
+{
+ /** GPIO direction (either input or output) */
+ direction_e direction : 1;
+ /** Callback called on GPIO events */
+ gpio_in_event_e event_cfg : 2;
+} gpio_cfg_intern_t;
+
+/** \brief GPIO id to GPIO pin map (array index: GPIO id ; array value: GPIO pin) */
+static const gpio_pin_t m_id_to_pin_map[] = BOARD_GPIO_PIN_LIST;
+
+/** \brief Compute number of GPIOs that are mapped (= total number of used GPIOs) */
+#define BOARD_GPIO_NUMBER (sizeof(m_id_to_pin_map) / sizeof(m_id_to_pin_map[0]))
+
+/** \brief GPIO id to GPIO internal config map (array index: GPIO id ; array value: GPIO internal config) */
+static gpio_cfg_intern_t m_id_to_cfg_map[BOARD_GPIO_NUMBER];
+
+/** \brief GPIO id to GPIO event callback map (array index: GPIO id ; array value: GPIO event callback) */
+static gpio_in_event_cb_f m_id_to_event_cb_map[BOARD_GPIO_NUMBER];
+
+/** \brief Has the library been initialized */
+static bool m_initialized = false;
+
+/**
+ * \brief Check if the pin numbers of the mapped GPIOs are valid (if they exist on the MCU)
+ * \return True if all the pin numbers are valid ; False otherwise
+ */
+static bool check_pins(void);
+
+/**
+ * \brief Configure mode (e.g.: pull-down) of input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] in_cfg
+ * GPIO input configuration
+ */
+static void input_set_cfg_mode(gpio_id_t id, const gpio_in_cfg_t *in_cfg);
+
+/**
+ * \brief Configure interrupt of input GPIO
+ * \param id
+ * Id of the GPIO
+ * \param[in] in_cfg
+ * GPIO input configuration
+ */
+static void input_set_cfg_irq(gpio_id_t id, const gpio_in_cfg_t *in_cfg);
+
+/** \brief Initialize GPIOs interrupts */
+static void input_init_irq(void);
+
+/**
+ * \brief Check if any of the GPIO "SENSE" is enabled
+ * \return True if any of the GPIO "SENSE" is enabled ; False otherwise
+ */
+static bool any_sense_enabled(void);
+
+/** \brief function called when a GPIO interrupt is raised. Used to generate the appropriate GPIO event */
+static void gpio_event_handle(void);
+
+gpio_res_e Gpio_init(void)
+{
+ gpio_id_t id;
+ const gpio_in_cfg_t in_cfg =
+ {
+ .event_cb = NULL,
+ .event_cfg = GPIO_IN_EVENT_NONE,
+ .in_mode_cfg = GPIO_IN_DISABLED
+ };
+
+ if (m_initialized)
+ {
+ /* return if GPIO initialization has already been performed */
+ return GPIO_RES_OK;
+ }
+ if (!check_pins())
+ {
+ return GPIO_RES_INVALID_PIN;
+ }
+
+ Sys_enterCriticalSection();
+
+ /* Configure each mapped GPIOs to a default configuration */
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ input_set_cfg_mode(id, &in_cfg);
+ input_set_cfg_irq(id, &in_cfg);
+ /* Store direction and part of configuration that is used internally */
+ m_id_to_event_cb_map[id] = in_cfg.event_cb;
+ m_id_to_cfg_map[id].direction = DIR_INPUT;
+ m_id_to_cfg_map[id].event_cfg = in_cfg.event_cfg;
+ }
+ input_init_irq();
+
+ Sys_exitCriticalSection();
+
+ m_initialized = true;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_inputSetCfg(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || in_cfg == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ Sys_enterCriticalSection();
+
+ input_set_cfg_mode(id, in_cfg);
+ input_set_cfg_irq(id, in_cfg);
+ /* Store direction and part of configuration that is used internally */
+ m_id_to_event_cb_map[id] = in_cfg->event_cb;
+ m_id_to_cfg_map[id].direction = DIR_INPUT;
+ m_id_to_cfg_map[id].event_cfg = in_cfg->event_cfg;
+
+ Sys_exitCriticalSection();
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_inputRead(gpio_id_t id, gpio_level_e *level)
+{
+ gpio_pin_t pin;
+ bool read_val;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || level == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_INPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, NULL, &pin);
+ read_val = (nrf_gpio_pin_read(pin) != 0);
+ *level = read_val ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputSetCfg(gpio_id_t id, const gpio_out_cfg_t *out_cfg)
+{
+ nrf_gpio_pin_pull_t pull;
+ nrf_gpio_pin_drive_t drive;
+ gpio_pin_t pin;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || out_cfg == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ /*
+ * convert board independant operating mode enum,
+ * to board specific operating mode enum
+ */
+ switch (out_cfg->out_mode_cfg)
+ {
+ case GPIO_OUT_MODE_PUSH_PULL:
+ drive = NRF_GPIO_PIN_S0S1;
+ pull = NRF_GPIO_PIN_NOPULL;
+ break;
+ case GPIO_OUT_MODE_OPEN_DRAIN:
+ drive = NRF_GPIO_PIN_S0D1;
+ pull = NRF_GPIO_PIN_NOPULL;
+ break;
+ case GPIO_OUT_MODE_OPEN_DRAIN_WITH_PULL_UP:
+ drive = NRF_GPIO_PIN_S0D1;
+ pull = NRF_GPIO_PIN_PULLUP;
+ break;
+ default:
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ Sys_enterCriticalSection();
+
+ Gpio_getPin(id, NULL, &pin);
+ nrf_gpio_cfg(pin,
+ NRF_GPIO_PIN_DIR_OUTPUT,
+ NRF_GPIO_PIN_INPUT_DISCONNECT,
+ pull,
+ drive,
+ NRF_GPIO_PIN_NOSENSE);
+ /* Set pin default state */
+ nrf_gpio_pin_write(pin, (out_cfg->level_default != GPIO_LEVEL_LOW));
+ /* Store direction */
+ m_id_to_cfg_map[id].direction = DIR_OUTPUT;
+
+ Sys_exitCriticalSection();
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputWrite(gpio_id_t id, gpio_level_e level)
+{
+ gpio_pin_t pin;
+ bool write_val;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, NULL, &pin);
+ write_val = (level != GPIO_LEVEL_LOW);
+ nrf_gpio_pin_write(pin, write_val);
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputToggle(gpio_id_t id)
+{
+ gpio_pin_t pin;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, NULL, &pin);
+ nrf_gpio_pin_toggle(pin);
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_outputRead(gpio_id_t id, gpio_level_e *level)
+{
+ gpio_pin_t pin;
+ bool read_val;
+
+ if (!m_initialized)
+ {
+ return GPIO_RES_UNINITIALIZED;
+ }
+ if (id >= BOARD_GPIO_NUMBER || level == NULL)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+ if (m_id_to_cfg_map[id].direction != DIR_OUTPUT)
+ {
+ return GPIO_RES_INVALID_DIRECTION;
+ }
+
+ Gpio_getPin(id, NULL, &pin);
+ read_val = nrf_gpio_pin_out_read(pin) != 0;
+ *level = read_val ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW;
+
+ return GPIO_RES_OK;
+}
+
+gpio_res_e Gpio_getPin(gpio_id_t id, gpio_port_t *port, gpio_pin_t *pin)
+{
+ if (id >= BOARD_GPIO_NUMBER)
+ {
+ return GPIO_RES_INVALID_PARAM;
+ }
+
+ if (port)
+ {
+ /*
+ * With NRF chips, all the information is stored in pin.
+ * Thus port is always set to 0 and it can be ignored.
+ */
+ *port = 0;
+ }
+ if (pin)
+ {
+ *pin = m_id_to_pin_map[id];
+ }
+
+ return GPIO_RES_OK;
+}
+
+uint8_t Gpio_getNumber(void)
+{
+ return BOARD_GPIO_NUMBER;
+}
+
+static bool check_pins(void)
+{
+ gpio_id_t id;
+ gpio_pin_t pin;
+
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ Gpio_getPin(id, NULL, &pin);
+ if (!nrf_gpio_pin_present_check(pin))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+static void input_set_cfg_mode(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ gpio_pin_t pin;
+ nrf_gpio_pin_pull_t nrf_pin_pull;
+ nrf_gpio_pin_input_t nrf_connect;
+
+ /*
+ * convert board independant mode enum,
+ * to board specific pull enum
+ */
+ switch (in_cfg->in_mode_cfg)
+ {
+ case GPIO_IN_DISABLED:
+ nrf_pin_pull = NRF_GPIO_PIN_NOPULL;
+ nrf_connect = NRF_GPIO_PIN_INPUT_DISCONNECT;
+ break;
+ case GPIO_IN_PULL_NONE:
+ nrf_pin_pull = NRF_GPIO_PIN_NOPULL;
+ nrf_connect = NRF_GPIO_PIN_INPUT_CONNECT;
+ break;
+ case GPIO_IN_PULL_DOWN:
+ nrf_pin_pull = NRF_GPIO_PIN_PULLDOWN;
+ nrf_connect = NRF_GPIO_PIN_INPUT_CONNECT;
+ break;
+ case GPIO_IN_PULL_UP:
+ nrf_pin_pull = NRF_GPIO_PIN_PULLUP;
+ nrf_connect = NRF_GPIO_PIN_INPUT_CONNECT;
+ break;
+ }
+ Gpio_getPin(id, NULL, &pin);
+
+ nrf_gpio_cfg(pin,
+ NRF_GPIO_PIN_DIR_INPUT,
+ nrf_connect,
+ nrf_pin_pull,
+ NRF_GPIO_PIN_S0S1,
+ NRF_GPIO_PIN_NOSENSE);
+}
+
+static void input_set_cfg_irq(gpio_id_t id, const gpio_in_cfg_t *in_cfg)
+{
+ gpio_pin_t pin;
+ nrf_gpio_pin_sense_t sense;
+
+ Gpio_getPin(id, NULL, &pin);
+
+ /* if no event on this GPIO, ... */
+ if (in_cfg->event_cfg == GPIO_IN_EVENT_NONE)
+ {
+ /* ...then disable its sense feature */
+ nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
+ nrf_gpio_pin_latch_clear(pin);
+
+ /* if not a single GPIO uses its sense feature, ... */
+ if(!any_sense_enabled())
+ {
+ /* ...then disable the port interrupt (since it is no longer used by any GPIO) */
+ nrf_gpiote_int_disable(NRF_GPIOTE, GPIOTE_INTENCLR_PORT_Msk);
+ }
+ }
+ /* if event on this GPIO (rising edge, falling edge, or both),... */
+ else
+ {
+ /* ...then read the current pin state and set for next sense to oposit */
+ sense = (nrf_gpio_pin_read(pin)) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
+ nrf_gpio_cfg_sense_set(pin, sense);
+ nrf_gpio_pin_latch_clear(pin);
+ nrf_gpiote_int_enable(NRF_GPIOTE, GPIOTE_INTENCLR_PORT_Msk);
+ }
+}
+
+static void input_init_irq(void)
+{
+ nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
+ nrf_gpiote_int_disable(NRF_GPIOTE, GPIOTE_INTENCLR_PORT_Msk);
+ lib_system->enableAppIrq(true,
+ GPIOTE_IRQn,
+ APP_LIB_SYSTEM_IRQ_PRIO_LO,
+ gpio_event_handle);
+ lib_system->clearPendingFastAppIrq(GPIOTE_IRQn);
+}
+
+static bool any_sense_enabled(void)
+{
+ gpio_id_t id;
+ gpio_pin_t pin;
+ nrf_gpio_pin_sense_t sense;
+
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ Gpio_getPin(id, NULL, &pin);
+ sense = nrf_gpio_pin_sense_get(pin);
+ if (sense != NRF_GPIO_PIN_NOSENSE)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void gpio_event_handle(void)
+{
+ gpio_id_t id;
+ gpio_pin_t pin;
+ gpio_in_event_cb_f event_cb;
+ gpio_in_event_e event_cfg;
+ nrf_gpio_pin_sense_t sense;
+ gpio_in_event_e event;
+
+ /* leave if the port interrupt flag is not set (should not happen) */
+ if (!nrf_gpiote_event_check(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT))
+ {
+ return;
+ }
+
+ /* clear the port interrupt */
+ nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
+
+ /* for each GPIO */
+ for (id = 0; id < BOARD_GPIO_NUMBER; id++)
+ {
+ Gpio_getPin(id, NULL, &pin);
+ /* check if the GPIO latch (= GPIO interrupt flag) is set */
+ if (nrf_gpio_pin_latch_get(pin) != 0)
+ {
+ /* get stored/internal config */
+ event_cb = m_id_to_event_cb_map[id];
+ event_cfg = m_id_to_cfg_map[id].event_cfg;
+
+ sense = nrf_gpio_pin_sense_get(pin);
+ /*
+ * Invoke user handler only if the sensed pin level
+ * matches its polarity configuration.
+ */
+ if (event_cb &&
+ ((IS_RISING_EDGE(event_cfg) && IS_FALLING_EDGE(event_cfg)) ||
+ (sense == NRF_GPIO_PIN_SENSE_HIGH && IS_RISING_EDGE(event_cfg)) ||
+ (sense == NRF_GPIO_PIN_SENSE_LOW && IS_FALLING_EDGE(event_cfg))))
+ {
+ event = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? GPIO_IN_EVENT_RISING_EDGE : GPIO_IN_EVENT_FALLING_EDGE;
+ event_cb(id, event);
+ }
+
+ /*
+ * Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
+ * can be deasserted. Therefore PORT event generated again,
+ * unless some other PINx.DETECT signal is still active.
+ */
+ sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
+ nrf_gpio_cfg_sense_set(pin, sense);
+
+ /*
+ * Try to clear LATCH bit corresponding to currently processed pin.
+ * This may not succeed if the pin's state changed during the interrupt processing
+ * and now it matches the new sense configuration. In such case,
+ * the pin will be processed again in another iteration of the outer loop.
+ */
+ nrf_gpio_pin_latch_clear(pin);
+ }
+ }
+}
+
+#endif // BOARD_GPIO_PIN_LIST
diff --git a/mcu/nrf/common/hal/led.c b/mcu/nrf/common/hal/led.c
deleted file mode 100644
index 0ee11ac6..00000000
--- a/mcu/nrf/common/hal/led.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright 2018 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file led.c
- * \brief Board-specific LED functions for nrf52
- */
-
-#include "led.h"
-#include "mcu.h"
-#include "board.h"
-
-#ifdef BOARD_LED_PIN_LIST
-
-/*
- * The selected board has LEDs
- */
-
-#ifndef BOARD_LED_ACTIVE_LOW
-/** \brief Are LEDs active low. It can be overwritten from board.h */
-#define BOARD_LED_ACTIVE_LOW true
-#endif
-
-/** \brief Board-dependent LED number to pin mapping */
-static const uint8_t pin_map[] = BOARD_LED_PIN_LIST;
-
-/** \brief Compute number of leds on the board */
-#define NUMBER_OF_LEDS (sizeof(pin_map) / sizeof(pin_map[0]))
-
-static void led_configure(uint_fast8_t led_num)
-{
- uint_fast8_t pin_num = pin_map[led_num];
-
- nrf_gpio_cfg_output(pin_num);
-
- // Off by default
-#if BOARD_LED_ACTIVE_LOW
- nrf_gpio_pin_set(pin_num);
-#else // BOARD_LED_ACTIVE_LOW
- nrf_gpio_pin_clear(pin_num);
-#endif // BOARD_LED_ACTIVE_LOW
-}
-
-void Led_init(void)
-{
- for (uint8_t i = 0; i < NUMBER_OF_LEDS; i++)
- {
- // Set up LED GPIO
- led_configure(i);
- }
-}
-
-bool Led_get(uint8_t led_id)
-{
- if (led_id >= (sizeof(pin_map) / sizeof(pin_map[0])))
- {
- return LED_RES_INVALID_ID;
- }
- uint_fast8_t pin_num = pin_map[led_id];
-#if BOARD_LED_ACTIVE_LOW
- return (nrf_gpio_pin_out_read(pin_num) == 0);
-#else //BOARD_LED_ACTIVE_HIGH
- return (nrf_gpio_pin_out_read(pin_num) != 0);
-#endif // BOARD_LED_ACTIVE_LOW
-}
-
-led_res_e Led_set(uint8_t led_id, bool state)
-{
- if (led_id >= (sizeof(pin_map) / sizeof(pin_map[0])))
- {
- return LED_RES_INVALID_ID;
- }
-
- uint_fast8_t pin_num = pin_map[led_id];
-
-#if BOARD_LED_ACTIVE_LOW
- if (state)
- {
- nrf_gpio_pin_clear(pin_num);
- }
- else
- {
- nrf_gpio_pin_set(pin_num);
- }
-#else // BOARD_LED_ACTIVE_LOW
- if (state)
- {
- nrf_gpio_pin_set(pin_num);
- }
- else
- {
- nrf_gpio_pin_clear(pin_num);
- }
-#endif // BOARD_LED_ACTIVE_LOW
-
- return LED_RES_OK;
-}
-
-led_res_e Led_toggle(uint8_t led_id)
-{
- if (led_id >= (sizeof(pin_map) / sizeof(pin_map[0])))
- {
- return LED_RES_INVALID_ID;
- }
-
- uint_fast8_t pin_num = pin_map[led_id];
-
- nrf_gpio_pin_toggle(pin_num);
-
- return LED_RES_OK;
-}
-
-uint8_t Led_getNumber(void)
-{
- return NUMBER_OF_LEDS;
-}
-
-#else // BOARD_LED_PIN_LIST
-
-/*
- * The selected board has no LEDs
- *
- * As some example apps support such boards but also provide extra status
- * information when a board has LEDs, the LED driver has this dummy
- * implementation to simplify the build process.
- */
-
-void Led_init(void)
-{
- // Do nothing
-}
-
-led_res_e Led_set(uint8_t led_id, bool state)
-{
- (void) led_id;
- (void) state;
-
- // Invalid LED number
- return LED_RES_INVALID_ID;
-}
-
-led_res_e Led_toggle(uint8_t led_id)
-{
- (void) led_id;
-
- // Invalid LED number
- return LED_RES_INVALID_ID;
-}
-
-uint8_t Led_getNumber(void)
-{
- return 0;
-}
-
-#endif // BOARD_LED_PIN_LIST
diff --git a/mcu/nrf/common/hal/spi.c b/mcu/nrf/common/hal/spi.c
index d8a22c14..805efd2b 100644
--- a/mcu/nrf/common/hal/spi.c
+++ b/mcu/nrf/common/hal/spi.c
@@ -26,8 +26,20 @@ void __attribute__((__interrupt__)) SPI_IRQHandler(void);
#elif defined(USE_SPI2)
#define SPI_IRQn SPIM2_SPIS2_SPI2_IRQn
#define SPI_DEV NRF_SPIM2
+#elif defined(USE_SPI3)
+#if MCU_SUB == 832
+#error SPI3 is not available on nrf52832
+#endif
+#define SPI_IRQn SPIM3_IRQn
+#define SPI_DEV NRF_SPIM3
#else
-#error USE_SPI0 or USE_SPI1 or USE_SPI2 must be defined
+#error You must specify either USE_SPI0, USE_SPI1, USE_SPI2 or USE_SPI3 (nrf52833 and nrf52840 only) in your board.h
+#endif
+
+#if MCU_SUB == 832
+#define MAX_XFER_SIZE UINT8_MAX
+#else
+#define MAX_XFER_SIZE UINT16_MAX
#endif
/** Is SPI module initialized */
@@ -295,6 +307,13 @@ spi_res_e SPI_transfer(spi_xfer_t * xfer_p,
return SPI_RES_INVALID_XFER;
}
+ // Check transfer size
+ if ((xfer_p->write_size > MAX_XFER_SIZE) || (xfer_p->read_size > MAX_XFER_SIZE))
+ {
+ return SPI_RES_INVALID_XFER;
+ }
+
+
// Enable SPIM module
SPI_DEV->ENABLE =
(SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos);
diff --git a/mcu/nrf/makefile b/mcu/nrf/makefile
index 8fb83080..369601aa 100644
--- a/mcu/nrf/makefile
+++ b/mcu/nrf/makefile
@@ -19,16 +19,12 @@ INCLUDES += -I$(MCU_PATH)$(MCU_FAMILY)/common/
-include $(MCU_PREFIX)hal/makefile
# Build common HAL drivers for nrf-family
-ifeq ($(HAL_SPI), yes)
-SRCS += $(NRF_FAMILY_HAL_PREFIX)spi.c
-endif
-
-ifeq ($(HAL_BUTTON), yes)
-SRCS += $(NRF_FAMILY_HAL_PREFIX)button.c
+ifeq ($(HAL_GPIO), yes)
+SRCS += $(NRF_FAMILY_HAL_PREFIX)gpio.c
endif
-ifeq ($(HAL_LED), yes)
-SRCS += $(NRF_FAMILY_HAL_PREFIX)led.c
+ifeq ($(HAL_SPI), yes)
+SRCS += $(NRF_FAMILY_HAL_PREFIX)spi.c
endif
ifeq ($(HAL_PERSISTENT_MEMORY), yes)
diff --git a/mcu/nrf/nrf52/hal/radio/radio_power_table_nrf52840_4dBm.h b/mcu/nrf/nrf52/hal/radio/radio_power_table_nrf52840_4dBm.h
index 58f221ac..32250f9d 100644
--- a/mcu/nrf/nrf52/hal/radio/radio_power_table_nrf52840_4dBm.h
+++ b/mcu/nrf/nrf52/hal/radio/radio_power_table_nrf52840_4dBm.h
@@ -13,7 +13,7 @@
const app_lib_radio_cfg_power_t power_table_nrf52840_4dBm =
{
.rx_current = 46, // 4.6 mA RX current
- .rx_gain_dbm = 0, // 0 dBm RX gain
+ .rx_gain_db = 0, // 0 dB RX gain
.power_count = 8, // 8 power levels
.powers =
{
diff --git a/mcu/nrf/nrf52/hal/usart.c b/mcu/nrf/nrf52/hal/usart.c
index 5a3234e5..a891f3fd 100644
--- a/mcu/nrf/nrf52/hal/usart.c
+++ b/mcu/nrf/nrf52/hal/usart.c
@@ -43,13 +43,6 @@ void __attribute__((__interrupt__)) UART0_IRQHandler(void);
bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
{
bool ret;
- //uart_tx_pin
- nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
- nrf_gpio_pin_set(BOARD_USART_TX_PIN);
-
- //uart_rx_pin
- nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
- nrf_gpio_pin_set(BOARD_USART_RX_PIN);
/* Module variables */
m_enabled = false;
@@ -58,6 +51,11 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
m_tx_active = false;
/* GPIO init */
+ nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_TX_PIN);
+ nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_RX_PIN);
+
NRF_UART0->PSELTXD = BOARD_USART_TX_PIN;
NRF_UART0->PSELRXD = BOARD_USART_RX_PIN;
NRF_UART0->TASKS_STOPTX = 1;
@@ -324,9 +322,8 @@ static void set_flow_control(bool hw)
/* No parity, no HW flow control */
NRF_UART0->CONFIG = 0;
- // Deactivate HAL_USART_CTS_PIN
+ // Deactivate CTS & RTS pins
nrf_gpio_cfg_default(BOARD_USART_CTS_PIN);
- // Deactivate HAL_USART_RTS_PIN
nrf_gpio_cfg_default(BOARD_USART_RTS_PIN);
}
}
diff --git a/mcu/nrf/nrf52/hal/usart_dma.c b/mcu/nrf/nrf52/hal/usart_dma.c
index 18222387..ca821ad0 100644
--- a/mcu/nrf/nrf52/hal/usart_dma.c
+++ b/mcu/nrf/nrf52/hal/usart_dma.c
@@ -68,13 +68,6 @@ void __attribute__((__interrupt__)) TIMER1_IRQHandler(void);
bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
{
bool ret;
- //uart_tx_pin
- nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
- nrf_gpio_pin_set(BOARD_USART_TX_PIN);
-
- //uart_rx_pin
- nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
- nrf_gpio_pin_set(BOARD_USART_RX_PIN);
/* Module variables */
m_enabled = 0;
@@ -82,6 +75,11 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
m_rx_callback = NULL;
/* GPIO init */
+ nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_TX_PIN);
+ nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_RX_PIN);
+
NRF_UARTE0->PSEL.TXD = BOARD_USART_TX_PIN;
NRF_UARTE0->PSEL.RXD = BOARD_USART_RX_PIN;
NRF_UARTE0->TASKS_STOPTX = 1;
@@ -92,11 +90,9 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
//uart_cts_pin
nrf_gpio_cfg_default(BOARD_USART_CTS_PIN);
nrf_gpio_pin_set(BOARD_USART_CTS_PIN);
-
//uart_rts_pin
nrf_gpio_cfg_default(BOARD_USART_RTS_PIN);
nrf_gpio_pin_set(BOARD_USART_RTS_PIN);
-
/* Set flow control */
set_flow_control(flow_control == UART_FLOW_CONTROL_HW);
#endif
@@ -281,7 +277,6 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
m_rx_callback = rx_callback;
if (m_rx_callback)
{
- /* Enable interrupt */
// Enable RX input
nrf_gpio_cfg(BOARD_USART_RX_PIN,
NRF_GPIO_PIN_DIR_INPUT,
@@ -289,12 +284,9 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_SENSE_LOW);
-
-
}
else
{
- /* Disable interrupt */
// Disable RX input: note autopowering uart will not work either
nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
}
@@ -435,9 +427,8 @@ static void set_flow_control(bool hw)
/* No parity, no HW flow control */
NRF_UARTE0->CONFIG = 0;
- // Deactivate HAL_USART_CTS_PIN
+ // Deactivate CTS & RTS pins
nrf_gpio_cfg_default(BOARD_USART_CTS_PIN);
- // Deactivate HAL_USART_RTS_PIN
nrf_gpio_cfg_default(BOARD_USART_RTS_PIN);
}
}
diff --git a/mcu/nrf/nrf52/ini_files/nrf52832_app.ini b/mcu/nrf/nrf52/ini_files/nrf52832_app.ini
index dc0e9fd4..ac8cea65 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52832_app.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52832_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/nrf/nrf52/ini_files/nrf52832_wp.ini b/mcu/nrf/nrf52/ini_files/nrf52832_wp.ini
index 679b3ae3..281ba951 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52832_wp.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52832_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 4096 ; Size of individually erasable block, in bytes: 4 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000103 ; Area ID: HWM_NRF52832_SP_2 | 0x10000100
diff --git a/mcu/nrf/nrf52/ini_files/nrf52833_app.ini b/mcu/nrf/nrf52/ini_files/nrf52833_app.ini
index dc0e9fd4..ac8cea65 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52833_app.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52833_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/nrf/nrf52/ini_files/nrf52833_wp.ini b/mcu/nrf/nrf52/ini_files/nrf52833_wp.ini
index d4821d96..d6803af5 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52833_wp.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52833_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 4096 ; Size of individually erasable block, in bytes: 4 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000109 ; Area ID: HWM_NRF52833 | 0x10000100
diff --git a/mcu/nrf/nrf52/ini_files/nrf52840_app.ini b/mcu/nrf/nrf52/ini_files/nrf52840_app.ini
index 62b28680..a810bf7b 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52840_app.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52840_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/nrf/nrf52/ini_files/nrf52840_wp.ini b/mcu/nrf/nrf52/ini_files/nrf52840_wp.ini
index 003bb7a9..9bbe8b31 100644
--- a/mcu/nrf/nrf52/ini_files/nrf52840_wp.ini
+++ b/mcu/nrf/nrf52/ini_files/nrf52840_wp.ini
@@ -22,7 +22,7 @@ eraseblock = 4096 ; Size of individually erasable block, in bytes: 4 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
id = 0x10000106 ; Area ID: HWM_NRF52840 | 0x10000100
diff --git a/mcu/nrf/nrf52/linker/gcc_bl_nrf52832.ld b/mcu/nrf/nrf52/linker/gcc_bl_nrf52832.ld
index dccac852..3c4934a2 100644
--- a/mcu/nrf/nrf52/linker/gcc_bl_nrf52832.ld
+++ b/mcu/nrf/nrf52/linker/gcc_bl_nrf52832.ld
@@ -58,6 +58,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -73,6 +74,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/nrf/nrf52/linker/gcc_bl_nrf52833.ld b/mcu/nrf/nrf52/linker/gcc_bl_nrf52833.ld
index fadf3002..a473bc26 100644
--- a/mcu/nrf/nrf52/linker/gcc_bl_nrf52833.ld
+++ b/mcu/nrf/nrf52/linker/gcc_bl_nrf52833.ld
@@ -58,6 +58,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -73,6 +74,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/nrf/nrf52/linker/gcc_bl_nrf52840.ld b/mcu/nrf/nrf52/linker/gcc_bl_nrf52840.ld
index d51e2885..641bbab9 100644
--- a/mcu/nrf/nrf52/linker/gcc_bl_nrf52840.ld
+++ b/mcu/nrf/nrf52/linker/gcc_bl_nrf52840.ld
@@ -58,6 +58,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -73,6 +74,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/mcu/nrf/nrf91/config.mk b/mcu/nrf/nrf91/config.mk
index 8e3de50a..367f2ecf 100644
--- a/mcu/nrf/nrf91/config.mk
+++ b/mcu/nrf/nrf91/config.mk
@@ -12,12 +12,14 @@ mac_profile?=dect_nr_19_ghz
radio?=none
ifeq ($(MCU_SUB),60)
# Hardware magic used for this architecture
- HW_MAGIC=12
+ HW_MAGIC=0F
HW_VARIANT_ID=12
else
$(error "Invalid MCU_SUB for nrf91! $(MCU_SUB) only 60 supported")
endif
+modemfw_area_id=0x000004$(HW_MAGIC)
+modemfw_name=firmware.update.image.cbor
# Add custom flags
# Remove the -Wunused-parameter flag added by -Wextra as some cortex M4 header do not respect it
CFLAGS += -Wno-unused-parameter
diff --git a/mcu/nrf/nrf91/hal/usart_dma.c b/mcu/nrf/nrf91/hal/usart_dma.c
index b993ec03..d03c1790 100644
--- a/mcu/nrf/nrf91/hal/usart_dma.c
+++ b/mcu/nrf/nrf91/hal/usart_dma.c
@@ -68,13 +68,6 @@ void __attribute__((__interrupt__)) TIMER1_IRQHandler(void);
bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
{
bool ret;
- //uart_tx_pin
- nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
- nrf_gpio_pin_set(BOARD_USART_TX_PIN);
-
- //uart_rx_pin
- nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
- nrf_gpio_pin_set(BOARD_USART_RX_PIN);
/* Module variables */
m_enabled = 0;
@@ -82,6 +75,11 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
m_rx_callback = NULL;
/* GPIO init */
+ nrf_gpio_cfg_default(BOARD_USART_TX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_TX_PIN);
+ nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
+ nrf_gpio_pin_set(BOARD_USART_RX_PIN);
+
NRF_UARTE0->PSEL.TXD = BOARD_USART_TX_PIN;
NRF_UARTE0->PSEL.RXD = BOARD_USART_RX_PIN;
NRF_UARTE0->TASKS_STOPTX = 1;
@@ -89,14 +87,10 @@ bool Usart_init(uint32_t baudrate, uart_flow_control_e flow_control)
NRF_UARTE0->ENABLE = UARTE_ENABLE_ENABLE_Disabled;
#if defined(BOARD_USART_CTS_PIN) && defined (BOARD_USART_RTS_PIN)
- //uart_cts_pin
nrf_gpio_cfg_default(BOARD_USART_CTS_PIN);
nrf_gpio_pin_set(BOARD_USART_CTS_PIN);
-
- //uart_rts_pin
nrf_gpio_cfg_default(BOARD_USART_RTS_PIN);
nrf_gpio_pin_set(BOARD_USART_RTS_PIN);
-
/* Set flow control */
set_flow_control(flow_control == UART_FLOW_CONTROL_HW);
#endif
@@ -281,7 +275,6 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
m_rx_callback = rx_callback;
if (m_rx_callback)
{
- /* Enable interrupt */
// Enable RX input
nrf_gpio_cfg(BOARD_USART_RX_PIN,
NRF_GPIO_PIN_DIR_INPUT,
@@ -289,12 +282,9 @@ void Usart_enableReceiver(serial_rx_callback_f rx_callback)
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_SENSE_LOW);
-
-
}
else
{
- /* Disable interrupt */
// Disable RX input: note autopowering uart will not work either
nrf_gpio_cfg_default(BOARD_USART_RX_PIN);
}
@@ -435,9 +425,8 @@ static void set_flow_control(bool hw)
/* No parity, no HW flow control */
NRF_UARTE0->CONFIG = 0;
- // Deactivate HAL_USART_CTS_PIN
+ // Deactivate CTS & RTS pins
nrf_gpio_cfg_default(BOARD_USART_CTS_PIN);
- // Deactivate HAL_USART_RTS_PIN
nrf_gpio_cfg_default(BOARD_USART_RTS_PIN);
}
}
diff --git a/mcu/nrf/nrf91/ini_files/nrf9160_app.ini b/mcu/nrf/nrf91/ini_files/nrf9160_app.ini
index bff4b093..341adac3 100644
--- a/mcu/nrf/nrf91/ini_files/nrf9160_app.ini
+++ b/mcu/nrf/nrf91/ini_files/nrf9160_app.ini
@@ -19,7 +19,7 @@
; bit 0 : store version numbers in this area (must be 1 for application area and 0 for others
; except if you know what you are doing)
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:application]
id = APP_AREA_ID ; Area ID, different for each application
diff --git a/mcu/nrf/nrf91/ini_files/nrf9160_wp.ini b/mcu/nrf/nrf91/ini_files/nrf9160_wp.ini
index 5e95639c..6f1ce1fe 100644
--- a/mcu/nrf/nrf91/ini_files/nrf9160_wp.ini
+++ b/mcu/nrf/nrf91/ini_files/nrf9160_wp.ini
@@ -22,23 +22,35 @@ eraseblock = 4096 ; Size of individually erasable block, in bytes: 4 kB
; Flags definition:
; bit 0 : store version numbers in this area
; bit 1 : memory area is located in external flash
-; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user
+; bits 2,3,4 : area type, 0:bootloader, 1:stack, 2:application, 3:persistent, 4:scratchpad, 5:user, 6:modemfw
[area:bootloader]
-id = 0x1000010F ; Area ID: HWM_NRF9160 | 0x10000100
+id = 0x10000112 ; Area ID: HW_VARIANT_ID=0x12 | 0x10000100
address = 0x00000000 ; Start address: beginning of Flash
length = 32768 ; Length in bytes: 32 kB
flags = 0x00000000 ; Don't store version; internal flash; bootloader
settings = 0x00007c00 ; Offset of bootloader settings from addr. (areas, keys)
[area:firmware]
-id = STACK_AREA_ID ; Area ID: HWM_NRF9160 | 0x00000100
+id = STACK_AREA_ID ; Area ID: HW_MAGIC=0x0f | 0x00000100
address = 0x00008000 ; Start address: right after bootloader
length = 245760 ; Length in bytes: 240 kB
flags = 0x00000005 ; Store version; internal flash; stack
[area:persistent]
-id = 0x2000000F ; Area ID: HWM_NRF9160 | 0x20000000
+id = 0x20000012 ; Area ID: HW_VARIANT_ID=0x12 | 0x20000000
address = 0x000fe000 ; Start address: 8 kB before end of Flash
length = 8192 ; Length in bytes: 8 kB
flags = 0x0000000C ; Don't store version; internal flash; persistent
+
+[area:scratchpad]
+id = 0x00000212 ; Area ID: HW_VARIANT_ID=0x12 | 0x00000200
+address = 0x00000000 ; Start address: at the start of ext flash
+length = 2097152 ; Length in bytes: 2 MB
+flags = 0x00000012 ; Don't store version; external flash; scratchpad
+
+[area:modemfw]
+id = 0x0000040F ; Area ID: HW_VARIANT_ID=0x0F | 0x00000400
+address = 0xFFFFFFFF ; Start address: N/A
+length = 0 ; Length in bytes: 0 MB
+flags = 0x0000001A ; Don't store version; modemfw
diff --git a/mcu/nrf/nrf91/linker/gcc_bl_nrf9160.ld b/mcu/nrf/nrf91/linker/gcc_bl_nrf9160.ld
index 245321c3..beb63fd3 100644
--- a/mcu/nrf/nrf91/linker/gcc_bl_nrf9160.ld
+++ b/mcu/nrf/nrf91/linker/gcc_bl_nrf9160.ld
@@ -58,6 +58,7 @@ SECTIONS
*scratchpad.*o*(.data* .data)
*internal_flash*.*o*(.data* .data)
*external_flash*.*o*(.data* .data)
+ *debug_flow*.*o*(.data* .data)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder.
*/
@@ -73,6 +74,7 @@ SECTIONS
*scratchpad.*o*(.bss.* .bss)
*internal_flash*.*o*(.bss* .bss)
*external_flash*.*o*(.bss* .bss)
+ *debug_flow*.*o*(.bss* .bss)
/* Customer specific external flash driver must be located in
* board/board_name/bootloader folder
*/
diff --git a/source/example_apps/ble_scanner/app.c b/source/example_apps/ble_scanner/app.c
index 625021bb..16a76aac 100644
--- a/source/example_apps/ble_scanner/app.c
+++ b/source/example_apps/ble_scanner/app.c
@@ -212,7 +212,6 @@ void App_init(const app_global_functions_t * functions)
#endif
LOG(LVL_INFO, "Starting BLE Scanner app");
- Led_init();
Ble_scanner_init(ble_scanner_filter, on_beacon_received);
diff --git a/source/example_apps/control_node/app.c b/source/example_apps/control_node/app.c
index 5db179b0..87a26cc7 100644
--- a/source/example_apps/control_node/app.c
+++ b/source/example_apps/control_node/app.c
@@ -186,8 +186,6 @@ void App_init(const app_global_functions_t * functions)
return;
}
- Button_init();
-
app_res = lib_settings->setNodeRole(APP_LIB_SETTINGS_ROLE_ADVERTISER);
if (app_res != APP_RES_OK)
{
diff --git a/source/example_apps/control_node/config.mk b/source/example_apps/control_node/config.mk
index 36a2889e..08f9d245 100644
--- a/source/example_apps/control_node/config.mk
+++ b/source/example_apps/control_node/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/example_apps/control_router/app.c b/source/example_apps/control_router/app.c
index 1eed4b6d..63f8674c 100644
--- a/source/example_apps/control_router/app.c
+++ b/source/example_apps/control_router/app.c
@@ -275,8 +275,6 @@ void App_init(const app_global_functions_t * functions)
return;
}
- Led_init();
-
ctrl_ret = Control_Router_init(&conf);
if (ctrl_ret != CONTROL_RET_OK)
{
diff --git a/source/example_apps/control_router/config.mk b/source/example_apps/control_router/config.mk
index 5ee4ef48..8072a1d7 100644
--- a/source/example_apps/control_router/config.mk
+++ b/source/example_apps/control_router/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/example_apps/custom_app/config.mk b/source/example_apps/custom_app/config.mk
index 136bcc01..70c14280 100644
--- a/source/example_apps/custom_app/config.mk
+++ b/source/example_apps/custom_app/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/example_apps/evaluation_app/app.c b/source/example_apps/evaluation_app/app.c
index 3732e1a7..bd765d56 100644
--- a/source/example_apps/evaluation_app/app.c
+++ b/source/example_apps/evaluation_app/app.c
@@ -46,7 +46,7 @@
#define DEFAULT_PERIOD_MS (DEFAULT_PERIOD_S*1000u)
/** The application will register for this type of app_config, corresponding to the measurement rate. */
-#define CUSTOM_PERIOD_TYPE 0xC3
+#define CUSTOM_PERIOD_TYPE 0xC3
/** Time needed to execute the periodic work, in us. */
#define PERIODIC_WORK_EXECUTION_TIME_US (250u)
@@ -204,7 +204,7 @@ typedef struct __attribute__((packed))
} msg_t;
/** Application periodic message fixed data pattern. */
-static const uint8_t m_periodic_data_pattern[PERIODIC_MSG_DATA_PATTERN_LEN] =
+static const uint8_t m_periodic_data_pattern[PERIODIC_MSG_DATA_PATTERN_LEN] =
{0x0A,0x0B,0x0B,0x0A,0x0A,0x0C,0x0D,0x0C};
/** Button ID which was pressed */
@@ -625,7 +625,7 @@ static app_lib_data_receive_res_e unicast_broadcast_data_received_cb(
* @brief Period change callback
* This function is called when an app config message concerning period change has been received
*/
-static void appConfigPeriodReceivedCb(uint16_t type,
+static void appConfigPeriodReceivedCb(uint16_t type,
uint8_t length,
uint8_t * value_p)
{
@@ -698,11 +698,7 @@ void App_init(const app_global_functions_t * functions)
#ifdef ENABLE_LOW_LATENCY_MODE
lib_settings->setNodeRole(APP_LIB_SETTINGS_ROLE_AUTOROLE_LL);
#endif
- /* Set up LED. */
- Led_init();
- /* Set up buttons. */
- Button_init();
num_buttons = Button_get_number();
for (uint8_t button_id = 0; button_id < num_buttons; button_id++)
diff --git a/source/example_apps/low_latency_app/app.c b/source/example_apps/low_latency_app/app.c
index 9a2ba5fa..60ae9312 100644
--- a/source/example_apps/low_latency_app/app.c
+++ b/source/example_apps/low_latency_app/app.c
@@ -6,7 +6,7 @@
/*
* @file app.c
- * @brief This file is an example application to demonstrate Low-Latency capabilities for a lighting usecase.
+ * @brief This file is an example application to demonstrate Low-Latency capabilities for a lighting usecase.
* (see README for additional information)
*/
@@ -30,7 +30,7 @@
#include "debug_log.h"
#define MAX_LED_PER_BOARD 4u
-#define SWITCH_ON_COMMAND_PATTERN 0b00000001
+#define SWITCH_ON_COMMAND_PATTERN 0b00000001
/** Endpoint used to communicate. */
#define DATA_EP (25u)
@@ -46,7 +46,7 @@
/** Message ID. */
-typedef enum
+typedef enum
{
/** Button pressed message, send to other nodes through active flooding. */
MSG_ID_SWITCH_COMMAND = 1,
@@ -99,7 +99,7 @@ typedef struct __attribute__((packed))
} msg_t;
-/**
+/**
* @brief LED state control function.
* @param led_id
* LED ID of led to change state.
@@ -118,7 +118,7 @@ static void set_led_state(uint8_t led_id, uint8_t led_state)
}
/** Send functions. */
-/**
+/**
* @brief Function sending a message to all nodes, with node to node method.
* @param id : message Id, @ref message_id_e.
* @param payload : pointer on the data to send.
@@ -133,8 +133,8 @@ static app_lib_data_send_res_e send_node_to_node_msg(message_id_e message_id, ui
msg.id = (uint8_t)message_id;
/* Fill the message. */
- memcpy(&msg.payload.switch_status,
- (payload_switch_command_t *)payload,
+ memcpy(&msg.payload.switch_status,
+ (payload_switch_command_t *)payload,
sizeof(payload_switch_command_t));
msg_byte_size += sizeof(payload_switch_command_t);
@@ -210,16 +210,16 @@ static app_lib_data_receive_res_e data_received_cb(
payload_switch_command_t *payload = & msg->payload.switch_status;
LOG (LVL_INFO, "Switch command received : button_id = %d, action = %d", payload->button_id, payload->action);
/* Check the action type. */
- if (payload->action == 1) /* Button pressed. */
+ if (payload->action == 1) /* Button pressed. */
{
- set_led_for_button(payload->button_id, payload->action);
+ set_led_for_button(payload->button_id, payload->action);
}
else if (payload->action == 0)
{
/* Button released, no action yet. */
}
}
- else
+ else
{
LOG(LVL_INFO, "Message received doesn't match the size of the expected message.");
}
@@ -257,7 +257,7 @@ static app_lib_data_receive_res_e data_received_cb(
{
LOG(LVL_INFO,
"Set new Mcast address : 0x%x",
- msg->payload.set_multicast_address.multicast_address);
+ msg->payload.set_multicast_address.multicast_address);
m_mcast_address=msg->payload.set_multicast_address.multicast_address;
app_persistent_res_e res = App_Persistent_write((uint8_t *) &m_mcast_address, sizeof(m_mcast_address));
if (res != APP_PERSISTENT_RES_OK)
@@ -307,9 +307,9 @@ static uint32_t task_send_button_pressed_msg(void)
static uint32_t counter_value = 0;
payload.counter = counter_value;
uint8_t led_id = 1;
-
+
/* Construct switch command. */
- payload.button_id = m_button_pressed_id;
+ payload.button_id = m_button_pressed_id;
payload.action = 1; /* Always do something when a button is pressed */
/* Send message. */
app_lib_data_send_res_e res = send_node_to_node_msg(MSG_ID_SWITCH_COMMAND, (uint8_t *)&payload);
@@ -404,11 +404,6 @@ void App_init(const app_global_functions_t * functions)
LOG(LVL_ERROR, "Persistent area is not initialized as it should (no area defined?)\n");
}
- /* Set up LED. */
- Led_init();
-
- /* Set up buttons. */
- Button_init();
num_buttons = Button_get_number();
for (uint8_t button_id = 0; button_id < num_buttons; button_id++)
diff --git a/source/example_apps/minimal_app/config.mk b/source/example_apps/minimal_app/config.mk
index 04bc3eb6..3164206d 100644
--- a/source/example_apps/minimal_app/config.mk
+++ b/source/example_apps/minimal_app/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/example_apps/ruuvi_evk/app.c b/source/example_apps/ruuvi_evk/app.c
index dbc72a49..de6bf9f8 100644
--- a/source/example_apps/ruuvi_evk/app.c
+++ b/source/example_apps/ruuvi_evk/app.c
@@ -11,6 +11,7 @@
#include "tlv.h"
#include "app_scheduler.h"
#include "board.h"
+#include "gpio.h"
#include "spi.h"
#include "power.h"
@@ -43,18 +44,17 @@ static bool ruuvi_spi_init(void)
{
spi_res_e res;
spi_conf_t conf;
+ gpio_out_cfg_t gpio_conf = {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH
+ };
/* Initialize LIS2DH12 Chip select pin. */
- nrf_gpio_pin_dir_set(BOARD_SPI_LIS2DH12_CS_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
- nrf_gpio_cfg_output(BOARD_SPI_LIS2DH12_CS_PIN);
- nrf_gpio_pin_set(BOARD_SPI_LIS2DH12_CS_PIN);
-
+ Gpio_outputSetCfg(BOARD_GPIO_ID_LIS2DX12_SPI_CS, &gpio_conf);
/* Initialize BME280 Chip select pin. */
- nrf_gpio_pin_dir_set(BOARD_SPI_BME280_CS_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
- nrf_gpio_cfg_output(BOARD_SPI_BME280_CS_PIN);
- nrf_gpio_pin_set(BOARD_SPI_BME280_CS_PIN);
-
+ Gpio_outputSetCfg(BOARD_GPIO_ID_BME280_SPI_CS, &gpio_conf);
/* Initialize SPI driver. */
+
conf.bit_order = SPI_ORDER_MSB;
conf.clock = 4000000;
conf.mode = SPI_MODE_HIGH_FIRST;
diff --git a/source/example_apps/ruuvi_evk/bme280_wrapper.c b/source/example_apps/ruuvi_evk/bme280_wrapper.c
index 8e898a2a..c4638c68 100644
--- a/source/example_apps/ruuvi_evk/bme280_wrapper.c
+++ b/source/example_apps/ruuvi_evk/bme280_wrapper.c
@@ -8,6 +8,7 @@
#include "hal_api.h"
#include "spi.h"
#include "api.h"
+#include "gpio.h"
#include
#include "bme280_wrapper.h"
@@ -46,14 +47,10 @@ static void bme280_delay_ms(uint32_t period)
*/
void bme280_select_chip(bool select)
{
- if (select)
- {
- nrf_gpio_pin_clear(BOARD_SPI_BME280_CS_PIN);
- }
- else
- {
- nrf_gpio_pin_set(BOARD_SPI_BME280_CS_PIN);
- }
+ gpio_level_e level;
+
+ level = select ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH;
+ Gpio_outputWrite(BOARD_GPIO_ID_BME280_SPI_CS, level);
}
/**
diff --git a/source/example_apps/ruuvi_evk/lis2dh12_wrapper.c b/source/example_apps/ruuvi_evk/lis2dh12_wrapper.c
index 83dd886e..dde67b4a 100644
--- a/source/example_apps/ruuvi_evk/lis2dh12_wrapper.c
+++ b/source/example_apps/ruuvi_evk/lis2dh12_wrapper.c
@@ -8,6 +8,7 @@
#include "hal_api.h"
#include "spi.h"
#include "api.h"
+#include "gpio.h"
#include
#include "lis2dh12_wrapper.h"
@@ -47,14 +48,10 @@ static void lis2dh12_delay_ms(uint32_t period)
*/
void lis2dh12_select_chip(bool select)
{
- if (select)
- {
- nrf_gpio_pin_clear(BOARD_SPI_LIS2DH12_CS_PIN);
- }
- else
- {
- nrf_gpio_pin_set(BOARD_SPI_LIS2DH12_CS_PIN);
- }
+ gpio_level_e level;
+
+ level = select ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH;
+ Gpio_outputWrite(BOARD_GPIO_ID_LIS2DX12_SPI_CS, level);
}
/**
diff --git a/source/example_apps/ruuvi_evk/makefile b/source/example_apps/ruuvi_evk/makefile
index 3a813266..f5132489 100644
--- a/source/example_apps/ruuvi_evk/makefile
+++ b/source/example_apps/ruuvi_evk/makefile
@@ -8,6 +8,7 @@ INCLUDES += -I$(APP_SRCS_PATH)BME280_driver/
INCLUDES += -I$(APP_SRCS_PATH)LIS2DH12_driver/lis2dh12_STdC/driver/
HAL_SPI=yes
+HAL_GPIO=yes
# Use App Scheduler and configure it
APP_SCHEDULER=yes
diff --git a/source/reference_apps/dualmcu_app/config.mk b/source/reference_apps/dualmcu_app/config.mk
index 8e2e52de..1e09dffd 100644
--- a/source/reference_apps/dualmcu_app/config.mk
+++ b/source/reference_apps/dualmcu_app/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := pca10059 pca10056 promistel_rpi_hat pca10100 ublox_b204 pca10040 wuerth_261101102 mdbt50q_rx nrf52832_mdk_v2 silabs_brd4254a tbsense2 silabs_brd4253a silabs_brd4180b silabs_brd4184a silabs_brd4181b bgm220-ek4314a silabs_brd4312a silabs_brd4210a pan1780
+TARGET_BOARDS := pca10090 pca10059 pca10056 promistel_rpi_hat pca10100 ublox_b204 pca10040 wuerth_261101102 mdbt50q_rx nrf52832_mdk_v2 silabs_brd4254a tbsense2 silabs_brd4253a silabs_brd4180b silabs_brd4184a silabs_brd4181b bgm220-ek4314a silabs_brd4312a silabs_brd4210a pan1780 pca10090 pca10090_low_tx_power
# Define a specific application area_id
app_specific_area_id=0x846B74
diff --git a/source/reference_apps/dualmcu_app/gencustomscratchpad.py b/source/reference_apps/dualmcu_app/gencustomscratchpad.py
index a176f263..f767e2fc 100755
--- a/source/reference_apps/dualmcu_app/gencustomscratchpad.py
+++ b/source/reference_apps/dualmcu_app/gencustomscratchpad.py
@@ -54,7 +54,7 @@ def make_header(data):
uint8_t pad;
/** Scratchpad type information for bootloader: bl_header_type_e */
uint32_t type;
- /** Status code from bootloader: bl_header_status_e */
+ /** Status code from bootloader: bl_scratchpad_status_e */
uint32_t status;
};
diff --git a/source/reference_apps/positioning_app/app.c b/source/reference_apps/positioning_app/app.c
index f9c4b4ba..361ea48e 100644
--- a/source/reference_apps/positioning_app/app.c
+++ b/source/reference_apps/positioning_app/app.c
@@ -29,10 +29,13 @@
#include "shared_beacon.h"
#include "posapp_settings.h"
#include "board.h"
-#include "led.h"
-
-#include "gpio.h"
#include "voltage.h"
+#ifdef BUTTON_ENABLED
+#include "button.h"
+#endif
+#ifdef CONF_USE_LED_NOTIFICATION
+#include "led.h"
+#endif
#ifdef MOTION_SUPPORTED
#include "motion.h"
#endif
@@ -40,10 +43,12 @@
#include "app_persistent.h"
#endif
+#ifdef BUTTON_ENABLED
+#define BUTTON_ID 0
+#endif
#ifdef CONF_USE_LED_NOTIFICATION
#define LED_ON true
#define LED_OFF false
-
/** used to share led id to led control task */
#define LED_ID 0
#endif
@@ -53,15 +58,15 @@ static uint8_t m_event_config_change_id = POSLIB_FLAG_EVENT_SUBSCRIBERS_MAX;
static uint8_t m_event_led_on_id = POSLIB_FLAG_EVENT_SUBSCRIBERS_MAX;
static uint8_t m_event_led_off_id = POSLIB_FLAG_EVENT_SUBSCRIBERS_MAX;
+#ifdef BUTTON_ENABLED
/**
* @brief Example function used with PosLib_oneshot().
* This function called from HAL button as callback when requested
* button is pressed.
*/
-#ifdef BUTTON_ENABLED
-static void button_pressed_cb(uint8_t pin, gpio_event_e event)
+static void button_pressed_cb(uint8_t button_id, button_event_e button_event)
{
- LOG(LVL_DEBUG, "Start oneshot. Button event %u button pin %u", event, pin);
+ LOG(LVL_DEBUG, "Start oneshot. Button event %u button id %u", button_event, button_id);
PosLib_startOneshot();
}
@@ -70,21 +75,13 @@ static void button_pressed_cb(uint8_t pin, gpio_event_e event)
*/
static void enable_button(void)
{
- gpio_res_e res;
- uint8_t buttons_pins[] = BOARD_BUTTON_PIN_LIST;
- gpio_pull_e pull = BOARD_BUTTON_INTERNAL_PULL ? GPIO_PULLUP: GPIO_PULLDOWN;
- gpio_event_e event = BOARD_BUTTON_ACTIVE_LOW ? GPIO_EVENT_HL : GPIO_EVENT_LH;
- #define DEBOUNCE_MS 100 //FixME: move to general definitions
- #define BUTTON_ID 0 //FixME: move to general definitions
-
- res = GPIO_register_for_event(buttons_pins[BUTTON_ID],
- pull,
- event,
- DEBOUNCE_MS,
- button_pressed_cb);
- if (res == GPIO_RES_OK)
+ button_res_e res;
+
+ res = Button_register_for_event(BUTTON_ID, BUTTON_PRESSED, button_pressed_cb);
+
+ if (res == BUTTON_RES_OK)
{
- LOG(LVL_INFO, "Oneshot request active on button %u", BUTTON_ID);
+ LOG(LVL_INFO, "Oneshot request active on button id %u", BUTTON_ID);
}
else
{
@@ -160,7 +157,7 @@ static void App_posLib_event(POSLIB_FLAG_EVENT_info_t * msg)
#ifdef MOTION_SUPPORTED
update_motion(&settings.motion);
#endif
-
+
#ifdef CONF_USE_PERSISTENT_MEMORY
/** Writing to memory takes time, do it in own task - not in callback */
App_Scheduler_addTask_execTime(App_persistent_data_write, APP_SCHEDULER_SCHEDULE_ASAP, 500);
@@ -214,7 +211,7 @@ static poslib_ret_e App_start_positioning(void)
/** Configuration set to library */
res = PosLib_setConfig(&settings);
-
+
if (res != POS_RET_OK)
{
LOG(LVL_ERROR, "PosLib configuration fail. res: %d", res);
@@ -280,11 +277,6 @@ void App_init(const app_global_functions_t* functions)
/** Initialization of shared libraries */
enable_button();
-#ifdef CONF_USE_LED_NOTIFICATION
- /** Initialization of hal led services */
- Led_init();
-#endif
-
/* Initialize motion sensor if enabled */
#ifdef MOTION_SUPPORTED
PosAppMotion_init();
diff --git a/source/reference_apps/positioning_app/config.mk b/source/reference_apps/positioning_app/config.mk
index f77cb038..ae3f0f92 100644
--- a/source/reference_apps/positioning_app/config.mk
+++ b/source/reference_apps/positioning_app/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := pca10059 pca10056 pca10100 pca10040 ruuvitag silabs_brd4180b silabs_brd4184a silabs_brd4181b bgm220-ek4314a
+TARGET_BOARDS := pca10059 pca10056 pca10100 pca10040 ruuvitag silabs_brd4180b silabs_brd4184a silabs_brd4181b silabs_brd4184a pca10040 bgm220-ek4314a
#
# Network default settings configuration
#
@@ -46,7 +46,7 @@ default_bletx_interval_ms=1000
# POSLIB_BLETX_POWER. Fefault bletx power, 8 max used with all radio profiles
default_bletx_power=8
-# Default voltage reporting (yes/no)
+# Default voltage reporting (yes/no)
default_voltage_report=yes
# Default logging setting
@@ -55,7 +55,7 @@ default_debug_level=3
# Read configure values from Peristent Memory in use (yes/no)
use_persistent_memory=yes
-#Enable button for triggering oneshot update (yes/no)
+#Enable button for triggering oneshot update (yes/no)
button_enabled=no
#Enable led notification (yes/no)
@@ -82,4 +82,3 @@ app_minor=$(sdk_minor)
app_maintenance=$(sdk_maintenance)
app_development=2
-
diff --git a/source/reference_apps/positioning_app/docs/PosApp_guide.md b/source/reference_apps/positioning_app/docs/PosApp_guide.md
index 847d0da0..2d761985 100644
--- a/source/reference_apps/positioning_app/docs/PosApp_guide.md
+++ b/source/reference_apps/positioning_app/docs/PosApp_guide.md
@@ -10,18 +10,18 @@
# Introduction
-The positioning application (PosApp) implements the complete application required for the Wirepas Positioning System (WPS).
-The application is targeted to run on asset tracking tags and anchors and can be used as is or customised further. The application core is
+The positioning application (PosApp) implements the complete application required for the Wirepas Positioning System (WPS).
+The application is targeted to run on asset tracking tags and anchors and can be used as is or customised further. The application core is
the positioning library (PosLib) which provides all needed functionality to collect WPS measurements. In addition the application has the following modules:
* **settings:** responsible for handling PosLib settings
* **motion:** responsible for determining the motion state of the node
The application can run on both nRF52 and EFR32 chipset families as supported by Wirepas Massive (WM) stack. Note that for EFR32BG22 only
-tag functionality (i.e. non-router network role) is supported. The list of boards supported is visible in `config.mk`.
+tag functionality (i.e. non-router network role) is supported. The list of boards supported is visible in `config.mk`.
-The application version numbering scheme is (sdk major).(sdk minor).(sdk maintenance).(application version).
-
-In the following it is assumed that the reader is familiar with developing an application using the Wirepas SDK. It is recommended
+The application version numbering scheme is (sdk major).(sdk minor).(sdk maintenance).(application version).
+
+In the following it is assumed that the reader is familiar with developing an application using the Wirepas SDK. It is recommended
to read also [[1]](#References) and [[2]](#References).
# Getting started
@@ -33,37 +33,39 @@ The following application settings can be controlled through `config.mk` paramet
| Parameter | Description |
|-----------------------|----------------------------------------------------------------|
| default_network_address | Node network address |
-| default_network_channel | Node network channel |
+| default_network_channel | Node network channel |
| default_network_cipher_key | Network encryption key. (recommended to be set) |
| default_network_authen_key | Network authentication key. (recommended to be set) |
| app_specific_area_id | Application area ID. Shall be unique in the network |
-| default_role | Router (headnode) LE: 0x01, Router LL: 0x11, Non-router (subnode) LE: 0x02, Advertiser: 0x04 (note that anchors are always routers while tags non-routers and battery powered nodes shall always be low-energy)|
+| default_role | Router (headnode) LE: 0x01, Router LL: 0x11, Non-router (subnode) LE: 0x02, Advertiser: 0x04 (note that anchors are always routers while tags non-routers and battery powered nodes shall always be low-energy)|
| default_poslib_device_class | Positioning class for node 0xFF...0xF9 (see `poslib_class_e` in `poslib.h`)|
| default_poslib_device_mode | Tag NRLS: 1, Tag autoscan: 2, Anchor autoscan: 3, Anchor oportunistic: 4 (`poslib_mode_e` in `poslib.h`) |
-| default_update_period_static_s | Measurement rate if node is static or motion monitoring not supported |
-| default_update_period_dynamic_s | Measurement rate if node is dynamic. (not used if set to 0 or motion monitoring not supported)|
+| default_update_period_static_s | Measurement rate if node is static or motion monitoring not supported |
+| default_update_period_dynamic_s | Measurement rate if node is dynamic. (not used if set to 0 or motion monitoring not supported)|
| default_update_period_offline_s | Measurement rate when the node is outside network coverage. (not used if set to 0) |
| default_bletx_mode | (OFF: 0, always ON: 1, when outside coverage: 3 (see `poslib_ble_mode_e` in `poslib.h`)|
| default_bletx_activation_delay_s | BLE beacons activation delay when outside WM coverage |
-| default_bletx_type | (see Eddystone: 1, iBeacon 2, both: 3 (see `poslib_ble_type_e` in `poslib.h`) |
-| default_bletx_interval_ms | Default update period for BLE beacons. range 100 ... 60000 milliseconds |
+| default_bletx_type | (see Eddystone: 1, iBeacon 2, both: 3 (see `poslib_ble_type_e` in `poslib.h`) |
+| default_bletx_interval_ms | Default update period for BLE beacons. range 100 ... 60000 milliseconds |
| default_bletx_power | BLE beacon transmit power. (ceiled to maximum supported)|
| default_voltage_report | enables/disable voltage sampling ans sedning in PosLib : yes/no (recommended yes) |
-| default_debug_level| Logging level. LVL_DEBUG: 4, LVL_INFO: 3,LVL_WARNING: 2 ,LVL_ERROR: 1, LVL_NOLOG: 0|
+| default_debug_level| Logging level. LVL_DEBUG: 4, LVL_INFO: 3,LVL_WARNING: 2 ,LVL_ERROR: 1, LVL_NOLOG: 0|
| use_persistent_memory | Saves/retrieved the settings from persistent storage: yes/no |
-| button_enabled | Enable button for triggering oneshot update: yes/no (currently only supported on nRF52) |
+| button_enabled | Enable button for triggering oneshot update: yes/no (currently only supported on nRF52) |
| led_notification_enabled | Enable led notification feature: yes/no |
| motion_sensor | Defines the motion sensor type and bus used. LIS2DH12 over I2C: lis2dh12_i2c, LIS2DH12 over SPI: lis2dh12_spi |
| default_motion_enabled | Enables/disables motion support: 1/0 |
-| default_motion_threshold_mg | Acceleration threshold above which motion will be detected [mg]|
+| default_motion_threshold_mg | Acceleration threshold above which motion will be detected [mg]|
| default_motion_duration_ms | Duration for acceleration to be above threshold for motion to be detected [ms]|
| default_mbcn_enabled | Enables (1) or disable (0) mini-beacon sending |
-| default_mbcn_tx_interval_ms | Mini-beacon transmit rate in miliseconds: only 250ms, 500ms or 1000ms are allowed|
+| default_mbcn_tx_interval_ms | Mini-beacon transmit rate in miliseconds: only 250ms, 500ms or 1000ms are allowed|
| default_da_routing_enabled | Enables (1) or disable (0) re-routing of received DA data packets by a LL router|
| default_da_follow_network | Enables (1) or disable (0) the use of automatic neighbour discovery|
A separate build should be generated for anchor and tags with the corresponding parameters set.
+Regarding the sink of the positioning network, it should be operating in Low Latency (LL sink) to maintain the stability of NLRS tags in the network.
+
# Settings
The settings module is responsible for storing and retrieving from persistent storage the node network and PosLib settings.
@@ -72,27 +74,27 @@ The module API is defined in `poslib_settings.h` and consistes of:
bool PosApp_Settings_configureNode(void);
void PosApp_Settings_get(poslib_settings_t * settings);
bool PosApp_Settings_store(poslib_settings_t * settings);
-```
+```
The initial settings are taken from the provided compile time parameters. It is important that those settings are valid
-as otherwise PosLib will not start. Once PosLib is started it's settings can be updated over the network through the application
-configuration feature. Please note that the settings module will change the node network role if does not match the node positioning
-mode (e.g. if role is router but mode is tag then the role will be changed to non-router; when this happen a reboot will
-occur, see [[2]](#References)). If persistent storage is not enabled then positioning mode will be forced to match the node role according to the
-defaults set by `POSAPP_TAG_DEFAULT_ROLE` and `POSAPP_ANCHOR_DEFAULT_ROLE`.
+as otherwise PosLib will not start. Once PosLib is started it's settings can be updated over the network through the application
+configuration feature. Please note that the settings module will change the node network role if does not match the node positioning
+mode (e.g. if role is router but mode is tag then the role will be changed to non-router; when this happen a reboot will
+occur, see [[2]](#References)). If persistent storage is not enabled then positioning mode will be forced to match the node role according to the
+defaults set by `POSAPP_TAG_DEFAULT_ROLE` and `POSAPP_ANCHOR_DEFAULT_ROLE`.
## Manufacturing node customization
-During manufacturing it is possible to inject custom settings parameters for each node straight to the persistent storage during flashing.
-For generating the flash hex image of the persistent settings an utility is provided under persistent_config folder. Note that the resulting hex
+During manufacturing it is possible to inject custom settings parameters for each node straight to the persistent storage during flashing.
+For generating the flash hex image of the persistent settings an utility is provided under persistent_config folder. Note that the resulting hex
file shall either be combined with the application hex. If flashed separately then the persistent setting hex shall be flashed first.
# Motion
-The motion module implements all required functionality for detecting the motion state of the node. Currently the ST Microelectronics LIS2DH12 accelerometer
-is supported for nRF52 platform (e.g. `ruuvitag` board). The sensor can be either connected over I2C or SPI.
+The motion module implements all required functionality for detecting the motion state of the node. Currently the ST Microelectronics LIS2DH12 accelerometer
+is supported for nRF52 platform (e.g. `ruuvitag` board). The sensor can be either connected over I2C or SPI.
-All the module files are located under `motion` folder:
+All the module files are located under `motion` folder:
```
├── motion
├── acc_interface.h
@@ -106,7 +108,7 @@ All the module files are located under `motion` folder:
├── motion.c
└── motion.h
```
-and the module API is defined in `motion.h` consiting of:
+and the module API is defined in `motion.h` consisting of:
```c
posapp_motion_ret_e PosAppMotion_init();
posapp_motion_ret_e PosAppMotion_startMonitoring(posapp_motion_mon_settings_t * cfg);
@@ -114,26 +116,33 @@ posapp_motion_ret_e PosAppMotion_stopMonitoring();
posapp_motion_status_e PosAppMotion_getStatus();
```
-To enable motion support the parameter `motion_sensor` shall be set to either `lis2dh12_i2c` or `lis2dh12_spi` (for `ruuvitag` board use `lis2dh12_spi`).
+To enable motion support the parameter `motion_sensor` shall be set to one of the following value:
+* `lis2dw12_i2c`
+* `lis2dh12_i2c`
+* `lis2dw12_spi`
+* `lis2dh12_spi`
+
+For `ruuvitag` board use `lis2dh12_spi`.
+
The module assumes that the `board.h` contains the following defines according to the bus type used:
-* **I2C:**
- * `BOARD_LIS2DH12_INT1_PIN ` or `BOARD_LIS2DH12_INT2_PIN ` to indicate the interrupt pin connected to accelerometer
- * `BOARD_I2C_LIS2DH12_SA0 0/1` to indicate the address value
+* **I2C:**
+ * `BOARD_LIS2DH12_INT1_PIN ` or `BOARD_LIS2DH12_INT2_PIN ` to indicate the interrupt pin connected to accelerometer
+ * `BOARD_I2C_LIS2DH12_SA0 0/1` to indicate the address value
* `BOARD_I2C_LIS2DH12_SA0_PIN ` to indicate the SA0 pin
* **SPI:**
- * `BOARD_SPI_LIS2DH12_CS_PIN `: to indicate the chip select pin
-
+ * `BOARD_SPI_LIS2DH12_CS_PIN `: to indicate the chip select pin
+
In addition the standard defines for configuring the I2C/SPI HAL are required (see `boards\ruuvitag` for an example).
-Note that the accelerometer ST drivers provided on GitHub will be pulled at first compile.
+Note that the accelerometer ST drivers provided on GitHub will be pulled at first compile.
For minimal power consumption the implementation uses the accelerometer built-in motion detection. The motion configuration consists of
-acceleration threshold and duration. If the acceleration is above the threshold for the set duration then the node is considered to be in
-motion (an interrupt will be generated as long the condition persists). When no motion interrupts are generated for `MOTION_STATIC_TIMEOUT_MS`
+acceleration threshold and duration. If the acceleration is above the threshold for the set duration then the node is considered to be in
+motion (an interrupt will be generated as long the condition persists). When no motion interrupts are generated for `MOTION_STATIC_TIMEOUT_MS`
seconds (default 60 sec) the node will be considered static. Every time the motion state changes PosApp will notify PosLib.
## Adding support for other accelerometer sensors
-The motion module assumes an interface to the accelerometer as defined in `acc_interface.h` and other accelerometers can be added by simply
+The motion module assumes an interface to the accelerometer as defined in `acc_interface.h` and other accelerometers can be added by simply
implementing the interface.
# Directed-advertiser and mini-beacons
@@ -183,14 +192,14 @@ For an DA tag the `make` shall contain the following options set:
|`default_role_flag=0` | low-energy|
|`default_mbcn_enabled=1` | mini-beacons enabled|
|`default_mbcn_tx_interval_ms=1000` | mini-beacon transmit interval 1000ms|
-|`default_da_routing_enabled=1` | DA data routing disabled (no effect for tag)|
-|`default_da_follow_network=0` | Automatic neigbour discovery disabled|
+|`default_da_routing_enabled=0` | DA data routing disabled (no effect for tag)|
+|`default_da_follow_network=1` | Automatic neigbour discovery enabled|
### Building a dedicated anchor
A dedicated anchor is a WM node installed in fixed/known location sending mini-beacons.
The node role can be either non-router/router/autorole in LL or LE. The typical setup is
-a LE non-router battery powered which will allow an easy and quick installation.
+a LE non-router battery powered which will allow an easy and quick installation.
For a dedicated anchor the `make` shall contain the following options set:
@@ -217,7 +226,7 @@ Sending data can be done through the new introduced API:
The function prototype is identical with the Shared Data library `Shared_Data_sendData` (see the library documentation for details).
Note that the DA tag source address will not be visible to the sink as the packet is re-routed by the router application.
-As a result, the DA tag address shall be embedded into data payload.
+As a result, the DA tag address shall be embedded into data payload.
To send data to the sink set `data->dest_address = APP_ADDR_ANYSINK` in the call. If the node is DA tag the destination address
will be changed to the best router with DA support (if available). In case the node is not in DA role the standard data sending will be used.
@@ -225,31 +234,31 @@ will be changed to the best router with DA support (if available). In case the n
Data sending can be done to any app allowed endpoints (EP) but don't use any of PosLib endpoints (238:238, 238:0)!
Data sending shall be synchronized with PosLib positioning update. This can be done easily by registering for the
-`POSLIB_FLAG_EVENT_UPDATE_END` event using `PosLib_eventRegister` and sending the data in the provided callback.
+`POSLIB_FLAG_EVENT_UPDATE_END` event using `PosLib_eventRegister` and sending the data in the provided callback.
If there is the need to prepare/acquire the data before this can be triggered by registering to `POSLIB_FLAG_EVENT_UPDATE_START` event.
-### DA data re-routing
-
+### DA data re-routing
+
The LL DA enabled router will receive the data packet sent by the tag and will have to re-route it to the sink.
-This is not done automatically and if the re-routing is not implemented the packed will be lost!
+This is not done automatically and if the re-routing is not implemented the packed will be lost!
The router shall:
* register a unicast data receive handler using the shared data library for the expected EP
-
+
See `Shared_Data_addDataReceivedCb` and set:
```c
- item->filter.mode=SHARED_DATA_NET_MODE_UNICAST
- item->filter.src_endpoint=...
+ item->filter.mode=SHARED_DATA_NET_MODE_UNICAST
+ item->filter.src_endpoint=...
item->filter.dest_endpoint= ...
```
* In the data received callback send the received data packet to sink.
-See `Shared_Data_sendData`
+See `Shared_Data_sendData`
## Sending data to a DA tag from router/sink
-Currently not supported.
+Currently not supported.
## Customizing mini-beacon payload
@@ -269,19 +278,19 @@ typedef struct
Each record is a type-lenth-value (TLV) and there types are predefined in `poslib_mbcn_record_types_e`.
Note that `POSLIB_MBCN_TX_INTERVAL` and `POSLIB_MBCN_FEATURES` are reserved for PosLib and shall not be used.
-It is important that the mini-beacon payload is kept to minimum posible and therefore only add strictly the
+It is important that the mini-beacon payload is kept to minimum posible and therefore only add strictly the
required records (i.e. not the ones good to have).
## Receiving and decoding mini-beacons by the app
To receive the mini-beacons in the app register a data receive handle using `Shared_Data_addDataReceivedCb`.
```c
- item->filter.mode=SHARED_DATA_NET_MODE_BROADCAST
+ item->filter.mode=SHARED_DATA_NET_MODE_BROADCAST
item->filter.src_endpoint=POSLIB_MBCN_SRC_EP
item->filter.dest_endpoint=POSLIB_MBCN_DEST_EP
```
The received payload can then be decoded using the `PosLib_decodeMbcn` PosLib API utility function.
-Mini-beacons are only received when PosLib makes a positioning update and there can be several or zero mini-beacons from
+Mini-beacons are only received when PosLib makes a positioning update and there can be several or zero mini-beacons from
an anchor.
# Other features
@@ -290,12 +299,12 @@ an anchor.
As described in [[2]](#References)) PosLib can send a LED event notification according the settings sent over network through application configuration.
PosApp subscribes to this event and turns a LED on/off. This feature is enabled through `led_notification_enabled` parameter and the LED index is defined by `LED_ID`
-(the LED pin is defined according to `BOARD_LED_PIN_LIST` from `board.h`).
+(the LED pin is defined according to `BOARD_LED_ID_LIST` from `board.h`).
## Button triggered position update
-An example for triggering a position measurement update at a press of a button is provided. The feature is enabled through `button_enabled` and the used button index is
-defined by `BUTTON_ID` (the button pin is defined to `BOARD_BUTTON_PIN_LIST` from `board.h`). Currently this feature is only supported in nRF52 family.
+An example for triggering a position measurement update at a press of a button is provided. The feature is enabled through `button_enabled` and the used button index is
+defined by `BUTTON_ID` (the button pin is defined to `BOARD_BUTTON_ID_LIST` from `board.h`). Currently this feature is only supported in nRF52 family.
# References
diff --git a/source/reference_apps/positioning_app/gpio.h b/source/reference_apps/positioning_app/gpio.h
deleted file mode 100644
index 2aac21f9..00000000
--- a/source/reference_apps/positioning_app/gpio.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright 2021 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file gpio.h
- * \brief This file implements a simple GPIO interface
- *
- */
-
-#ifndef _POS_APP_GPIO_H_
-#define _POS_APP_GPIO_H_
-
-#include "api.h"
-
-/* the number of pin supported for event monitoring
- each pin can be associated with a single event type and callback */
-
-#define GPIO_MAX 8
-
-typedef enum
-{
- GPIO_RES_OK = 0, // Operation is successful
- GPIO_RES_FAIL = 1,
- GPIO_RES_NOT_INITIALIZED = 2
-} gpio_res_e;
-
-/**
- * \brief Supported GPIO event types
- */
-typedef enum
-{
- GPIO_EVENT_LH = 0, // triggers on LOW->HIGH transition
- GPIO_EVENT_HL, // triggers on HIGH->LOW transition
- GPIO_EVENT_ALL, // triggers on LOW->HIGH | HIGH->LOW transition
- GPIO_EVENT_MAX
-} gpio_event_e;
-
-/**
- * \brief Supported GPIO pull types
- */
-typedef enum
-{
- GPIO_PULLDOWN = 0,
- GPIO_PULLUP,
- GPIO_NOPULL,
- GPIO_PULL_MAX
-} gpio_pull_e;
-
-/**
- * \brief Callback structure for a GPIO event
- * \param pin
- * pin number
- * \param event
- * Event that generated this callback
- */
-typedef void (*on_gpio_event_cb)(uint8_t pin,
- gpio_event_e event);
-
-/**
- * \brief Register for a GPIO event on a given pin
- * \param pin
- * pin number FixMe: !! to be made generic whe EFR32 support added
- * \param pull
- * pull value :GPIO_PULLDOWN / GPIO_PULLUP / GPIO_NOPULL
- * \param event
- * Event that generated this callback
- * \param cb
- * callback function to be called when event occured
- * \return GPIO_RES_OK if success, GPIO_RES_FAIL if failure (\ref gpio_res_e )
- */
-gpio_res_e GPIO_register_for_event(uint8_t pin,
- gpio_pull_e pull,
- gpio_event_e event,
- uint8_t debounce_ms,
- on_gpio_event_cb cb);
-
-/**
- * \brief Deregister for GPIO event on a given pin
- * \param pin
- * pin number
- * \return GPIO_RES_OK if success, GPIO_RES_FAIL if failure (\ref gpio_res_e )
- */
-gpio_res_e GPIO_deregister_for_event(uint8_t pin);
-#endif
\ No newline at end of file
diff --git a/source/reference_apps/positioning_app/gpio_efr32.c b/source/reference_apps/positioning_app/gpio_efr32.c
deleted file mode 100644
index e9fae70d..00000000
--- a/source/reference_apps/positioning_app/gpio_efr32.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Copyright 2021 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file gpio_efr32.c
- * \brief This file implements the GPIO interface to EFR32 chips
- *
- */
-
-#define DEBUG_LOG_MODULE_NAME "GPIO"
-#ifdef DEBUG_POSLIB_LOG_MAX_LEVEL
-#define DEBUG_LOG_MAX_LEVEL DEBUG_POSLIB_LOG_MAX_LEVEL
-#else
-#define DEBUG_LOG_MAX_LEVEL LVL_NOLOG
-#endif
-
-#include "api.h"
-#include "mcu.h"
-#include "debug_log.h"
-#include "board.h"
-#include "gpio.h"
-
-#define MAX_EFR32_PIN_NUMBER 16
-
-typedef struct
-{
- uint8_t ext_int;
- uint8_t port;
- uint8_t pin;
-} int_gpio_t;
-
-static int_gpio_t m_pin_map[] = BOARD_INT_PIN_LIST;
-
-/** \brief Compute number of external int GPIO on the board */
-#define BOARD_INT_GPIO_NUMBER (sizeof(m_pin_map) / sizeof(m_pin_map[0]))
-
-typedef struct
-{
- uint8_t pin; //header pin number
- gpio_pull_e pull; //pin pull configuration
- gpio_event_e event; //pin event type
- uint8_t debounce_ms;
- uint32_t last_event_hp;
- on_gpio_event_cb cb; // event callback
-} gpio_conf_t;
-
-/** \brief Table to manage gpio */
-static gpio_conf_t m_gpio_conf[BOARD_INT_GPIO_NUMBER];
-
-bool m_gpio_init = false;
-
-static void gpio_interrupt_handler(void)
-{
- // Check all possible sources
- for (uint8_t i = 0; i < BOARD_INT_GPIO_NUMBER; i++)
- {
- gpio_conf_t * gpio = &m_gpio_conf[i];
-
- if (gpio->pin >= MAX_EFR32_PIN_NUMBER)
- {
- continue;
- }
-
- // Read external interrupt flag
- if ((GPIO->IF & (((uint32_t)1) << m_pin_map[i].ext_int)) != 0)
- {
- gpio_event_e event = hal_gpio_get(m_pin_map[i].port, m_pin_map[i].pin) ? GPIO_EVENT_LH : GPIO_EVENT_HL;
-
- // Call the pin callback
- if (gpio->cb != NULL &&
- (gpio->event == event ||
- gpio->event == GPIO_EVENT_ALL))
- {
- // call imediatelly if debounce not requested
- if (gpio->debounce_ms == 0)
- {
- gpio->cb(gpio->pin, event);
- }
- else
- {
- uint32_t now_hp = lib_time->getTimestampHp();
- uint32_t delta_ms = lib_time->getTimeDiffUs(now_hp, gpio->last_event_hp) * 1000;
-
- // call calback only if debounce is satisfied
- if (delta_ms > gpio->debounce_ms || gpio->last_event_hp == 0)
- {
- gpio->last_event_hp = now_hp;
- gpio->cb(gpio->pin, event);
- }
- }
- }
-
- // Clear external interrupt flag
-#if defined(_SILICON_LABS_32B_SERIES_1)
- GPIO->IFC = (uint32_t) 1 << m_pin_map[i].ext_int;
-#else
- GPIO->IF_CLR = (uint32_t) 1 << m_pin_map[i].ext_int;
-#endif
- }
- }
-}
-
-static bool gpio_enable_interrupt(gpio_conf_t *gpio_conf, uint8_t int_idx)
-{
- int_gpio_t int_pin = m_pin_map[int_idx];
-
- uint8_t ext_int = int_pin.ext_int;
- uint8_t port = int_pin.port;
- uint8_t pin = int_pin.pin;
-
- hal_gpio_set_mode(port,
- pin,
- GPIO_MODE_IN_OD_NOPULL);
- hal_gpio_set(port, pin);
-
- bool enable = (gpio_conf->cb != NULL);
-
- bool high_reg = ext_int >= 8;
- uint8_t shift = (ext_int & 7) * 4;
- uint32_t mask = ~((uint32_t)0xf << shift);
- uint32_t set = 0;
-
- // Select port
- set = enable ? (uint32_t)port << shift : 0;
- if (high_reg)
- {
-#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- GPIO->EXTIPSELH = (GPIO->EXTIPSELH & mask) | set;
-#endif
- }
- else
- {
- GPIO->EXTIPSELL = (GPIO->EXTIPSELL & mask) | set;
- }
-
- // Select pin
- set = enable ? (uint32_t)(pin & 3) << shift : 0;
- if (high_reg)
- {
-#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
- GPIO->EXTIPINSELH = (GPIO->EXTIPINSELH & mask) | set;
-#endif
- }
- else
- {
- GPIO->EXTIPINSELL = (GPIO->EXTIPINSELL & mask) | set;
- }
-
- // Set rising and falling edge sensitivity
- shift = ext_int;
- mask = ~((uint32_t)1 << shift);
- set = enable ? (uint32_t)1 << shift : 0;
- GPIO->EXTIRISE = (GPIO->EXTIRISE & mask) | set;
- GPIO->EXTIFALL = (GPIO->EXTIFALL & mask) | set;
-
- //Clear external interrupt flag
-#if defined(_SILICON_LABS_32B_SERIES_1)
- GPIO->IFC = (uint32_t)1 << shift;
-#else
- GPIO->IF_CLR = (uint32_t)1 << shift;
-#endif
-
- // Enable or disable external interrupt
- GPIO->IEN = (GPIO->IEN & mask) | set;
-
- return true;
-}
-
-static void gpio_init(void)
-{
- if (m_gpio_init)
- {
- return;
- }
-
- // Enable clocks
-#if defined(_SILICON_LABS_32B_SERIES_1)
- CMU->HFBUSCLKEN0 |= CMU_HFBUSCLKEN0_GPIO;
-#elif !defined (EFR32MG21)
- CMU->CLKEN0_SET = CMU_CLKEN0_GPIO;
-#endif
-
- LOG(LVL_DEBUG, "GPIO init");
-
- for (uint8_t i = 0; i < BOARD_INT_GPIO_NUMBER; i++)
- {
- m_gpio_conf[i].pin = MAX_EFR32_PIN_NUMBER;
- m_gpio_conf[i].cb = NULL;
- m_gpio_conf[i].event = GPIO_EVENT_ALL;
- m_gpio_conf[i].pull = GPIO_NOPULL;
-
- //Input No Pull, DOUT enables filter.
- hal_gpio_set_mode(m_pin_map[i].port,
- m_pin_map[i].pin,
- GPIO_MODE_IN_OD_NOPULL);
- hal_gpio_set(m_pin_map[i].port, m_pin_map[i].pin);
- }
-
- // Enable even or odd external interrupts
- lib_system->enableAppIrq(false,
- BOARD_LIS2_USE_EVEN_INT ? GPIO_EVEN_IRQn : GPIO_ODD_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_LO,
- gpio_interrupt_handler);
-
- m_gpio_init = true;
-}
-
-gpio_res_e GPIO_register_for_event(uint8_t pin,
- gpio_pull_e pull,
- gpio_event_e event,
- uint8_t debounce_ms,
- on_gpio_event_cb cb)
-{
- gpio_res_e ret;
- uint8_t idx = BOARD_INT_GPIO_NUMBER;
- uint8_t idx_free = BOARD_INT_GPIO_NUMBER;
-
- if(!m_gpio_init)
- {
- gpio_init();
- }
-
- if( (pin >= MAX_EFR32_PIN_NUMBER) || cb == NULL ||
- event >= GPIO_EVENT_MAX || pull >= GPIO_PULL_MAX )
- {
- return GPIO_RES_FAIL;
- }
-
- for (uint8_t i = 0; i < BOARD_INT_GPIO_NUMBER; i++)
- {
- if (m_gpio_conf[i].pin == pin)
- {
- idx = i;
- break;
- }
- else if (idx_free == BOARD_INT_GPIO_NUMBER && m_gpio_conf[i].cb == NULL)
- {
- idx_free = i;
- }
- }
- idx = (idx == BOARD_INT_GPIO_NUMBER) ? idx_free : idx;
-
- if (idx < BOARD_INT_GPIO_NUMBER)
- {
- m_gpio_conf[idx].pin = pin;
- m_gpio_conf[idx].cb = cb;
- m_gpio_conf[idx].event = event;
- m_gpio_conf[idx].pull = pull;
- m_gpio_conf[idx].debounce_ms = debounce_ms;
- gpio_enable_interrupt(&m_gpio_conf[idx], idx);
- ret = GPIO_RES_OK;
- }
- else
- {
- ret = GPIO_RES_FAIL;
- }
- return ret;
-}
-
-gpio_res_e GPIO_deregister_for_event(uint8_t pin)
-{
- if (!m_gpio_init)
- {
- gpio_init();
- }
-
- for (uint8_t i = 0; i < BOARD_INT_GPIO_NUMBER; i++)
- {
- if (m_gpio_conf[i].pin == pin)
- {
- int_gpio_t int_pin = m_pin_map[i];
- hal_gpio_clear(int_pin.port, int_pin.pin);
-
- m_gpio_conf[i].pin = MAX_EFR32_PIN_NUMBER;
- m_gpio_conf[i].cb = NULL;
- }
- }
-
- return GPIO_RES_OK;
-}
\ No newline at end of file
diff --git a/source/reference_apps/positioning_app/gpio_nrf52.c b/source/reference_apps/positioning_app/gpio_nrf52.c
deleted file mode 100644
index 40c2952a..00000000
--- a/source/reference_apps/positioning_app/gpio_nrf52.c
+++ /dev/null
@@ -1,278 +0,0 @@
-/* Copyright 2020 Wirepas Ltd. All Rights Reserved.
- *
- * See file LICENSE.txt for full license details.
- *
- */
-
-/*
- * \file gpio.c
- * \brief This file implements the GPIO interface to nRF52 chips
- *
- */
-
-#define DEBUG_LOG_MODULE_NAME "GPIO"
-#ifdef DEBUG_POSLIB_LOG_MAX_LEVEL
-#define DEBUG_LOG_MAX_LEVEL DEBUG_POSLIB_LOG_MAX_LEVEL
-#else
-#define DEBUG_LOG_MAX_LEVEL LVL_NOLOG
-#endif
-
-#include "api.h"
-#include "mcu.h"
-#include "debug_log.h"
-#include "gpio.h"
-
-#define MAX_NRF52_PINS 30 //FixMe: use the nrf52.h define if exists
-
-typedef struct
-{
- uint8_t pin; //pin number
- gpio_pull_e pull; //pin pull configuration
- gpio_event_e event; //pin event type
- uint8_t debounce_ms;
- uint32_t last_event_hp;
- on_gpio_event_cb cb; // event callback
-} gpio_conf_t;
-
-/** \brief Table to manage gpio */
-static gpio_conf_t m_gpio_conf[GPIO_MAX];
-bool m_gpio_init = false;
-
-
-static void gpiote_interrupt_handler(void)
-{
- if (NRF_GPIOTE->EVENTS_PORT == 0)
- {
- return;
- }
-
- NRF_GPIOTE->EVENTS_PORT = 0;
- // read any event from peripheral to flush the write buffer:
- EVENT_READBACK = NRF_GPIOTE->EVENTS_PORT;
-
- // Detect the pin generating the irq
- for (uint8_t i = 0; i < GPIO_MAX; i++)
- {
-
- gpio_conf_t * gpio = &m_gpio_conf[i];
-
- if (gpio->pin >= MAX_NRF52_PINS)
- {
- continue;
- }
-
- if (nrf_gpio_pin_latch_get(gpio->pin))
- {
- gpio_event_e event = nrf_gpio_pin_read(gpio->pin) ? GPIO_EVENT_LH : GPIO_EVENT_HL;
-
- //call the pin callback
- if (gpio->cb != NULL &&
- (gpio->event == event ||
- gpio->event == GPIO_EVENT_ALL))
- {
- // call imediatelly if debounce not requested
- if (gpio->debounce_ms == 0)
- {
- gpio->cb(gpio->pin, event);
- }
- else
- {
- uint32_t now_hp = lib_time->getTimestampHp();
- uint32_t delta_ms = lib_time->getTimeDiffUs(now_hp, gpio->last_event_hp) * 1000;
-
- // call calback only if debounce is satisfied
- if ( delta_ms > gpio->debounce_ms || gpio->last_event_hp == 0)
- {
- gpio->last_event_hp = now_hp;
- gpio->cb(gpio->pin, event);
- }
- }
- }
-
- //detect the gpio pin state and set sense to oposite level
- if ( gpio->event == GPIO_EVENT_ALL )
- {
- nrf_gpio_pin_sense_t sense;
-
- sense = (nrf_gpio_pin_read(gpio->pin) == 0) ?
- NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
- nrf_gpio_cfg_sense_set(gpio->pin, sense);
- }
- }
- // Clear the line
- nrf_gpio_pin_latch_clear(gpio->pin);
- }
-}
-
-static bool gpio_enable_interrupt(gpio_conf_t *gpio_conf)
-{
- nrf_gpio_pin_pull_t pull;
- nrf_gpio_pin_sense_t sense;
- bool sense_all = false;
-
- switch (gpio_conf->pull)
- {
- case GPIO_PULLDOWN:
- pull = NRF_GPIO_PIN_PULLDOWN;
- break;
- case GPIO_PULLUP:
- pull = NRF_GPIO_PIN_PULLUP;
- break;
- case GPIO_NOPULL:
- pull = NRF_GPIO_PIN_NOPULL;
- break;
- default:
- return false;
- }
-
- switch (gpio_conf->event)
- {
- case GPIO_EVENT_LH:
- sense = NRF_GPIO_PIN_SENSE_HIGH;
- break;
- case GPIO_EVENT_HL:
- sense = NRF_GPIO_PIN_SENSE_LOW;
- break;
- case GPIO_EVENT_ALL:
- sense = NRF_GPIO_PIN_SENSE_HIGH; //initial state guess
- sense_all = true;
- break;
- default:
- return false;
- }
-
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
- nrf_gpio_cfg_sense_input(gpio_conf->pin, pull, sense);
-
- if (sense_all) //detect the gpio pin state and set sense to oposite level
- {
- sense = (nrf_gpio_pin_read(gpio_conf->pin) == 0) ?
- NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
- nrf_gpio_cfg_sense_set(gpio_conf->pin, sense);
- }
-
- // Clear the line before enabling IRQ
- nrf_gpio_pin_latch_clear(gpio_conf->pin);
- NRF_GPIOTE->INTENSET = GPIOTE_INTENSET_PORT_Msk;
- return true;
-}
-
-static void gpio_init()
-{
- if(m_gpio_init)
- {
- return;
- }
-
- LOG(LVL_DEBUG, "GPIO init");
- for (uint8_t i = 0; i < GPIO_MAX; i++)
- {
- m_gpio_conf[i].pin = MAX_NRF52_PINS;
- m_gpio_conf[i].cb = NULL;
- m_gpio_conf[i].event = GPIO_EVENT_ALL;
- m_gpio_conf[i].pull = GPIO_NOPULL;
- }
-
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
- NRF_GPIOTE->EVENTS_PORT = 0;
-
- // Enable interrupt
- lib_system->clearPendingFastAppIrq(GPIOTE_IRQn);
- lib_system->enableAppIrq(true,
- GPIOTE_IRQn,
- APP_LIB_SYSTEM_IRQ_PRIO_LO,
- gpiote_interrupt_handler);
- m_gpio_init = true;
-}
-
-gpio_res_e GPIO_register_for_event(uint8_t pin,
- gpio_pull_e pull,
- gpio_event_e event,
- uint8_t debounce_ms,
- on_gpio_event_cb cb)
-{
- gpio_res_e ret;
- uint8_t idx = GPIO_MAX;
- uint8_t idx_free = GPIO_MAX;
-
- if(!m_gpio_init)
- {
- gpio_init();
- }
-
- /** FixME: check the macro for nRF52 max pin */
-
- if( (pin >= MAX_NRF52_PINS) || cb == NULL ||
- event >= GPIO_EVENT_MAX || pull >= GPIO_PULL_MAX )
- {
- return GPIO_RES_FAIL;
- }
-
- // find if pin is already registered | find a free slot
- // only one event registration per pin is allowed
-
- for (uint8_t i = 0; i < GPIO_MAX; i++)
- {
- if (m_gpio_conf[i].pin == pin)
- {
- idx = i;
- break;
- } else if (idx_free == GPIO_MAX && m_gpio_conf[i].cb == NULL)
- {
- idx_free = i;
- }
- }
-
- idx = (idx == GPIO_MAX) ? idx_free : idx;
-
- // update if a valid index found
- if (idx < GPIO_MAX)
- {
- m_gpio_conf[idx].pin = pin;
- m_gpio_conf[idx].cb = cb;
- m_gpio_conf[idx].event = event;
- m_gpio_conf[idx].pull = pull;
- m_gpio_conf[idx].debounce_ms = debounce_ms;
- gpio_enable_interrupt(&m_gpio_conf[idx]);
- ret = GPIO_RES_OK;
- }
- else
- {
- ret = GPIO_RES_FAIL;
- }
- return ret;
-}
-
-gpio_res_e GPIO_deregister_for_event(uint8_t pin)
-{
-
- bool pin_active = false;
-
- if(!m_gpio_init)
- {
- gpio_init();
- }
-
- for (uint8_t i = 0; i < GPIO_MAX; i++)
- {
- if (m_gpio_conf[i].pin == pin)
- {
- nrf_gpio_input_disconnect(pin);
- m_gpio_conf[i].pin = MAX_NRF52_PINS;
- m_gpio_conf[i].cb = NULL;
- }
- else if(m_gpio_conf[i].cb != NULL)
- {
- pin_active = true;
- }
- }
-
- // disable PORT interrupt if no pin is active
- if(!pin_active)
- {
- NRF_GPIOTE->INTENCLR = GPIOTE_INTENSET_PORT_Msk;
- NRF_GPIOTE->EVENTS_PORT = 0;
- }
- return GPIO_RES_OK;
-}
-
diff --git a/source/reference_apps/positioning_app/makefile b/source/reference_apps/positioning_app/makefile
index 2d2258ab..2b80cd1c 100644
--- a/source/reference_apps/positioning_app/makefile
+++ b/source/reference_apps/positioning_app/makefile
@@ -56,7 +56,7 @@ endif
#Button support
ifeq ($(button_enabled),yes)
-SRCS += $(SRCS_PATH)gpio_nrf52.c
+HAL_BUTTON=yes
CFLAGS += -DBUTTON_ENABLED
endif
@@ -71,5 +71,4 @@ STACK_STATE_CBS=1
ifneq ($(motion_sensor),)
INCLUDES += -I$(SRCS_PATH)/motion/
include $(SRCS_PATH)/motion/makefile_motion.mk
-endif
-
+endif
diff --git a/source/reference_apps/positioning_app/motion/lis2/lis2_dev.h b/source/reference_apps/positioning_app/motion/lis2/lis2_dev.h
index a6111bc4..2d4afbbc 100644
--- a/source/reference_apps/positioning_app/motion/lis2/lis2_dev.h
+++ b/source/reference_apps/positioning_app/motion/lis2/lis2_dev.h
@@ -8,22 +8,10 @@
#ifdef LIS2DH12
#include "lis2dh12_reg.h"
-
-#ifdef LIS2DH12_I2C
-
-#elif defined LIS2DH12_SPI
-#define BOARD_SPI_LIS2_CS_PIN BOARD_SPI_LIS2DH12_CS_PIN
-#endif
#endif
#ifdef LIS2DW12
#include "lis2dw12_reg.h"
-
-#ifdef LIS2DW12_I2C
-
-#elif defined LIS2DW12_SPI
-#define BOARD_SPI_LIS2_CS_PIN BOARD_SPI_LIS2DW12_CS_PIN
-#endif
#endif
void LIS2_dev_init(stmdev_ctx_t * dev);
diff --git a/source/reference_apps/positioning_app/motion/lis2/lis2_dev_i2c.c b/source/reference_apps/positioning_app/motion/lis2/lis2_dev_i2c.c
index 14d47f67..e3104f37 100644
--- a/source/reference_apps/positioning_app/motion/lis2/lis2_dev_i2c.c
+++ b/source/reference_apps/positioning_app/motion/lis2/lis2_dev_i2c.c
@@ -16,17 +16,16 @@
#include "hal_api.h"
#include "debug_log.h"
#include "i2c.h"
+#include "gpio.h"
#include "api.h"
#include "lis2_dev.h"
#ifdef LIS2DH12_I2C
#define LIS2_I2C_ADD_L LIS2DH12_I2C_ADD_L
#define LIS2_I2C_ADD_H LIS2DH12_I2C_ADD_H
-#define BOARD_I2C_LIS2_SA0 BOARD_I2C_LIS2DH12_SA0
#elif defined LIS2DW12_I2C
#define LIS2_I2C_ADD_L LIS2DW12_I2C_ADD_L
#define LIS2_I2C_ADD_H LIS2DW12_I2C_ADD_H
-#define BOARD_I2C_LIS2_SA0 BOARD_I2C_LIS2DW12_SA0
#endif
/** Maximum I2C write transfer */
@@ -102,10 +101,10 @@ static int32_t lis2_readI2C(void * handle,
if (res == I2C_RES_OK || res == I2C_RES_ALREADY_INITIALIZED)
{
i2c_xfer_t xfer_rx = {
- .address = m_lis2_address,
- .write_ptr = tx,
- .write_size = 1,
- .read_ptr = rx,
+ .address = m_lis2_address,
+ .write_ptr = tx,
+ .write_size = 1,
+ .read_ptr = rx,
.read_size = len,
.custom = 0};
@@ -121,7 +120,15 @@ static int32_t lis2_readI2C(void * handle,
void LIS2_dev_init(stmdev_ctx_t * dev)
{
- m_lis2_address = (BOARD_I2C_LIS2_SA0 == 0) ? LIS2_I2C_ADD_L >> 1 :
+ gpio_out_cfg_t gpio_conf = {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = BOARD_I2C_LIS2DX12_SA0 ? GPIO_LEVEL_HIGH : GPIO_LEVEL_LOW
+ };
+
+ Gpio_outputSetCfg(BOARD_GPIO_ID_LIS2DX12_SA0, &gpio_conf);
+
+
+ m_lis2_address = (BOARD_I2C_LIS2DX12_SA0 == 0) ? LIS2_I2C_ADD_L >> 1 :
LIS2_I2C_ADD_H >> 1;
dev->handle = NULL;
dev->write_reg = lis2_writeI2C;
diff --git a/source/reference_apps/positioning_app/motion/lis2/lis2_dev_spi.c b/source/reference_apps/positioning_app/motion/lis2/lis2_dev_spi.c
index b9b163cb..374805a5 100644
--- a/source/reference_apps/positioning_app/motion/lis2/lis2_dev_spi.c
+++ b/source/reference_apps/positioning_app/motion/lis2/lis2_dev_spi.c
@@ -16,6 +16,7 @@
#include "hal_api.h"
#include "debug_log.h"
#include "spi.h"
+#include "gpio.h"
#include "api.h"
#include "lis2_dev.h"
@@ -45,14 +46,10 @@ static spi_conf_t m_spi_conf = {
*/
void lis2_select_chip(bool select)
{
- if (select)
- {
- nrf_gpio_pin_clear(BOARD_SPI_LIS2_CS_PIN);
- }
- else
- {
- nrf_gpio_pin_set(BOARD_SPI_LIS2_CS_PIN);
- }
+ gpio_level_e level;
+
+ level = select ? GPIO_LEVEL_LOW : GPIO_LEVEL_HIGH;
+ Gpio_outputWrite(BOARD_GPIO_ID_LIS2DX12_SPI_CS, level);
}
/**
@@ -145,10 +142,13 @@ static int32_t lis2_spi_write(void *handle,
void LIS2_dev_init(stmdev_ctx_t * dev)
{
- nrf_gpio_pin_dir_set(BOARD_SPI_LIS2_CS_PIN, NRF_GPIO_PIN_DIR_OUTPUT);
- nrf_gpio_cfg_output(BOARD_SPI_LIS2_CS_PIN);
- nrf_gpio_pin_set(BOARD_SPI_LIS2_CS_PIN);
- LOG(LVL_DEBUG, "BOARD_SPI_LIS2_CS_PIN: %u", BOARD_SPI_LIS2_CS_PIN);
+ gpio_out_cfg_t gpio_conf = {
+ .out_mode_cfg = GPIO_OUT_MODE_PUSH_PULL,
+ .level_default = GPIO_LEVEL_HIGH
+ };
+
+ Gpio_outputSetCfg(BOARD_GPIO_ID_LIS2DX12_SPI_CS, &gpio_conf);
+ LOG(LVL_DEBUG, "BOARD_GPIO_ID_LIS2DX12_SPI_CS: %u", BOARD_GPIO_ID_LIS2DX12_SPI_CS);
dev->handle = NULL;
dev->write_reg = lis2_spi_write;
dev->read_reg = lis2_spi_read;
diff --git a/source/reference_apps/positioning_app/motion/lis2/lis2dh12_wrapper.h b/source/reference_apps/positioning_app/motion/lis2/lis2dh12_wrapper.h
index 58e21de1..41a86b8f 100644
--- a/source/reference_apps/positioning_app/motion/lis2/lis2dh12_wrapper.h
+++ b/source/reference_apps/positioning_app/motion/lis2/lis2dh12_wrapper.h
@@ -12,12 +12,12 @@
#include "board.h"
/** LIS2DH12 interrupt pin for motion monitoring, @note Only one pin shall be defined in board.h */
-#ifdef BOARD_LIS2DH12_INT1_PIN
+#ifdef BOARD_GPIO_ID_LIS2DX12_INT1
#define LIS2DH12_MOTION_USE_INT1
-#define MOTION_MON_INT_PIN BOARD_LIS2DH12_INT1_PIN
-#elif defined BOARD_LIS2DH12_INT2_PIN
+#define MOTION_MON_INT_GPIO_ID BOARD_GPIO_ID_LIS2DX12_INT1
+#elif defined BOARD_GPIO_ID_LIS2DH12_INT2
#define LIS2DH12_MOTION_USE_INT2
-#define MOTION_MON_INT_PIN BOARD_LIS2DH12_INT2_PIN
+#define MOTION_MON_INT_GPIO_ID BOARD_GPIO_ID_LIS2DH12_INT2
#endif
/** LIS2DH12 montion monitoring sampling rate */
diff --git a/source/reference_apps/positioning_app/motion/lis2/lis2dw12_wrapper.h b/source/reference_apps/positioning_app/motion/lis2/lis2dw12_wrapper.h
index 07498579..39a16869 100644
--- a/source/reference_apps/positioning_app/motion/lis2/lis2dw12_wrapper.h
+++ b/source/reference_apps/positioning_app/motion/lis2/lis2dw12_wrapper.h
@@ -12,12 +12,12 @@
#include "board.h"
/** LIS2DW12 interrupt pin for motion monitoring, @note Only one pin shall be defined in board.h */
-#ifdef BOARD_LIS2DW12_INT1_PIN
+#ifdef BOARD_GPIO_ID_LIS2DX12_INT1
#define LIS2DW12_MOTION_USE_INT1
-#define MOTION_MON_INT_PIN BOARD_LIS2DW12_INT1_PIN
+#define MOTION_MON_INT_GPIO_ID BOARD_GPIO_ID_LIS2DX12_INT1
#elif defined BOARD_LIS2DW12_INT2_PIN
#define LIS2DW12_MOTION_USE_INT2
-#define MOTION_MON_INT_PIN BOARD_LIS2DW12_INT2_PIN
+#define MOTION_MON_INT_GPIO_ID BOARD_GPIO_ID_LIS2DW12_INT2
#endif
/** LIS2DW12 montion monitoring sampling rate */
diff --git a/source/reference_apps/positioning_app/motion/makefile_motion.mk b/source/reference_apps/positioning_app/motion/makefile_motion.mk
index a7c7e4bb..1f5c3413 100644
--- a/source/reference_apps/positioning_app/motion/makefile_motion.mk
+++ b/source/reference_apps/positioning_app/motion/makefile_motion.mk
@@ -8,12 +8,9 @@ CFLAGS += -DMOTION_SUPPORTED
# Generic accelerometer interface
SRCS += $(SRCS_PATH)motion/motion.c
-ifeq ($(MCU),nrf52)
- SRCS += $(SRCS_PATH)gpio_nrf52.c
-else ifeq ($(MCU),efr32)
- SRCS += $(SRCS_PATH)gpio_efr32.c
-endif
INCLUDES += -I$(SRCS_PATH)motion/
+# GPIO HAL is required by the motion module
+HAL_GPIO=yes
###### LIS2DH12 support start ######
#LIS2DH12 I2C
diff --git a/source/reference_apps/positioning_app/motion/motion.c b/source/reference_apps/positioning_app/motion/motion.c
index e1a77525..47feaf60 100644
--- a/source/reference_apps/positioning_app/motion/motion.c
+++ b/source/reference_apps/positioning_app/motion/motion.c
@@ -30,10 +30,10 @@ typedef enum
/** Monitoring variables */
static bool m_mon_enabled = false;
static posapp_motion_mon_settings_t m_mon_cfg = {
- .threshold_mg = 0,
+ .threshold_mg = 0,
.duration_ms = 0,
.cb = NULL};
-
+
/** Acceletometer data sampling variables */
static bool m_acc_init = false;
static bool m_acc_sampling = false;
@@ -55,7 +55,7 @@ static uint32_t set_motion_static()
return APP_SCHEDULER_STOP_TASK;
}
-static void acc_event_cb(uint8_t pin, gpio_event_e event)
+static void acc_event_cb(gpio_id_t id, gpio_in_event_e event)
{
if (m_mon_enabled && m_mon_cfg.cb != NULL)
{
@@ -91,7 +91,7 @@ static uint32_t accelerometer_task(void)
}
break;
}
-
+
case ACC_READ:
{
if (ACC_readMeasurement(&m_meas))
@@ -102,18 +102,18 @@ static uint32_t accelerometer_task(void)
else
{
LOG(LVL_ERROR, "Accelerometer measurement error");
- m_acc_cb(NULL);
+ m_acc_cb(NULL);
}
m_acc_sampling = false;
- return APP_SCHEDULER_STOP_TASK;
+ return APP_SCHEDULER_STOP_TASK;
break;
}
-
+
default:
{
m_acc_sampling = false;
- return APP_SCHEDULER_STOP_TASK;
+ return APP_SCHEDULER_STOP_TASK;
}
break;
}
@@ -121,13 +121,20 @@ static uint32_t accelerometer_task(void)
}
static posapp_motion_ret_e enable_monitoring(void)
-{
+{
+ gpio_res_e gpio_res;
+ const gpio_in_cfg_t motion_mon_int_cfg =
+ {
+ .event_cb = acc_event_cb,
+ .event_cfg = GPIO_IN_EVENT_RISING_EDGE,
+ .in_mode_cfg = GPIO_IN_PULL_NONE
+ };
if (!m_acc_init)
{
LOG(LVL_ERROR, "Accelerometer not initialised");
m_mon_enabled = false;
- return POSAPP_MOTION_RET_ACC_INIT_ERROR;
+ return POSAPP_MOTION_RET_ACC_INIT_ERROR;
}
if (!ACC_enableMonitoring(m_mon_cfg.threshold_mg, m_mon_cfg.duration_ms))
@@ -136,13 +143,12 @@ static posapp_motion_ret_e enable_monitoring(void)
m_mon_enabled = false;
return POSAPP_MOTION_RET_ACC_INIT_ERROR;
}
-
+
//FixME: to determing through testing if we need debounce (i.e. limit acc. irq fireing)
- if (GPIO_register_for_event(MOTION_MON_INT_PIN,
- GPIO_NOPULL,
- GPIO_EVENT_LH,
- 0,
- acc_event_cb) != GPIO_RES_OK)
+
+ gpio_res = Gpio_inputSetCfg(MOTION_MON_INT_GPIO_ID, &motion_mon_int_cfg);
+
+ if (gpio_res != GPIO_RES_OK)
{
LOG(LVL_ERROR, "Cannot enable acc. interrupt pin");
@@ -151,7 +157,7 @@ static posapp_motion_ret_e enable_monitoring(void)
}
else
{
- LOG(LVL_DEBUG, "Acc pin %u registered", MOTION_MON_INT_PIN);
+ LOG(LVL_DEBUG, "Acc pin %u registered", MOTION_MON_INT_GPIO_ID);
}
m_mon_enabled = true;
@@ -162,21 +168,27 @@ static posapp_motion_ret_e enable_monitoring(void)
static posapp_motion_ret_e disable_monitoring(void)
{
bool ret;
+ const gpio_in_cfg_t motion_mon_int_cfg =
+ {
+ .event_cb = NULL,
+ .event_cfg = GPIO_IN_EVENT_NONE,
+ .in_mode_cfg = GPIO_IN_DISABLED
+ };
if (!m_mon_enabled)
{
return POSAPP_MOTION_RET_ERROR;
}
- ret = (GPIO_deregister_for_event(MOTION_MON_INT_PIN) != GPIO_RES_OK);
-
- return ret ? POSAPP_MOTION_RET_OK : POSAPP_MOTION_RET_ERROR;
+ ret = (Gpio_inputSetCfg(MOTION_MON_INT_GPIO_ID, &motion_mon_int_cfg) != GPIO_RES_OK);
+
+ return ret ? POSAPP_MOTION_RET_OK : POSAPP_MOTION_RET_ERROR;
}
posapp_motion_ret_e PosAppMotion_startMonitoring(posapp_motion_mon_settings_t * cfg)
{
-
+
if (!m_acc_init)
{
LOG(LVL_ERROR, "Aceelerometer not initialized");
@@ -206,12 +218,12 @@ posapp_motion_ret_e PosAppMotion_startMonitoring(posapp_motion_mon_settings_t *
if (cfg->cb == NULL)
{
LOG(LVL_ERROR, "Monitoring callback is NULL");
- return POSAPP_MOTION_RET_INVALID_PARAMETER;
+ return POSAPP_MOTION_RET_INVALID_PARAMETER;
}
m_mon_cfg = *cfg;
return enable_monitoring();
-
+
}
posapp_motion_ret_e PosAppMotion_stopMonitoring()
@@ -257,7 +269,7 @@ posapp_motion_ret_e PosAppMotion_getAcceleration(posapp_motion_acc_callback_f cb
m_acc_state = ACC_START;
App_Scheduler_addTask_execTime(accelerometer_task, APP_SCHEDULER_SCHEDULE_ASAP, 500);
-
+
return POSAPP_MOTION_RET_OK;
}
@@ -268,7 +280,7 @@ posapp_motion_ret_e PosAppMotion_init()
LOG(LVL_ERROR, "Cannot initialize the accelerometer");
m_acc_init = false;
return POSAPP_MOTION_RET_ACC_INIT_ERROR;
- }
+ }
m_acc_init = true;
LOG(LVL_DEBUG, "Accelerometer intitialised");
diff --git a/source/reference_apps/positioning_app/persistent_config/genConfigHex.py b/source/reference_apps/positioning_app/persistent_config/genConfigHex.py
index 5d8e8ddd..cb61f93b 100644
--- a/source/reference_apps/positioning_app/persistent_config/genConfigHex.py
+++ b/source/reference_apps/positioning_app/persistent_config/genConfigHex.py
@@ -160,15 +160,7 @@ def main():
metavar="VALUE",
required=True,
help="Address of the storage area ([area:app_persistent])\n"
- "defined in scratchpad_ini/scratchpad_.ini file\n"
- "Default values per mcu are :\n"
- " - NRF52832 : 512000 (0x7D000)\n"
- " - NRF52833 : 512000 (0x7D000)\n"
- " - NRF52840 : 1036288 (0xFD000)\n"
- " - EFR32xg1x (512k) : 518144 (0x7E800)\n"
- " - EFR32xg1x (1024k): 1042432 (0xFE800)\n"
- " - EFR32xg22 (512k) : 499712 (0x7A000)\n"
- " - EFR32xg21 (1024k): 1024000 (0xFA000)")
+ "defined in mcu//ini_files/_app.ini file\n")
try:
args = parser.parse_args()
diff --git a/source/unitary_apps/aes/config.mk b/source/unitary_apps/aes/config.mk
index b3de4103..f9fa875c 100644
--- a/source/unitary_apps/aes/config.mk
+++ b/source/unitary_apps/aes/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
# Define a specific application area_id
app_specific_area_id=0x8cad1b
diff --git a/source/unitary_apps/app_persistent/app.c b/source/unitary_apps/app_persistent/app.c
index f02dd93c..48976fef 100644
--- a/source/unitary_apps/app_persistent/app.c
+++ b/source/unitary_apps/app_persistent/app.c
@@ -20,10 +20,8 @@
#include "api.h"
#include "node_configuration.h"
#include "led.h"
-#include "button.h"
#include "app_persistent.h"
-
#define DEBUG_LOG_MODULE_NAME "APP_PERS"
#define DEBUG_LOG_MAX_LEVEL LVL_INFO
#include "debug_log.h"
@@ -46,9 +44,6 @@ void App_init(const app_global_functions_t * functions)
LOG_INIT();
- // Initialize peripherals
- Led_init();
-
Led_set(0, true);
LOG(LVL_INFO, "App_persistent example started\n");
diff --git a/source/unitary_apps/app_persistent/config.mk b/source/unitary_apps/app_persistent/config.mk
index d0fa210a..23270423 100644
--- a/source/unitary_apps/app_persistent/config.mk
+++ b/source/unitary_apps/app_persistent/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/appconfig/config.mk b/source/unitary_apps/appconfig/config.mk
index c6e59787..6afd6ea5 100644
--- a/source/unitary_apps/appconfig/config.mk
+++ b/source/unitary_apps/appconfig/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/blink/app.c b/source/unitary_apps/blink/app.c
index 2bfafcc9..f9dc2958 100644
--- a/source/unitary_apps/blink/app.c
+++ b/source/unitary_apps/blink/app.c
@@ -119,11 +119,6 @@ void App_init(const app_global_functions_t * functions)
return;
}
- // Set up LEDs
- Led_init();
-
- // Set up buttons
- Button_init();
uint_fast8_t num_buttons = Button_get_number();
for (uint_fast8_t button_id = 0; button_id < num_buttons; button_id++)
{
diff --git a/source/unitary_apps/diradv/app.c b/source/unitary_apps/diradv/app.c
index dc972890..6326f07c 100644
--- a/source/unitary_apps/diradv/app.c
+++ b/source/unitary_apps/diradv/app.c
@@ -203,15 +203,10 @@ void App_init(const app_global_functions_t * functions)
return;
}
- // Initialize buttons
- Button_init();
// Query value of button 1
bool pressed = false;
Button_getState(0, &pressed);
- // Initialize leds
- Led_init();
-
// Override node role
if (pressed)
{
@@ -244,4 +239,3 @@ void App_init(const app_global_functions_t * functions)
*/
lib_state->startStack();
}
-
diff --git a/source/unitary_apps/local_provisioning/app.c b/source/unitary_apps/local_provisioning/app.c
index fd1d027d..763334f8 100644
--- a/source/unitary_apps/local_provisioning/app.c
+++ b/source/unitary_apps/local_provisioning/app.c
@@ -107,8 +107,6 @@ void App_init(const app_global_functions_t * functions)
LOG_INIT();
LOG(LVL_INFO, "Starting");
- Button_init();
- Led_init();
Local_provisioning_init(NULL, on_prov_proxy_enabled_cb);
if (Local_provisioning_is_provisioned())
diff --git a/source/unitary_apps/local_provisioning/config.mk b/source/unitary_apps/local_provisioning/config.mk
index c434e908..c1f2dc43 100644
--- a/source/unitary_apps/local_provisioning/config.mk
+++ b/source/unitary_apps/local_provisioning/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
# App specific configuration
#
diff --git a/source/unitary_apps/provisioning_joining_node/app.c b/source/unitary_apps/provisioning_joining_node/app.c
index 36f5788b..30d11677 100644
--- a/source/unitary_apps/provisioning_joining_node/app.c
+++ b/source/unitary_apps/provisioning_joining_node/app.c
@@ -153,7 +153,6 @@ void App_init(const app_global_functions_t * functions)
LOG(LVL_DEBUG, " - net addr: %06X", net_addr);
LOG(LVL_DEBUG, " - net ch: %d", net_channel);
- Button_init();
Button_register_for_event(0, BUTTON_PRESSED, button_0_cb);
if (!Storage_init())
diff --git a/source/unitary_apps/provisioning_joining_node/config.mk b/source/unitary_apps/provisioning_joining_node/config.mk
index 4e3fc049..8c257f18 100644
--- a/source/unitary_apps/provisioning_joining_node/config.mk
+++ b/source/unitary_apps/provisioning_joining_node/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/provisioning_joining_node/genConfigHex.py b/source/unitary_apps/provisioning_joining_node/genConfigHex.py
index 7092c730..d8c43751 100644
--- a/source/unitary_apps/provisioning_joining_node/genConfigHex.py
+++ b/source/unitary_apps/provisioning_joining_node/genConfigHex.py
@@ -90,14 +90,15 @@ def main():
help="Address of the storage area ([area:app_persistent]) "
"defined in mcu//ini_files/_app.ini file\n"
"Default values per mcu are :\n"
- " - NRF52832 : 499712 (0x7A000)\n"
- " - NRF52833 : 499712 (0x7A000)\n"
- " - NRF52840 : 1024000 (0xFA000)\n"
- " - EFR32xg1x (512k) : 503808 (0x7B000)\n"
- " - EFR32xg1x (1024k): 1028096 (0xFB000)\n"
- " - EFR32xg22 (512k) : 491520 (0x78000)\n"
- " - EFR32xg21 (768k) : 753664 (0xB8000)\n"
- " - EFR32xg21 (1024k): 1015808 (0xF8000)")
+ " - NRF52832 : 499712 (0x7A000)\n"
+ " - NRF52833 : 499712 (0x7A000)\n"
+ " - NRF52840 : 1024000 (0xFA000)\n"
+ " - EFR32xg1x (512k) : 503808 (0x7B000)\n"
+ " - EFR32xg1x (1024k): 1028096 (0xFB000)\n"
+ " - EFR32xg22 (512k) : 491520 (0x78000)\n"
+ " - EFR32xg21 (768k) : 753664 (0xB8000)\n"
+ " - EFR32xg21 (1024k): 1015808 (0xF8000)\n"
+ " - EFR32xg23 (512k) : 134709248 (0x8078000)")
try:
args = parser.parse_args()
diff --git a/source/unitary_apps/provisioning_proxy/app.c b/source/unitary_apps/provisioning_proxy/app.c
index aa1a366d..bb1629f0 100644
--- a/source/unitary_apps/provisioning_proxy/app.c
+++ b/source/unitary_apps/provisioning_proxy/app.c
@@ -146,7 +146,6 @@ void App_init(const app_global_functions_t * functions)
Provisioning_Proxy_init(&conf);
- Button_init();
Button_register_for_event(0, BUTTON_PRESSED, button_0_cb);
/* Start the stack. */
diff --git a/source/unitary_apps/provisioning_proxy/config.mk b/source/unitary_apps/provisioning_proxy/config.mk
index d8529416..c292235f 100644
--- a/source/unitary_apps/provisioning_proxy/config.mk
+++ b/source/unitary_apps/provisioning_proxy/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/scheduler/app.c b/source/unitary_apps/scheduler/app.c
index e660438b..da3822de 100644
--- a/source/unitary_apps/scheduler/app.c
+++ b/source/unitary_apps/scheduler/app.c
@@ -141,10 +141,6 @@ void App_init(const app_global_functions_t * functions)
LOG_INIT();
- // Initialize peripherals
- Led_init();
- Button_init();
-
// Launch two periodic task with different period
App_Scheduler_addTask_execTime(periodic_task_50ms, APP_SCHEDULER_SCHEDULE_ASAP, 5);
App_Scheduler_addTask_execTime(periodic_task_500ms, APP_SCHEDULER_SCHEDULE_ASAP, 5);
diff --git a/source/unitary_apps/scheduler/config.mk b/source/unitary_apps/scheduler/config.mk
index d0fa210a..23270423 100644
--- a/source/unitary_apps/scheduler/config.mk
+++ b/source/unitary_apps/scheduler/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/shared_data/config.mk b/source/unitary_apps/shared_data/config.mk
index 000b6f1a..3dc68110 100644
--- a/source/unitary_apps/shared_data/config.mk
+++ b/source/unitary_apps/shared_data/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/source/unitary_apps/tinycbor/config.mk b/source/unitary_apps/tinycbor/config.mk
index ac5747e2..8f46d49f 100644
--- a/source/unitary_apps/tinycbor/config.mk
+++ b/source/unitary_apps/tinycbor/config.mk
@@ -1,5 +1,5 @@
# Boards compatible with this app
-TARGET_BOARDS := silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
+TARGET_BOARDS := pca10090 silabs_brd4254a efr32_template pca10059 silabs_brd4180b pca10056 nrf52_template silabs_brd4184a silabs_brd4181b promistel_rpi_hat pca10090_low_tx_power pca10100 ublox_b204 tbsense2 pca10112 pca10040 bgm220-ek4314a wuerth_261101102 pca10090_nrf52840 silabs_brd4210a mdbt50q_rx nrf52832_mdk_v2 ruuvitag pan1780 silabs_brd4312a silabs_brd4253a
#
# Network default settings configuration
#
diff --git a/tools/bootloader_config.py b/tools/bootloader_config.py
index d6fdf3eb..3209dcfb 100755
--- a/tools/bootloader_config.py
+++ b/tools/bootloader_config.py
@@ -98,6 +98,7 @@ class AreaDesc(object):
PERSISTENT_TYPE = 3
SCRATCHPAD_TYPE = 4
USER_TYPE = 5
+ MODEMFW_TYPE = 6
def __init__(self, area_id, address, length, flags, area_type):
"""Area descriptor creation
@@ -119,7 +120,7 @@ def __init__(self, area_id, address, length, flags, area_type):
raise ValueError("wrong flags for area id=%s", id)
self.flags = flags
- if area_type < AreaDesc.BOOTLOADER_TYPE or area_type > AreaDesc.USER_TYPE:
+ if area_type < AreaDesc.BOOTLOADER_TYPE or area_type > AreaDesc.MODEMFW_TYPE:
raise ValueError("wrong area type for area id=%s", id)
self.type = area_type
diff --git a/tools/firmware_selector.py b/tools/firmware_selector.py
index 92a3621b..c580ba73 100755
--- a/tools/firmware_selector.py
+++ b/tools/firmware_selector.py
@@ -10,7 +10,7 @@
import argparse
import textwrap
from os import listdir
-from os.path import isfile, join
+from os.path import isfile, join, exists
from shutil import copyfile
# Python 2 and Python 3 support
@@ -107,6 +107,8 @@ def is_compatible(self, target_config):
elif key == "mcu_mem_var":
# Handle in previous case
continue
+ elif key == "modem_fw":
+ continue
else:
# print("{} vs {}".format(self.general[key], target_config[key]))
# Other keys must match
@@ -274,6 +276,9 @@ def main():
parser.add_argument("--mode", "-mo",
help = "Special mode for the binary",
default = None)
+ parser.add_argument("--modem_fw", "-mfw",
+ help = "Modem firmware image file name",
+ default = None)
try:
args = parser.parse_args()
@@ -314,6 +319,9 @@ def main():
target_config['mac_profileid'] = args.mac_profileid
if args.mode not in (None, ''):
target_config['mode'] = args.mode
+ if args.modem_fw not in (None, ''):
+ target_config['modem_fw'] = args.modem_fw
+
if args.firmware_type == "wp_bootloader":
# Set it as a string instead of bool to ease the following check
@@ -355,6 +363,12 @@ def main():
# Copy conf file and firmware binary to output folder
copyfile(conf_file, os.path.join(args.output_path, args.output_name + '.conf'))
copyfile(binary_file, os.path.join(args.output_path, args.output_name + firmware_suffix))
+ if args.modem_fw is not None and len(args.modem_fw) != 0 and args.radio != "none":
+ binary_path = os.path.split(conf_file)[0]
+ modem_fw_filename = possible_firmwares[0][1].general['modem_fw']
+ modem_fw_file = os.path.join(binary_path,modem_fw_filename)
+ if exists(modem_fw_file):
+ copyfile(modem_fw_file, os.path.join(args.output_path, 'modem_fw.cbor'))
if args.unlocked:
print_unprotected_bootloader()
diff --git a/tools/genscratchpad.py b/tools/genscratchpad.py
index ca8da202..9ab66a95 100755
--- a/tools/genscratchpad.py
+++ b/tools/genscratchpad.py
@@ -68,6 +68,8 @@ def __init__(self, file_spec = None, data = None,
# Set default values.
self.area_id = 0x00000000
self.version = version
+ self.compressable = None
+ self.encryptable = None
self.compressed = False
self.encrypted = False
@@ -79,58 +81,91 @@ def __init__(self, file_spec = None, data = None,
# File specification given, parse it.
version, self.area_id, filename = self.parse_file_spec(file_spec)
self.version = self.parse_version(version)
-
- # Read data from file.
- memory = hextool.Memory()
- hextool.load_intel_hex(memory, filename = filename)
-
- if memory.num_ranges == 0:
- # No data found in file.
- raise ValueError("file contains no data: '%s'" % filename)
- elif (memory.max_address -
- memory.min_address > self.MAX_NUM_BYTES_PER_FILE):
- raise ValueError("file too big: '%s'" % filename)
-
- # Convert Memory object to a flat bytearray.
- self.data = memory[memory.min_address:memory.max_address]
- self.raw_data = memory[memory.min_address:memory.max_address]
+ self.filename = filename
+
+ # determine what to do based on the file extension
+ filename_base, filename_ext = os.path.splitext(filename)
+ if filename_ext == '.hex':
+ # Read data from file.
+ memory = hextool.Memory()
+ hextool.load_intel_hex(memory, filename = filename)
+
+ if memory.num_ranges == 0:
+ # No data found in file.
+ raise ValueError("file contains no data: '%s'" % filename)
+ elif (memory.max_address -
+ memory.min_address > self.MAX_NUM_BYTES_PER_FILE):
+ raise ValueError("file too big: '%s'" % filename)
+
+ self.compressable = True
+ self.encryptable = True
+ # Convert Memory object to a flat bytearray.
+ self.data = memory[memory.min_address:memory.max_address]
+ self.raw_data = memory[memory.min_address:memory.max_address]
+ elif filename_ext == '.cbor':
+ self.compressable = False
+ self.encryptable = False
+ memory = hextool.Memory()
+ hextool.load_binary(memory, filename = filename)
+ self.data = memory[0:memory.num_bytes]
+ self.raw_data = memory[0:memory.num_bytes]
+ else:
+ raise ValueError("Unsupported file extension: '%s'" % filename)
# Create a file header for uncompressed, unencrypted data.
self.header = self.make_file_header(self.area_id, len(self.data),
*self.version)
def compress(self):
- if self.compressed:
- raise ValueError("data already compressed")
+ if not self.compressable:
+ # the length of the scratchpad file must be multiple of 16,
+ # extend the bytearray to next multiple of 16
+ data_pld_len = len(self.data)
+ num_blocks = (data_pld_len + self.BLOCK_LENGTH - 1) // \
+ self.BLOCK_LENGTH
+ fill_zeros = num_blocks * InFile.BLOCK_LENGTH - data_pld_len
+ self.data.extend(bytearray([0]*fill_zeros))
+ data_length = len(self.data)
+ pad = data_length - data_pld_len
- # OPTIMIZE: Avoid extra conversions between bytearrays and bytes.
- # Compress data. zlib.compress() does not accept
- # bytearrays, so convert bytearray to bytes.
- compressed_data = bytearray(zlib.compress(bytes(self.data), 9))
+ else:
+ if self.compressed:
+ raise ValueError("data already compressed")
- # Determine compressed data length without
- # zlib header and Adler-32 checksum.
- comp_data_len = len(compressed_data) - 2 - 4
+ # OPTIMIZE: Avoid extra conversions between bytearrays and bytes.
+ # Compress data. zlib.compress() does not accept
+ # bytearrays, so convert bytearray to bytes.
+ compressed_data = bytearray(zlib.compress(bytes(self.data), 9))
- # Pad size to a multiple of block length.
- num_blocks = (comp_data_len + self.BLOCK_LENGTH - 1) // \
- self.BLOCK_LENGTH
+ # Determine compressed data length without
+ # zlib header and Adler-32 checksum.
+ comp_data_len = len(compressed_data) - 2 - 4
- # Mark data as compressed.
- self.compressed = True
+ # Pad size to a multiple of block length.
+ num_blocks = (comp_data_len + self.BLOCK_LENGTH - 1) // \
+ self.BLOCK_LENGTH
- # Create a bytearray object for compressed data.
- self.data = bytearray(num_blocks * InFile.BLOCK_LENGTH)
+ # Mark data as compressed.
+ self.compressed = True
- # Copy compressed data to bytearray, but leave
- # out zlib header and Adler-32 checksum.
- self.data[:comp_data_len] = compressed_data[2:-4]
+ # Create a bytearray object for compressed data.
+ self.data = bytearray(num_blocks * InFile.BLOCK_LENGTH)
+
+ # Copy compressed data to bytearray, but leave
+ # out zlib header and Adler-32 checksum.
+ self.data[:comp_data_len] = compressed_data[2:-4]
+ data_length = len(self.data)
+ pad = 0x00000000
# Update the file header now that data length has changed.
- self.header = self.make_file_header(self.area_id, len(self.data),
- *self.version)
+ self.header = self.make_file_header(self.area_id, data_length,
+ *self.version, pad)
def encrypt(self, cipher):
+
+ if not self.encryptable:
+ return
+
if self.encrypted:
raise ValueError("data already encrypted")
@@ -211,7 +246,8 @@ def parse_version(version):
@staticmethod
def make_file_header(areaid, length,
- ver_major, ver_minor, ver_maint, ver_devel):
+ ver_major, ver_minor, ver_maint, ver_devel,
+ pad = 0x00000000):
'''
From bootloader.h:
@@ -229,7 +265,7 @@ def make_file_header(areaid, length,
uint8_t maint;
/** Firmware development version number component */
uint8_t devel;
- /** Padding, reserved for future use, must be 0 */
+ /** Padding, reserved for future use, must be < 16 */
uint32_t pad;
};
'''
@@ -237,8 +273,6 @@ def make_file_header(areaid, length,
if areaid < 0 or areaid > 4294967295:
raise ValueError("memory area ID not 0 .. 4294967295")
- pad = 0x00000000
-
return struct.pack("<2L4BL", areaid, length,
ver_major, ver_minor, ver_maint, ver_devel, pad)
@@ -348,7 +382,7 @@ def make_header(self):
uint8_t pad;
/** Scratchpad type information for bootloader: bl_header_type_e */
uint32_t type;
- /** Status code from bootloader: bl_header_status_e */
+ /** Status code from bootloader: bl_scratchpad_status_e */
uint32_t status;
};
diff --git a/tools/sdk_wizard.py b/tools/sdk_wizard.py
index 6d71a662..0dbba5b8 100755
--- a/tools/sdk_wizard.py
+++ b/tools/sdk_wizard.py
@@ -130,6 +130,8 @@ def main():
key_pair = KeyDesc(auth, encryp)
key_dic = {"default": key_pair}
config = BootloaderConfig(None, None, key_dic, None)
+ # Hack: erase platform to avoid default one
+ config.platform = None
# Write it to the output file
config.to_ini_file(args.out_key_file)
diff --git a/util/makefile b/util/makefile
index 9d211e98..3a26da69 100644
--- a/util/makefile
+++ b/util/makefile
@@ -14,6 +14,22 @@ SRCS += $(UTIL_PATH)syscalls.c
SRCS += $(UTIL_PATH)uart_print.c
endif
+ifeq ($(WIRESHARK), yes)
+ifeq ($(APP_PRINTING), yes)
+# Both are using same uart so cannot be used together
+$(error APP_PRINTING and WIRESHARK option are mutually exclusive and cannot both be set to yes)
+endif
+ifneq ($(SHARED_DATA), yes)
+$(error WIRESHARK util lib can only be used if SHARED_DATA is also used in your application)
+endif
+WIRESHARK_PATH = $(UTIL_PATH)wireshark/
+CFLAGS += -DWIRESHARK
+INCLUDES += -I$(WIRESHARK_PATH)
+HAL_UART=yes
+# HAL_UART_BUFFER_SIZE=2048 // Not supported yet
+SRCS += $(WIRESHARK_PATH)wireshark.c
+endif
+
ifeq ($(TINY_CBOR), yes)
CBOR_PATH = $(UTIL_PATH)tinycbor/src/
SRCS += $(CBOR_PATH)cborencoder.c \
diff --git a/util/wireshark/README.md b/util/wireshark/README.md
new file mode 100644
index 00000000..bb5bdb3f
--- /dev/null
+++ b/util/wireshark/README.md
@@ -0,0 +1,95 @@
+# Wireshark
+
+All the traffic from a given node can be observed with the Wireshark application.
+Only the traffic routed to the application (Uplink and Downlink) can be observed.
+
+Few steps must be done to enable this feature.
+
+## Configuration of the node
+
+The traffic is captured in the [shared_data library](../../libraries/shared_data/) so the application must use it.
+
+In your application makefile, the Wireshark feature must be enabled:
+
+```c
+WIRESHARK=yes
+WIRESHARK_UART_BAUDRATE=115200 //Higher throughput can be used by modifying the extcap wireshark extension
+```
+This feature is using the serial port to send the traffic out of the node. As our API only allows one serial port at a time, it prevents the usage of other serial modules like APP_PRINTING.
+In other words, be sure to disable the APP_PRINTING flag (APP_PRINTING =no) when the WIRESHARK flag is enabled (WIRESHARK=yes). setting both flags to “yes” would generate an error at compile time, since both modules (printing/logging module and the wireshark module) use the same UART.
+
+## Example with custom_app
+
+To ensure that everything works fine, you can start with the custom_app by ediding its [makefile](../../source/example_apps/custom_app/makefile) as followed:
+
+```diff
+-APP_PRINTING=yes
++APP_PRINTING=no
++
++WIRESHARK=yes
++WIRESHARK_UART_BAUDRATE=115200
+```
+
+## Wireshark PC application
+
+### Installation
+
+Wireshark must be installed on your PC (not described here). It can be downloaded [here](https://www.wireshark.org/download.html).
+This plugin was tested in a Windows environement with version 3.6.6, but should work the same way on Linux or Mac.
+
+### Get Wireshark extension folders
+
+Once installed, please open **Help > About Wireshark** to find the Extcap and Lua plugin folders as shown on following screenshot:
+
+
+### Install the extcap plugin
+
+This external capture plugin (refered as extcap in Wireshark terminology) is directly invoked by Wireshark to read the node traffic and send it to the right format (pcap).
+This plugin is written in Python and requires pyserial python package.
+It can be installed with following command:
+
+```shell
+pip install pyserial
+```
+
+Please copy [wirepas_node_sniffer.py](wireshark_app/wirepas_node_sniffer.py) into the Personal or Global Extcap path of Wireshark obtained in [previous section](#get-wireshark-extension-folders) (On windows, [wirepas_node_sniffer.bat](wireshark_app/wirepas_node_sniffer.bat) must also be copied).
+
+
+### Install the Wirepas Lua dissector
+
+The Lua dissector will instruct the Wireshark application how to interpret the packet received on
+
+Please copy [wirepas_node_sniffer.lua](wireshark_app/wirepas_node_sniffer.lua) into the Personal or Global Lua path of Wireshark obtained in [previous section](#get-wireshark-extension-folders)
+
+
+## Test the system
+
+Flash your node with your application and connect it to your PC.
+
+Once done, start the Wireshark application.
+You should now see a new interface for your node as shown on following screenshot.
+
+
+
+If your device doesn't appear, please check this [section](#device-detection-based-on-usb-pidvid)
+
+Once you have click on your interface and if you are running the custom_app application, you should see something like this.
+
+
+
+You can see periodic sending of 4 bytes from the app to the sink every 10s with an incrementing counter.
+
+
+## Known issues
+
+### Session end not correctly handled on Windows
+On Windows, there is an issue to close the connection. So to restart a capture session, you may have to restart Wireshark or unplug and plug again your device. In fact, the previous session will not close correctly the uart connection preventing any further opening.
+
+### Default uart buffer size may be insufficient
+To be described
+
+
+### Device detection based on usb pid/vid
+
+Device detection is based on usb pid/vid.
+If your uart to usb converter pid/vid is not in the list at the beginning of [wirepas_node_sniffer.py](wireshark_app/wirepas_node_sniffer.py), please add it there and restart Wireshark.
diff --git a/util/wireshark/wireshark.c b/util/wireshark/wireshark.c
new file mode 100644
index 00000000..de69ecae
--- /dev/null
+++ b/util/wireshark/wireshark.c
@@ -0,0 +1,80 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+#include
+#include
+#include "api.h"
+#include "usart.h"
+#include "wireshark.h"
+
+
+static const uint8_t SLIP_END=0xC0;
+
+/**
+ * \brief send a buffer with slip escaping
+ * \note no check on return code as it is assumed that system
+ * can write the messages fast enough
+ */
+static void slip_send_buffer(const uint8_t * buf, size_t len)
+{
+ const uint8_t SLIP_ESC=0xDB;
+ const uint8_t SLIP_ESC_END=0xDC;
+ const uint8_t SLIP_ESC_ESC=0xDD;
+
+ while (len--) {
+ uint8_t ch = *buf;
+ switch(ch)
+ {
+ case SLIP_ESC:
+ Usart_sendBuffer(&SLIP_ESC, 1);
+ Usart_sendBuffer(&SLIP_ESC_ESC, 1);
+ break;
+ case SLIP_END:
+ Usart_sendBuffer(&SLIP_ESC, 1);
+ Usart_sendBuffer(&SLIP_ESC_END, 1);
+ break;
+ default:
+ Usart_sendBuffer(buf, 1);
+ break;
+ }
+ buf++;
+ }
+}
+
+void Wireshark_print(
+ uint32_t src,
+ uint32_t dest,
+ uint8_t qos,
+ uint8_t src_ep,
+ uint8_t dst_ep,
+ int8_t rssi,
+ uint32_t delay,
+ const uint8_t * data,
+ size_t len)
+{
+ /* Print new frame char */
+ Usart_sendBuffer(&SLIP_END, 1);
+
+ /* Print meta data */
+ slip_send_buffer((uint8_t *) &src, 4);
+ slip_send_buffer((uint8_t *) &dest, 4);
+ slip_send_buffer((uint8_t *) &qos, 1);
+ slip_send_buffer((uint8_t *) &src_ep, 1);
+ slip_send_buffer((uint8_t *) &dst_ep, 1);
+ slip_send_buffer((uint8_t *) &rssi, 1);
+ slip_send_buffer((uint8_t *) &delay, 4);
+
+ slip_send_buffer(data, len);
+
+ /* Print end frame char */
+ Usart_sendBuffer(&SLIP_END, 1);
+}
+
+void Wireshark_init(void)
+{
+ Usart_init(WIRESHARK_UART_BAUDRATE, UART_FLOW_CONTROL_NONE);
+ Usart_setEnabled(true);
+}
diff --git a/util/wireshark/wireshark.h b/util/wireshark/wireshark.h
new file mode 100644
index 00000000..23b8a9dc
--- /dev/null
+++ b/util/wireshark/wireshark.h
@@ -0,0 +1,36 @@
+/* Copyright 2022 Wirepas Ltd. All Rights Reserved.
+ *
+ * See file LICENSE.txt for full license details.
+ *
+ */
+
+/**
+ * \file wireshark.h
+ *
+ * Helper file to print wireshark frame to be displayed in Wireshark UI
+ */
+#ifndef WIRESHARK_H
+#define WIRESHARK_H
+
+#include
+#include
+#include "api.h"
+
+#ifndef WIRESHARK_UART_BAUDRATE
+#define WIRESHARK_UART_BAUDRATE 115200
+#endif
+
+void Wireshark_print(
+ uint32_t src,
+ uint32_t dest,
+ uint8_t qos,
+ uint8_t src_ep,
+ uint8_t dst_ep,
+ int8_t rssi,
+ uint32_t delay,
+ const uint8_t * data,
+ size_t len);
+
+void Wireshark_init(void);
+
+#endif // WIRESHARK_H
diff --git a/util/wireshark/wireshark_app/screenshots/CustomApp.PNG b/util/wireshark/wireshark_app/screenshots/CustomApp.PNG
new file mode 100644
index 00000000..8d4d9cf6
Binary files /dev/null and b/util/wireshark/wireshark_app/screenshots/CustomApp.PNG differ
diff --git a/util/wireshark/wireshark_app/screenshots/SelectInterface.PNG b/util/wireshark/wireshark_app/screenshots/SelectInterface.PNG
new file mode 100644
index 00000000..d4212283
Binary files /dev/null and b/util/wireshark/wireshark_app/screenshots/SelectInterface.PNG differ
diff --git a/util/wireshark/wireshark_app/screenshots/WiresharkFolders.PNG b/util/wireshark/wireshark_app/screenshots/WiresharkFolders.PNG
new file mode 100644
index 00000000..193d7608
Binary files /dev/null and b/util/wireshark/wireshark_app/screenshots/WiresharkFolders.PNG differ
diff --git a/util/wireshark/wireshark_app/wirepas_node_sniffer.bat b/util/wireshark/wireshark_app/wirepas_node_sniffer.bat
new file mode 100644
index 00000000..6a2b1722
--- /dev/null
+++ b/util/wireshark/wireshark_app/wirepas_node_sniffer.bat
@@ -0,0 +1,2 @@
+@echo off
+python "%~dp0wirepas_node_sniffer.py" %*
diff --git a/util/wireshark/wireshark_app/wirepas_node_sniffer.lua b/util/wireshark/wireshark_app/wirepas_node_sniffer.lua
new file mode 100644
index 00000000..0e4bd4af
--- /dev/null
+++ b/util/wireshark/wireshark_app/wirepas_node_sniffer.lua
@@ -0,0 +1,44 @@
+wirepas_node_sniffer = Proto("wirepas_node_sniffer","Wirepas sniffer")
+wirepas_node_sniffer.fields.src_add = ProtoField.uint32("wirepas_node_sniffer.src_add", "Source Address")
+wirepas_node_sniffer.fields.dst_add = ProtoField.uint32("wirepas_node_sniffer.dst_add", "Destination Address")
+wirepas_node_sniffer.fields.qos = ProtoField.uint8("wirepas_node_sniffer.qos", "QoS")
+wirepas_node_sniffer.fields.src_ep = ProtoField.uint8("wirepas_node_sniffer.src_ep", "Source Endpoint")
+wirepas_node_sniffer.fields.dst_ep = ProtoField.uint8("wirepas_node_sniffer.dst_ep", "Destination Endpoint")
+wirepas_node_sniffer.fields.rssi = ProtoField.int8("wirepas_node_sniffer.rssi", "Rssi")
+wirepas_node_sniffer.fields.delay = ProtoField.uint32("wirepas_node_sniffer.delay", "Delay")
+
+-- create a function to dissect it
+function wirepas_node_sniffer.dissector(buffer, pinfo, tree)
+ HEADER_LEN = 16
+ if buffer:len() > HEADER_LEN then
+ local src_add = buffer(0,4)
+ local dst_add = buffer(4,4)
+ local qos = buffer(8,1)
+ local src_ep = buffer(9,1)
+ local dst_ep = buffer(10,1)
+ local rssi = buffer(11,1)
+ local delay = buffer(12,4)
+
+ pinfo.cols.protocol = "Wirepas Raw"
+
+ pinfo.cols.src = src_add:uint()
+ pinfo.cols.dst = dst_add:uint()
+
+ local t = tree:add(wirepas_node_sniffer, buffer(0,HEADER_LEN), "Wirepas Node Sniffer")
+ t:add_le(wirepas_node_sniffer.fields.src_add, src_add)
+ t:add_le(wirepas_node_sniffer.fields.dst_add, dst_add)
+ t:add_le(wirepas_node_sniffer.fields.qos, qos)
+ t:add_le(wirepas_node_sniffer.fields.src_ep, src_ep)
+ t:add_le(wirepas_node_sniffer.fields.dst_ep, dst_ep)
+ t:add_le(wirepas_node_sniffer.fields.rssi, rssi)
+ t:add_le(wirepas_node_sniffer.fields.delay, delay)
+ if (src_ep:uint() == 128 and dst_ep:uint() == 02) then
+ Dissector.get("ipv6"):call(buffer(HEADER_LEN):tvb(), pinfo, tree)
+ --elseif (src_ep:uint() == 1 and dst_ep:uint() == 1) then
+ -- pinfo.cols.protocol = "Wirepas Custom app"
+ end
+ end
+end
+
+local wtap_encap_table = DissectorTable.get("wtap_encap")
+wtap_encap_table:add(wtap.USER0, wirepas_node_sniffer)
diff --git a/util/wireshark/wireshark_app/wirepas_node_sniffer.py b/util/wireshark/wireshark_app/wirepas_node_sniffer.py
new file mode 100644
index 00000000..a6622573
--- /dev/null
+++ b/util/wireshark/wireshark_app/wirepas_node_sniffer.py
@@ -0,0 +1,318 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+
+is_standalone = __name__ == '__main__'
+
+import queue as Queue
+
+if is_standalone:
+ sys.path.insert(0, os.getcwd())
+
+import signal
+import struct
+import threading
+import time
+import logging
+from argparse import ArgumentParser
+from serial import Serial, serialutil
+from serial.tools.list_ports import comports
+
+# List of USB PID/VID that can be used to connect to a Wirepas node
+# This list can be extended if another serial to USB converter is used
+USB_PID_VID = [(0x0403,0x6001),
+ (0x0403,0x6015),
+ (0x1366,0x0105),
+ (0x1366,0x1015),
+ (0x1366,0x1054),
+ (0x1366,0x1055)]
+
+class WirepasNodeSniffer(object):
+
+ def __init__(self, connection_open_timeout=None):
+ self.serial = None
+ self.serial_queue = Queue.Queue()
+ self.running = threading.Event()
+ self.logger = logging.getLogger()
+
+ self.dev = None
+ self.channel = None
+ self.dlt = None
+ self.threads = []
+ self.connection_open_timeout = connection_open_timeout
+
+
+ def stop_sig_handler(self, *args, **kwargs):
+ """
+ Function responsible for closing the connection
+ """
+ self.logger.info("in stop_sig_handler")
+
+ if self.running.is_set():
+ self.running.clear()
+
+ for thread in self.threads:
+ try:
+ thread.join(timeout=10)
+ if thread.is_alive() is True:
+ self.logger.error("Failed to stop thread {}".format(thread.name))
+ except RuntimeError:
+ pass
+
+ @staticmethod
+ def extcap_interfaces():
+ """
+ Wireshark-related method that returns configuration options.
+ :return: string with wireshark-compatible information
+ """
+ res = []
+ res.append("extcap {version=0.1}{display=Wirepas Node Sniffer}")
+ for port in comports():
+ if (port.vid, port.pid) in USB_PID_VID:
+ res.append("interface {value=%s}{display=Wirepas Node Sniffer %s}" % (port.device,port.device) )
+
+ return "\n".join(res)
+
+ @staticmethod
+ def extcap_dlts():
+ """
+ Wireshark-related method that returns configuration options.
+ :return: string with wireshark-compatible information
+ """
+ res = []
+ res.append("dlt {number=147}{name=USER0}{display=Wirepas Node Sniffer")
+
+ return "\n".join(res)
+
+ @staticmethod
+ def extcap_config():
+ """
+ Wireshark-related method that returns configuration options.
+ :return: string with wireshark-compatible information
+ """
+ return "\n"
+
+ def pcap_header(self):
+ """
+ Returns pcap header to be written into pcap file.
+ """
+ # More details here: https://wiki.wireshark.org/Development/LibpcapFileFormat#global-header
+ header = bytearray()
+ header += struct.pack(' start_connection + self.connection_open_timeout:
+ raise RuntimeError(
+ "Could not open serial connection to sniffer before timeout of {} seconds".format(
+ self.connection_open_timeout))
+ time.sleep(0.5)
+
+ packet_queue = Queue.Queue()
+ self.dev = dev
+ self.running.set()
+
+ self.dlt = 147
+
+ self.threads.append(threading.Thread(target=self.serial_reader, args=(self.dev, packet_queue), name="serial_reader", daemon=True))
+ self.threads.append(threading.Thread(target=self.fifo_writer, args=(fifo, packet_queue), name="fifo_writer", daemon=True))
+
+
+ for thread in self.threads:
+ thread.start()
+
+ while is_standalone and self.running.is_set():
+ time.sleep(1)
+
+ logging.info("Exiting main thread")
+ self.serial.close()
+
+
+ @staticmethod
+ def parse_args():
+ """
+ Helper methods to make the standalone script work in console and wireshark.
+ """
+ parser = ArgumentParser(description="Extcap program for the nRF Sniffer for 802.15.4")
+
+ parser.add_argument("--extcap-interfaces", help="Provide a list of interfaces to capture from", action="store_true")
+ parser.add_argument("--extcap-interface", help="Provide the interface to capture from")
+ parser.add_argument("--extcap-dlts", help="Provide a list of dlts for the given interface", action="store_true")
+ parser.add_argument("--extcap-config", help="Provide a list of configurations for the given interface", action="store_true")
+ parser.add_argument("--capture", help="Start the capture routine", action="store_true" )
+ parser.add_argument("--fifo", help="Use together with capture to provide the fifo to dump data to")
+ parser.add_argument("--extcap-capture-filter", help="Used together with capture to provide a capture filter")
+
+ result, unknown = parser.parse_known_args()
+
+ if result.capture and not result.extcap_interface:
+ parser.error("--extcap-interface is required if --capture is present")
+
+ return result
+
+ def __str__(self):
+ return "{} ({}) channel {}".format(type(self).__name__, self.dev, self.channel)
+
+ def __repr__(self):
+ return self.__str__()
+
+
+if is_standalone:
+ args = WirepasNodeSniffer.parse_args()
+
+ logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s', level=logging.INFO)
+
+ sniffer_comm = WirepasNodeSniffer(2)
+
+ if args.extcap_interfaces:
+ print(sniffer_comm.extcap_interfaces())
+
+ if args.extcap_dlts:
+ print(sniffer_comm.extcap_dlts())
+
+ if args.extcap_config:
+ print(sniffer_comm.extcap_config())
+
+ if args.capture and args.fifo:
+ signal.signal(signal.SIGINT, sniffer_comm.stop_sig_handler)
+ signal.signal(signal.SIGTERM, sniffer_comm.stop_sig_handler)
+
+ try:
+ sniffer_comm.extcap_capture(args.fifo, args.extcap_interface)
+ except KeyboardInterrupt as e:
+ sniffer_comm.stop_sig_handler()
+ except RuntimeError as e:
+ logging.error("Cannot open serial connection")
+ exit(1)
diff --git a/version.txt b/version.txt
deleted file mode 100644
index 65307e0d..00000000
--- a/version.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-Thu Nov 3 15:43:15 UTC 2022
-657b41094b972b0fb6cd44db2f0d9b4de43ccb96