From 6f6410061de69bf419e2ad3a55d9fcb429ca8b07 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Mon, 4 Dec 2023 15:44:58 +0100 Subject: [PATCH] soc: stm32wba: Implement BLE controller lib APIs over Zephyr In order to enable BLE support on STM32WBA, following APIs are implemented: - HostStack_: BLE Controller scheduling - ll_sys_: Link layer API required for scheduling - UTIL_TIMER_: BLE Controller timer utility - LINKLAYER_PLAT_: BLE controller utilities Signed-off-by: Erwan Gouriou --- soc/arm/st_stm32/stm32wba/CMakeLists.txt | 10 + .../stm32wba/Kconfig.defconfig.series | 26 ++ soc/arm/st_stm32/stm32wba/hci_if/bleplat.c | 100 ++++++ .../st_stm32/stm32wba/hci_if/host_stack_if.c | 82 +++++ .../st_stm32/stm32wba/hci_if/linklayer_plat.c | 304 ++++++++++++++++++ .../stm32wba/hci_if/linklayer_plat_local.h | 13 + soc/arm/st_stm32/stm32wba/hci_if/ll_sys_if.c | 47 +++ .../st_stm32/stm32wba/hci_if/stm32_timer.c | 59 ++++ 8 files changed, 641 insertions(+) create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/bleplat.c create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/host_stack_if.c create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat.c create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat_local.h create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/ll_sys_if.c create mode 100644 soc/arm/st_stm32/stm32wba/hci_if/stm32_timer.c diff --git a/soc/arm/st_stm32/stm32wba/CMakeLists.txt b/soc/arm/st_stm32/stm32wba/CMakeLists.txt index 0fd5073770d..d26c143f8f6 100644 --- a/soc/arm/st_stm32/stm32wba/CMakeLists.txt +++ b/soc/arm/st_stm32/stm32wba/CMakeLists.txt @@ -9,4 +9,14 @@ zephyr_sources_ifdef(CONFIG_PM power.c ) +if(CONFIG_BT_STM32WBA) + zephyr_include_directories(hci_if) + + zephyr_sources(hci_if/linklayer_plat.c) + zephyr_sources(hci_if/bleplat.c) + zephyr_sources(hci_if/host_stack_if.c) + zephyr_sources(hci_if/ll_sys_if.c) + zephyr_sources(hci_if/stm32_timer.c) +endif() + set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/arm/st_stm32/stm32wba/Kconfig.defconfig.series b/soc/arm/st_stm32/stm32wba/Kconfig.defconfig.series index e6d57729a09..a1099228e5f 100644 --- a/soc/arm/st_stm32/stm32wba/Kconfig.defconfig.series +++ b/soc/arm/st_stm32/stm32wba/Kconfig.defconfig.series @@ -13,4 +13,30 @@ config SOC_SERIES config STM32_LPTIM_TIMER default y if PM +choice BT_HCI_BUS_TYPE + default BT_STM32WBA + depends on BT +endchoice + +config BT_STM32WBA + select DYNAMIC_INTERRUPTS + select DYNAMIC_DIRECT_INTERRUPTS + select ENTROPY_GENERATOR + select USE_STM32_HAL_RAMCFG + +if BT_STM32WBA + +choice LIBC_IMPLEMENTATION + default NEWLIB_LIBC +endchoice + +choice LINKER_ORPHAN_CONFIGURATION + default LINKER_ORPHAN_SECTION_PLACE +endchoice + +config ENTROPY_STM32_CLK_CHECK + default n + +endif + endif # SOC_SERIES_STM32WBAX diff --git a/soc/arm/st_stm32/stm32wba/hci_if/bleplat.c b/soc/arm/st_stm32/stm32wba/hci_if/bleplat.c new file mode 100644 index 00000000000..7c1ed1aa962 --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/bleplat.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "bleplat.h" +#include "bpka.h" +#include "linklayer_plat.h" + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +LOG_MODULE_REGISTER(ble_plat); + +RAMCFG_HandleTypeDef hramcfg_SRAM1; +const struct device *rng_dev; + +void BLEPLAT_Init(void) +{ + BPKA_Reset(); + + rng_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); + if (!device_is_ready(rng_dev)) { + LOG_ERR("error: random device not ready"); + } +} + +void BLEPLAT_RngGet(uint8_t n, uint32_t *val) +{ + LINKLAYER_PLAT_GetRNG((uint8_t *)val, 4 * n); +} + +int BLEPLAT_PkaStartP256Key(const uint32_t *local_private_key) +{ + return BPKA_StartP256Key(local_private_key); +} + +void BLEPLAT_PkaReadP256Key(uint32_t *local_public_key) +{ + BPKA_ReadP256Key(local_public_key); +} + +int BLEPLAT_PkaStartDhKey(const uint32_t *local_private_key, + const uint32_t *remote_public_key) +{ + return BPKA_StartDhKey(local_private_key, remote_public_key); +} + +int BLEPLAT_PkaReadDhKey(uint32_t *dh_key) +{ + return BPKA_ReadDhKey(dh_key); +} + +void BPKACB_Complete(void) +{ + BLEPLATCB_PkaComplete(); +} + +void MX_RAMCFG_Init(void) +{ + /* Initialize RAMCFG SRAM1 */ + hramcfg_SRAM1.Instance = RAMCFG_SRAM1; + if (HAL_RAMCFG_Init(&hramcfg_SRAM1) != HAL_OK) { + LOG_ERR("Could not init RAMCFG"); + } +} + +void *ble_memcpy(void *dst, const void *src, uint8_t n) +{ + memcpy(dst, src, (size_t)n); + + return dst; +} + +void *ble_memset(void *dst, uint8_t c, uint16_t n) +{ + memset((void *)dst, (int)c, (size_t)n); + + return dst; +} + +int8_t ble_memcmp(const void *a, const void *b, uint16_t n) +{ + return (int8_t)memcmp(a, b, (size_t)n); +} + +void Error_Handler(void) +{ + LOG_ERR(""); +} + +/* BLE ctlr should not disable HSI on its own */ +void SCM_HSI_CLK_OFF(void) {} + +/* BLE ctlr should not alter RNG clocks */ +void HW_RNG_DisableClock(uint8_t) {} +void HW_RNG_EnableClock(uint8_t) {} diff --git a/soc/arm/st_stm32/stm32wba/hci_if/host_stack_if.c b/soc/arm/st_stm32/stm32wba/hci_if/host_stack_if.c new file mode 100644 index 00000000000..6cc224cc60a --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/host_stack_if.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "app_conf.h" +#include "blestack.h" +#include "bpka.h" +#include "ll_intf.h" + +K_MUTEX_DEFINE(ble_ctlr_stack_mutex); +struct k_work_q ble_ctlr_work_q, ll_work_q; +struct k_work ble_ctlr_stack_work, bpka_work; + +uint8_t ll_state_busy; + +#define BLE_CTLR_TASK_STACK_SIZE (256 * 7) +#define LL_TASK_STACK_SIZE (256 * 7) +#define BLE_CTLR_TASK_PRIO (14) +#define LL_TASK_PRIO (14) + +K_THREAD_STACK_DEFINE(ble_ctlr_work_area, BLE_CTLR_TASK_STACK_SIZE); +K_THREAD_STACK_DEFINE(ll_work_area, LL_TASK_STACK_SIZE); + +void HostStack_Process(void) +{ + k_work_submit_to_queue(&ble_ctlr_work_q, &ble_ctlr_stack_work); +} + +static void ble_ctlr_stack_handler(struct k_work *work) +{ + uint8_t running = 0x0; + change_state_options_t options; + + k_mutex_lock(&ble_ctlr_stack_mutex, K_FOREVER); + running = BleStack_Process(); + k_mutex_unlock(&ble_ctlr_stack_mutex); + + if (ll_state_busy == 1) { + options.combined_value = 0x0F; + ll_intf_chng_evnt_hndlr_state(options); + ll_state_busy = 0; + } + + if (running == BLE_SLEEPMODE_RUNNING) { + HostStack_Process(); + } +} + +void BPKACB_Process(void) +{ + k_work_submit_to_queue(&ble_ctlr_work_q, &bpka_work); +} + +static void bpka_work_handler(struct k_work *work) +{ + BPKA_BG_Process(); +} + +static int stm32wba_ble_ctlr_init(void) +{ + k_work_queue_init(&ble_ctlr_work_q); + k_work_queue_start(&ble_ctlr_work_q, ble_ctlr_work_area, + K_THREAD_STACK_SIZEOF(ble_ctlr_work_area), + BLE_CTLR_TASK_PRIO, NULL); + + k_work_queue_init(&ll_work_q); + k_work_queue_start(&ll_work_q, ll_work_area, + K_THREAD_STACK_SIZEOF(ll_work_area), + LL_TASK_PRIO, NULL); + + k_work_init(&ble_ctlr_stack_work, &ble_ctlr_stack_handler); + k_work_init(&bpka_work, &bpka_work_handler); + + return 0; +} + +SYS_INIT(stm32wba_ble_ctlr_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat.c b/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat.c new file mode 100644 index 00000000000..1e890949147 --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "scm.h" + +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +LOG_MODULE_REGISTER(linklayer_plat); + +#define RADIO_INTR_PRIO_HIGH_Z (RADIO_INTR_PRIO_HIGH + _IRQ_PRIO_OFFSET) +#define RADIO_INTR_PRIO_LOW_Z (RADIO_INTR_PRIO_LOW + _IRQ_PRIO_OFFSET) + +/* 2.4GHz RADIO ISR callbacks */ +typedef void (*radio_isr_cb_t) (void); + +radio_isr_cb_t radio_callback; +radio_isr_cb_t low_isr_callback; + +extern const struct device *rng_dev; + +/* Radio critical sections */ +volatile int32_t prio_high_isr_counter; +volatile int32_t prio_low_isr_counter; +volatile int32_t prio_sys_isr_counter; +volatile int32_t irq_counter; +volatile uint32_t local_basepri_value; + +/* Radio SW low ISR global variable */ +volatile uint8_t radio_sw_low_isr_is_running_high_prio; + +void LINKLAYER_PLAT_ClockInit(void) +{ + LL_PWR_EnableBkUpAccess(); + + /* Select LSE as Sleep CLK */ + __HAL_RCC_RADIOSLPTIM_CONFIG(RCC_RADIOSTCLKSOURCE_LSE); + + LL_PWR_DisableBkUpAccess(); + + /* Enable AHB5ENR peripheral clock (bus CLK) */ + __HAL_RCC_RADIO_CLK_ENABLE(); +} + +void LINKLAYER_PLAT_DelayUs(uint32_t delay) +{ + k_busy_wait(delay); +} + +void LINKLAYER_PLAT_WaitHclkRdy(void) +{ + while (HAL_RCCEx_GetRadioBusClockReadiness() != RCC_RADIO_BUS_CLOCK_READY) { + } +} + +void LINKLAYER_PLAT_AclkCtrl(uint8_t enable) +{ + LOG_DBG("enable: %d", enable); + if (enable) { + /* Enable RADIO baseband clock (active CLK) */ + HAL_RCCEx_EnableRadioBBClock(); + + /* Polling on HSE32 activation */ + while (LL_RCC_HSE_IsReady() == 0) { + } + } else { + /* Disable RADIO baseband clock (active CLK) */ + HAL_RCCEx_DisableRadioBBClock(); + } +} + +void LINKLAYER_PLAT_GetRNG(uint8_t *ptr_rnd, uint32_t len) +{ + int ret; + + /* Read 32-bit random values from HW driver */ + ret = entropy_get_entropy_isr(rng_dev, (char *)ptr_rnd, len, 0); + if (ret < 0) { + LOG_ERR("Error: entropy_get_entropy failed: %d", ret); + } + LOG_DBG("n %d, val: %p", len, (void *)ptr_rnd); +} + +void LINKLAYER_PLAT_SetupRadioIT(void (*intr_cb)()) +{ + radio_callback = intr_cb; +} + +void LINKLAYER_PLAT_SetupSwLowIT(void (*intr_cb)()) +{ + low_isr_callback = intr_cb; +} + +void radio_high_prio_isr(void) +{ + radio_callback(); + + HAL_RCCEx_DisableRequestUponRadioWakeUpEvent(); + + __ISB(); + + ISR_DIRECT_PM(); +} + +void radio_low_prio_isr(void) +{ + irq_disable((IRQn_Type)RADIO_SW_LOW_INTR_NUM); + + low_isr_callback(); + + /* Check if nested SW radio low interrupt has been requested*/ + if (radio_sw_low_isr_is_running_high_prio != 0) { + NVIC_SetPriority((IRQn_Type) RADIO_SW_LOW_INTR_NUM, RADIO_INTR_PRIO_LOW); + radio_sw_low_isr_is_running_high_prio = 0; + } + + /* Re-enable SW radio low interrupt */ + irq_enable((IRQn_Type)RADIO_SW_LOW_INTR_NUM); + + ISR_DIRECT_PM(); +} + + +void link_layer_register_isr(void) +{ + ARM_IRQ_DIRECT_DYNAMIC_CONNECT(RADIO_INTR_NUM, 0, 0, reschedule); + + /* Ensure the IRQ is disabled before enabling it at run time */ + irq_disable((IRQn_Type)RADIO_INTR_NUM); + + irq_connect_dynamic((IRQn_Type)RADIO_INTR_NUM, RADIO_INTR_PRIO_HIGH_Z, + (void (*)(const void *))radio_high_prio_isr, NULL, 0); + + irq_enable((IRQn_Type)RADIO_INTR_NUM); + + ARM_IRQ_DIRECT_DYNAMIC_CONNECT(RADIO_SW_LOW_INTR_NUM, 0, 0, reschedule); + + /* Ensure the IRQ is disabled before enabling it at run time */ + irq_disable((IRQn_Type)RADIO_SW_LOW_INTR_NUM); + + irq_connect_dynamic((IRQn_Type)RADIO_SW_LOW_INTR_NUM, RADIO_SW_LOW_INTR_PRIO, + (void (*)(const void *))radio_low_prio_isr, NULL, 0); + + irq_enable((IRQn_Type)RADIO_SW_LOW_INTR_NUM); +} + + +void LINKLAYER_PLAT_TriggerSwLowIT(uint8_t priority) +{ + uint8_t low_isr_priority = RADIO_INTR_PRIO_LOW_Z; + + LOG_DBG("Priotity: %d", priority); + + /* Check if a SW low interrupt as already been raised. + * Nested call far radio low isr are not supported + **/ + + if (NVIC_GetActive(RADIO_SW_LOW_INTR_NUM) == 0) { + /* No nested SW low ISR, default behavior */ + + if (priority == 0) { + low_isr_priority = RADIO_SW_LOW_INTR_PRIO; + } + + NVIC_SetPriority((IRQn_Type)RADIO_SW_LOW_INTR_NUM, low_isr_priority); + } else { + /* Nested call detected */ + /* No change for SW radio low interrupt priority for the moment */ + + if (priority != 0) { + /* At the end of current SW radio low ISR, this pending SW + * low interrupt will run with RADIO_INTR_PRIO_LOW_Z priority + **/ + radio_sw_low_isr_is_running_high_prio = 1; + } + } + + NVIC_SetPendingIRQ((IRQn_Type)RADIO_SW_LOW_INTR_NUM); +} + +void LINKLAYER_PLAT_EnableIRQ(void) +{ + irq_counter = MAX(0, irq_counter - 1); + + if (irq_counter == 0) { + __enable_irq(); + } +} + +void LINKLAYER_PLAT_DisableIRQ(void) +{ + __disable_irq(); + + irq_counter++; +} + +void LINKLAYER_PLAT_Assert(uint8_t condition) +{ + __ASSERT_NO_MSG(condition); +} + +void LINKLAYER_PLAT_EnableSpecificIRQ(uint8_t isr_type) +{ + + LOG_DBG("isr_type: %d", isr_type); + + if ((isr_type & LL_HIGH_ISR_ONLY) != 0) { + prio_high_isr_counter--; + if (prio_high_isr_counter == 0) { + irq_enable(RADIO_INTR_NUM); + } + } + + if ((isr_type & LL_LOW_ISR_ONLY) != 0) { + prio_low_isr_counter--; + if (prio_low_isr_counter == 0) { + irq_enable(RADIO_SW_LOW_INTR_NUM); + } + } + + if ((isr_type & SYS_LOW_ISR) != 0) { + prio_sys_isr_counter--; + if (prio_sys_isr_counter == 0) { + __set_BASEPRI(local_basepri_value); + } + } +} + +void LINKLAYER_PLAT_DisableSpecificIRQ(uint8_t isr_type) +{ + + LOG_DBG("isr_type: %d", isr_type); + + if ((isr_type & LL_HIGH_ISR_ONLY) != 0) { + prio_high_isr_counter++; + if (prio_high_isr_counter == 1) { + irq_disable(RADIO_INTR_NUM); + } + } + + if ((isr_type & LL_LOW_ISR_ONLY) != 0) { + prio_low_isr_counter++; + if (prio_low_isr_counter == 1) { + irq_disable(RADIO_SW_LOW_INTR_NUM); + } + } + + if ((isr_type & SYS_LOW_ISR) != 0) { + prio_sys_isr_counter++; + if (prio_sys_isr_counter == 1) { + local_basepri_value = __get_BASEPRI(); + __set_BASEPRI_MAX(RADIO_INTR_PRIO_LOW_Z << 4); + } + } +} + +void LINKLAYER_PLAT_EnableRadioIT(void) +{ + irq_enable((IRQn_Type)RADIO_INTR_NUM); +} + +void LINKLAYER_PLAT_DisableRadioIT(void) +{ + irq_disable((IRQn_Type)RADIO_INTR_NUM); +} + +void LINKLAYER_PLAT_StartRadioEvt(void) +{ + __HAL_RCC_RADIO_CLK_SLEEP_ENABLE(); + + NVIC_SetPriority(RADIO_INTR_NUM, RADIO_INTR_PRIO_HIGH_Z); + + scm_notifyradiostate(SCM_RADIO_ACTIVE); +} + +void LINKLAYER_PLAT_StopRadioEvt(void) +{ + __HAL_RCC_RADIO_CLK_SLEEP_DISABLE(); + + NVIC_SetPriority(RADIO_INTR_NUM, RADIO_INTR_PRIO_LOW_Z); + + scm_notifyradiostate(SCM_RADIO_NOT_ACTIVE); +} + +void LINKLAYER_PLAT_RequestTemperature(void) {} + +void LINKLAYER_PLAT_SCHLDR_TIMING_UPDATE_NOT(Evnt_timing_t *p_evnt_timing) {} + +void LINKLAYER_PLAT_EnableOSContextSwitch(void) {} + +void LINKLAYER_PLAT_DisableOSContextSwitch(void) {} diff --git a/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat_local.h b/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat_local.h new file mode 100644 index 00000000000..1cf621b89de --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/linklayer_plat_local.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef _STM32WBA_LINK_LAYER_PLAT_LOCAL_H_ +#define _STM32WBA_LINK_LAYER_PLAT_LOCAL_H_ + +void link_layer_register_isr(void); + +#endif /* _STM32WBA_LINK_LAYER_PLAT_LOCAL_H_ */ diff --git a/soc/arm/st_stm32/stm32wba/hci_if/ll_sys_if.c b/soc/arm/st_stm32/stm32wba/hci_if/ll_sys_if.c new file mode 100644 index 00000000000..8607cbbafd8 --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/ll_sys_if.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#define LOG_LEVEL CONFIG_SOC_LOG_LEVEL +LOG_MODULE_REGISTER(ll_sys_if); + +#include "ll_intf.h" +#include "ll_sys.h" +#include "linklayer_plat.h" +#include "app_conf.h" + +extern struct k_mutex ble_ctlr_stack_mutex; +extern struct k_work_q ll_work_q; +struct k_work ll_sys_work; + +void ll_sys_schedule_bg_process(void) +{ + k_work_submit_to_queue(&ll_work_q, &ll_sys_work); +} + +void ll_sys_schedule_bg_process_isr(void) +{ + k_work_submit_to_queue(&ll_work_q, &ll_sys_work); +} + +static void ll_sys_bg_process_handler(struct k_work *work) +{ + k_mutex_lock(&ble_ctlr_stack_mutex, K_FOREVER); + ll_sys_bg_process(); + k_mutex_unlock(&ble_ctlr_stack_mutex); +} + +void ll_sys_bg_process_init(void) +{ + k_work_init(&ll_sys_work, &ll_sys_bg_process_handler); +} + +void ll_sys_config_params(void) +{ + ll_intf_config_ll_ctx_params(USE_RADIO_LOW_ISR, NEXT_EVENT_SCHEDULING_FROM_ISR); +} diff --git a/soc/arm/st_stm32/stm32wba/hci_if/stm32_timer.c b/soc/arm/st_stm32/stm32wba/hci_if/stm32_timer.c new file mode 100644 index 00000000000..45c3f1b3782 --- /dev/null +++ b/soc/arm/st_stm32/stm32wba/hci_if/stm32_timer.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "stm32_timer.h" + +#define TICKS_PER_MS (CONFIG_SYS_CLOCK_TICKS_PER_SEC / MSEC_PER_SEC) + +static struct k_timer timer; + +UTIL_TIMER_Status_t UTIL_TIMER_Create(UTIL_TIMER_Object_t *timer_object, + uint32_t period, UTIL_TIMER_Mode_t mode, + void (*callback)(void *), void *argument) +{ + if (timer_object == NULL) { + return UTIL_TIMER_INVALID_PARAM; + } + + timer_object->ReloadValue = period * TICKS_PER_MS; + timer_object->Mode = mode; + timer_object->Callback = callback; + timer_object->argument = argument; + timer_object->IsRunning = false; + timer_object->IsReloadStopped = false; + timer_object->Next = NULL; + + return UTIL_TIMER_OK; +} + +UTIL_TIMER_Status_t UTIL_TIMER_Start(UTIL_TIMER_Object_t *timer_object) +{ + if (timer_object == NULL) { + return UTIL_TIMER_INVALID_PARAM; + } + + k_timer_user_data_set(&timer, timer_object); + k_timer_start(&timer, K_TICKS(timer_object->ReloadValue), + K_TICKS(timer_object->ReloadValue)); + timer_object->IsRunning = true; + + return UTIL_TIMER_OK; +} + +UTIL_TIMER_Status_t UTIL_TIMER_Stop(UTIL_TIMER_Object_t *timer_object) +{ + if (timer_object == NULL) { + return UTIL_TIMER_INVALID_PARAM; + } + + k_timer_stop(&timer); + timer_object->IsRunning = false; + + return UTIL_TIMER_OK; +}