Commit 22925907 authored by Erwan Gouriou's avatar Erwan Gouriou Committed by Erwan Gouriou
Browse files

lib: stm32wba: hci: Add flash_manager when building controller library

Flash manager is used to driver flash access coexistence between RF and
user accesses.

Signed-off-by: default avatarErwan Gouriou <erwan.gouriou@st.com>
parent 3fe2e327
Loading
Loading
Loading
Loading
+7 −0
Changes for lib/CMakeLists.txt: 7 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -38,6 +38,13 @@ if(CONFIG_HAS_STM32LIB)
    zephyr_sources(stm32wba/hci/bpka.c)
    zephyr_sources(stm32wba/hci/power_table.c)
    zephyr_sources(stm32wba/hci/scm.c)
    zephyr_sources(stm32wba/hci/log_module.c)
    if(CONFIG_FLASH)
      zephyr_sources(stm32wba/hci/flash_manager.c)
      zephyr_sources(stm32wba/hci/flash_driver.c)
      zephyr_sources(stm32wba/hci/stm_list.c)
      zephyr_sources(stm32wba/hci/rf_timing_synchro.c)
    endif()

    set(STM32WBA_BLE_LIB_DIR     ${CMAKE_CURRENT_SOURCE_DIR}/../zephyr/blobs/stm32wba/lib)
    set(STM32WBA_BLE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/stm32wba/hci)
+8 −0
Changes for lib/stm32wba/hci/README: 8 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -46,12 +46,20 @@ Description:
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/Core/Inc/app_entry.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/Core/Inc/utilities_conf.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/Core/Inc/main.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/rf_timing_synchro.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/rf_timing_synchro.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/flash_driver.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/flash_driver.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/flash_manager.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/Flash/flash_manager.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/RTDebug/debug_signals.h
      Projects/NUCLEO-WBA55CG/Applications/BLE/BLE_HeartRate/System/Modules/RTDebug/RTDebug.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/RTDebug/RTDebug.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/RTDebug/local_debug_tables.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/scm.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/scm.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/stm_list.c
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/stm_list.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Modules/utilities_common.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Interfaces/hw.h
      Projects/NUCLEO-WBA52CG/Applications/BLE/BLE_HeartRate/System/Interfaces/hw_aes.c
+132 −0
Changes for lib/stm32wba/hci/flash_driver.c: 132 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    flash_driver.c
  * @author  MCD Application Team
  * @brief   The Flash Driver module is the interface layer between Flash
  *          management modules and HAL Flash drivers
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "flash_driver.h"
#include "utilities_conf.h"

/* Global variables ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private defines -----------------------------------------------------------*/

#define FD_CTRL_NO_BIT_SET   (0UL) /* value used to reset the Flash Control status */

/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/**
 * @brief variable used to represent the Flash Control status
 */
static volatile FD_Flash_ctrl_bm_t FD_Flash_Control_status = FD_CTRL_NO_BIT_SET;

/* Private function prototypes -----------------------------------------------*/
/* Functions Definition ------------------------------------------------------*/

/**
  * @brief  Update Flash Control status
  * @param  Flags_bm: Bit mask identifying the caller (1 bit per user)
  * @param  Status:   Action requested (enable or disable flash access)
  * @retval None
  */
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status)
{
  UTILS_ENTER_CRITICAL_SECTION();

  switch (Status)
  {
    case LL_FLASH_DISABLE:
    {
      FD_Flash_Control_status |= (1u << Flags_bm);
      break;
    }
    case LL_FLASH_ENABLE:
    {
      FD_Flash_Control_status &= ~(1u << Flags_bm);
      break;
    }
    default :
    {
      break;
    }
  }

  UTILS_EXIT_CRITICAL_SECTION();
}

/**
  * @brief  Write a block of 128 bits (4 32-bit words) in Flash
  * @param  Dest: Address where to write in Flash (128-bit aligned)
  * @param  Payload: Address of data to be written in Flash (32-bit aligned)
  * @retval FD_FlashOp_Status_t: Success or failure of Flash write operation
  */
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload)
{
  FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;

  /* Check if RFTS OR Application allow flash access */
  if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
      (FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
  { /* Access not allowed */
    return status;
  }

  /* Wait for system to allow flash access */
  while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));

  if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, Dest, Payload) == HAL_OK)
  {
    status = FD_FLASHOP_SUCCESS;
  }
  return status;
}

/**
  * @brief  Erase one sector of Flash
  * @param  Sect: Identifier of the sector to erase
  * @retval FD_FlashOp_Status_t: Success or failure of Flash erase operation
  */
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect)
{
  FD_FlashOp_Status_t status = FD_FLASHOP_FAILURE;
  uint32_t page_error;
  FLASH_EraseInitTypeDef p_erase_init;

  /* Check if LL allows flash access */
  if ((FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS)) &&
      (FD_Flash_Control_status & (1u << FD_FLASHACCESS_RFTS_BYPASS)))
  { /* Access not allowed */
    return status;
  }

  /* Wait for system to allow flash access */
  while (FD_Flash_Control_status & (1u << FD_FLASHACCESS_SYSTEM));

  p_erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
  p_erase_init.Page = Sect;
  p_erase_init.NbPages = 1;

  if (HAL_FLASHEx_Erase(&p_erase_init, &page_error) == HAL_OK)
  {
    status = FD_FLASHOP_SUCCESS;
  }

  return status;
}
+90 −0
Changes for lib/stm32wba/hci/flash_driver.h: 90 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    flash_driver.h
  * @author  MCD Application Team
  * @brief   Header for flash_driver.c module
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef FLASH_DRIVER_H
#define FLASH_DRIVER_H

#ifdef __cplusplus
extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "utilities_common.h"

/* Exported types ------------------------------------------------------------*/

/* Bit mask to modify Flash Control status */
typedef uint32_t  FD_Flash_ctrl_bm_t;

/* Flash operation status */
typedef enum
{
  FD_FLASHOP_SUCCESS,
  FD_FLASHOP_FAILURE
} FD_FlashOp_Status_t;

/* Flash Driver commands to enable or disable flash access */
typedef enum
{
  LL_FLASH_ENABLE,
  LL_FLASH_DISABLE,
} FD_FLASH_Status_t;

/**
 * @brief Bit mask to modify Flash Control status
 *
 * @details Those bitmasks are used to enable/disable access to the flash:
 *   - System:
 *     -# FD_FLASHACCESS_SYSTEM: Determine whether or not the flash access is allowed from a system POV.
 *                               This bit has a predominance over all the other bit masks, ie: No flash operation can
 *                               be achieved without this to be set to 0, ie: LL_FLASH_ENABLE.
 *   - RFTS:
 *     -# FD_FLASHACCESS_RFTS: Determine whether or not the RF Timing Synchro allows flash access. This bit is set
 *                             once a window has been allowed by the BLE LL, ie: set to 0.
 *                             This bit has no impact when FD_FLASHACCESS_RFTS_BYPASS is set, ie: set to 0.
 *     -# FD_FLASHACCESS_RFTS_BYPASS: Nullify the impact of FD_FLASHACCESS_RFTS when enabled, ie: set to 0. Its role is
 *                                    to allow flash operation without the need to request a timing window to the RFTS,
 *                                    ie: Executing flash operation without the BLE LL.
 *
 */
typedef enum FD_FlashAccess_bm
{
  /* System flash access bitfield */
  FD_FLASHACCESS_SYSTEM,
  /* RF Timing Synchro flash access bitfield */
  FD_FLASHACCESS_RFTS,
  /* Bypass of RF Timing Synchro flash access bitfield */
  FD_FLASHACCESS_RFTS_BYPASS,
}FD_FlashAccess_bm_t;

/* Exported constants --------------------------------------------------------*/
/* Exported variables --------------------------------------------------------*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
void FD_SetStatus(FD_Flash_ctrl_bm_t Flags_bm, FD_FLASH_Status_t Status);
FD_FlashOp_Status_t FD_WriteData(uint32_t Dest, uint32_t Payload);
FD_FlashOp_Status_t FD_EraseSectors(uint32_t Sect);

#ifdef __cplusplus
}
#endif

#endif /*FLASH_DRIVER_H */
+514 −0
Changes for lib/stm32wba/hci/flash_manager.c: 514 added lines, 0 removed lines.
Original line number Diff line number Diff line
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    flash_manager.c
  * @author  MCD Application Team
  * @brief   The Flash Manager module provides an interface to write raw data
  *          from SRAM to FLASH
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "flash_manager.h"
#include "rf_timing_synchro.h"
#include "flash_driver.h"
#include "utilities_conf.h"

#include "stm32wbaxx_hal.h"

/* Debug */
#include "log_module.h"

/* Global variables ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/

/* State of the background process */
typedef enum FM_BackGround_States
{
  FM_BKGND_NOWINDOW_FLASHOP,
  FM_BKGND_WINDOWED_FLASHOP,
}FM_BackGround_States_t;

/* Flash operation type */
typedef enum
{
  FM_WRITE_OP,
  FM_ERASE_OP
} FM_FlashOp_t;

/**
 * @brief Flash operation configuration struct
 */
typedef struct FM_FlashOpConfig
{
  uint32_t *writeSrc;
  uint32_t *writeDest;
  int32_t  writeSize;
  uint32_t eraseFirstSect;
  uint32_t eraseNbrSect;
}FM_FlashOpConfig_t;

/* Private defines -----------------------------------------------------------*/

#define FLASH_WRITE_BLOCK_SIZE  4U
#define ALIGNMENT_32   0x00000003
#define ALIGNMENT_128  0x0000000F

/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/

/**
  * @brief Semaphore on Flash
  */
static bool busy_flash_sem = FALSE;

/**
  * @brief Indicates if the flash manager module is available or not
  */
static bool flash_manager_busy = FALSE;

/**
  * @brief Parameters for Flash Write command
  */
static bool fm_window_granted = FALSE;

/**
  * @brief Callback node list for pending flash operation request
  */
static tListNode fm_cb_pending_list;

/**
  * @brief Flag indicating if pending node list has been initialized
  */
static bool fm_cb_pending_list_init = FALSE;

/**
  * @brief Pointer to current flash operation requester's callback
  */
static void (*fm_running_cb)(FM_FlashOp_Status_t);

/**
  * @brief Type of current flash operation (Write/Erase)
  */
static FM_FlashOp_t fm_flashop;

/**
  * @brief Parameters for Flash operation
  */
static FM_FlashOpConfig_t fm_flashop_parameters;

/**
 * @brief State of the Background process
 */
static FM_BackGround_States_t FM_CurrentBackGroundState;

/* Private function prototypes -----------------------------------------------*/

static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode);
static void FM_WindowAllowed_Callback(void);

/* Functions Definition ------------------------------------------------------*/

/**
  * @brief  Request the Flash Manager module to initiate a Flash Write operation
  * @param  Src: Address of the data to be stored in FLASH. It shall be 32bits aligned
  * @param  Dest: Address where the data shall be written. It shall be 128bits aligned
  * @param  Size: This is the size of data to be written in Flash.
                  The size is a multiple of 32bits (size = 1 means 32bits)
  * @param  CallbackNode: Pointer to the callback node for storage in list
  * @retval FM_Cmd_Status_t: Status of the Flash Manager module
  */
FM_Cmd_Status_t FM_Write(uint32_t *Src, uint32_t *Dest, int32_t Size, FM_CallbackNode_t *CallbackNode)
{
  FM_Cmd_Status_t status;

  if (((uint32_t)Dest < FLASH_BASE) || ((uint32_t)Dest > (FLASH_BASE + FLASH_BANK_SIZE))
                                    || (((uint32_t)Dest + Size) > (FLASH_BASE + FLASH_BANK_SIZE)))
  {
    LOG_ERROR_SYSTEM("\r\nFM_Write - Destination address not part of the flash");

    /* Destination address not part of the flash */
    return FM_ERROR;
  }

  if (((uint32_t) Src & ALIGNMENT_32) || ((uint32_t) Dest & ALIGNMENT_128))
  {
    LOG_ERROR_SYSTEM("\r\nFM_Write - Source or destination address not properly aligned");

    /* Source or destination address not properly aligned */
    return FM_ERROR;
  }

  status = FM_CheckFlashManagerState(CallbackNode);

  if (status == FM_OK)
  { /* Flash manager is available */

    /* Save Write parameters */
    fm_flashop_parameters.writeSrc = Src;
    fm_flashop_parameters.writeDest = Dest;
    fm_flashop_parameters.writeSize = Size;

    fm_flashop = FM_WRITE_OP;

    FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;

    /* Window request to be executed in background */
    FM_ProcessRequest();
  }

  LOG_INFO_SYSTEM("\r\nFM_Write - Returned value : %d", status);

  return status;
}

/**
  * @brief  Request the Flash Manager module to initiate a Flash Erase operation
  * @param  FirstSect: Index of the first sector to erase
  * @param  NbrSect: Number of sector to erase
  * @param  CallbackNode: Pointer to the callback node for storage in list
  * @retval FM_Cmd_Status_t: Status of the Flash Manager module
  */
FM_Cmd_Status_t FM_Erase(uint32_t FirstSect, uint32_t NbrSect, FM_CallbackNode_t *CallbackNode)
{
  FM_Cmd_Status_t status;

  if ((FirstSect > FLASH_PAGE_NB) || ((FirstSect + NbrSect) > FLASH_PAGE_NB))
  {
    LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");

    /* Inconsistent request */
    return FM_ERROR;
  }

  if (NbrSect == 0)
  {
    LOG_ERROR_SYSTEM("\r\nFM_Erase - Inconsistent request");

    /* Inconsistent request */
    return FM_ERROR;
  }

  status = FM_CheckFlashManagerState(CallbackNode);

  if (status == FM_OK)
  { /* Flash manager is available */

    /* Save Erase parameters */
    fm_flashop_parameters.eraseFirstSect = FirstSect;
    fm_flashop_parameters.eraseNbrSect = NbrSect;

    fm_flashop = FM_ERASE_OP;

    FM_CurrentBackGroundState = FM_BKGND_NOWINDOW_FLASHOP;

    /* Window request to be executed in background */
    FM_ProcessRequest();
  }

  LOG_INFO_SYSTEM("\r\nFM_Erase - Returned value : %d", status);

  return status;
}

/**
  * @brief  Execute Flash Manager background tasks
  * @param  None
  * @retval None
  */
void FM_BackgroundProcess (void)
{
  static uint32_t duration;
  bool flashop_complete = false;
  FD_FlashOp_Status_t fdReturnValue = FD_FLASHOP_SUCCESS;
  FM_CallbackNode_t *pCbNode = NULL;

  switch (FM_CurrentBackGroundState)
  {
    case FM_BKGND_NOWINDOW_FLASHOP:
    {
      LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP");

      if (fm_flashop == FM_WRITE_OP)
      {
        LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Write operation");

        /* Update duration time value */
        duration = TIME_WINDOW_WRITE_REQUEST;

        /* Set the next possible state - App could stop at anytime no window operation */
        FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;

        HAL_FLASH_Unlock();

        while((fm_flashop_parameters.writeSize > 0) &&
              (fdReturnValue == FD_FLASHOP_SUCCESS))
        {
          fdReturnValue = FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
                                       (uint32_t) fm_flashop_parameters.writeSrc);

          if (fdReturnValue == FD_FLASHOP_SUCCESS)
          {
            fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
            fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
            fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
          }
        }

        HAL_FLASH_Lock();

        /* Is write over ? */
        if (fm_flashop_parameters.writeSize <= 0)
        {
          flashop_complete = true;
        }
      }
      else
      {
        LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_NOWINDOW_FLASHOP - Erase operation");

        /* Update duration time value */
        duration = TIME_WINDOW_ERASE_REQUEST;

        /* Set the next possible state */
        FM_CurrentBackGroundState = FM_BKGND_WINDOWED_FLASHOP;

        HAL_FLASH_Unlock();

        while((fm_flashop_parameters.eraseNbrSect > 0) &&
              (fdReturnValue == FD_FLASHOP_SUCCESS))
        {
          fdReturnValue = FD_EraseSectors(fm_flashop_parameters.eraseFirstSect);

          if (fdReturnValue == FD_FLASHOP_SUCCESS)
          {
            fm_flashop_parameters.eraseNbrSect--;
            fm_flashop_parameters.eraseFirstSect++;
          }
        }

        HAL_FLASH_Lock();

        if (fm_flashop_parameters.eraseNbrSect == 0)
        {
          flashop_complete = true;
        }
      }
      break;
    }

    case FM_BKGND_WINDOWED_FLASHOP:
    {
      LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP");

      if (fm_window_granted == false)
      {
        LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - No time window granted yet, request one");

        /* No time window granted yet, request one */
        RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
      }
      else
      {
        LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Time window granted");

        if (fm_flashop == FM_WRITE_OP)
        {
          /* Flash Write operation */
          LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Write operation");

          HAL_FLASH_Unlock();

          while((fm_flashop_parameters.writeSize > 0) &&
                (FD_WriteData((uint32_t) fm_flashop_parameters.writeDest,
                              (uint32_t) fm_flashop_parameters.writeSrc) == FD_FLASHOP_SUCCESS))
          {
              fm_flashop_parameters.writeDest += FLASH_WRITE_BLOCK_SIZE;
              fm_flashop_parameters.writeSrc += FLASH_WRITE_BLOCK_SIZE;
              fm_flashop_parameters.writeSize -= FLASH_WRITE_BLOCK_SIZE;
          }

          if (fm_flashop_parameters.writeSize <= 0)
          {
            flashop_complete = true;
          }

      HAL_FLASH_Lock();

    }
    else
    {
      /* Flash Erase operation */
      LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Case FM_BKGND_WINDOWED_FLASHOP - Erase operation");

      HAL_FLASH_Unlock();

      /* Erase only one sector in a single time window */
      if (FD_EraseSectors(fm_flashop_parameters.eraseFirstSect) == FD_FLASHOP_SUCCESS)
      {
        fm_flashop_parameters.eraseNbrSect--;
        fm_flashop_parameters.eraseFirstSect++;
      }

      if (fm_flashop_parameters.eraseNbrSect == 0)
      {
        flashop_complete = true;
      }

      HAL_FLASH_Lock();
    }

        /* Release the time window */
        RFTS_RelWindow();

        /* Indicate that there is no more window */
        fm_window_granted = false;
      }

      break;
    }

    default:
    {
      /* Nothing to do here */
      break;
    }
  }

  if (flashop_complete == true)
  {
    UTILS_ENTER_CRITICAL_SECTION();

    /* Release semaphore on flash */
    busy_flash_sem = false;

    /* Set Flash Manager busy */
    flash_manager_busy = false;

    UTILS_EXIT_CRITICAL_SECTION();

    /* Invoke the running callback if present */
    if (fm_running_cb != NULL)
    {
      fm_running_cb(FM_OPERATION_COMPLETE);
    }

    /* notify pending requesters */
    while((LST_is_empty (&fm_cb_pending_list) == false) &&
          (busy_flash_sem == false) && (flash_manager_busy == false))
    {
      LST_remove_head (&fm_cb_pending_list, (tListNode**)&pCbNode);
      pCbNode->Callback(FM_OPERATION_AVAILABLE);
    }
  }
  else
  {
    /* Flash operation not complete yet */
    LOG_INFO_SYSTEM("\r\nFM_BackgroundProcess - Flash operation not complete yet, request a new time window");

    /* Request a new time window */
    RFTS_ReqWindow(duration, &FM_WindowAllowed_Callback);
  }
}

/**
  * @brief  Check if the Flash Manager is busy or available
  * @param  CallbackNode: Pointer to the callback node for storage in list
  * @retval FM_Cmd_Status_t: Status of the Flash Manager module
  */
static FM_Cmd_Status_t FM_CheckFlashManagerState(FM_CallbackNode_t *CallbackNode)
{
  bool fm_process_cmd = false;
  FM_Cmd_Status_t status = FM_ERROR;

  /* Check if semaphore on flash is available */
  UTILS_ENTER_CRITICAL_SECTION();

  /* Initialize pending list if not done */
  if (fm_cb_pending_list_init == false)
  {
    LST_init_head(&fm_cb_pending_list);
    fm_cb_pending_list_init = true;
  }
  /* Check if semaphore on flash is available */
  if (busy_flash_sem == false)
  { /* Check if Flash Manager is already busy */
    if (flash_manager_busy == false)
    {
      busy_flash_sem = true; /* Get semaphore on flash */
      flash_manager_busy = true; /* Set Flash Manager busy */
      fm_process_cmd = true;
    }
    else
    {
      fm_process_cmd = false;
    }
  }
  else
  {
    fm_process_cmd = false;
  }
  UTILS_EXIT_CRITICAL_SECTION();

  if (fm_process_cmd == false)
  { /* Flash manager busy */

    /* Append callback to the pending list */
    if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
    {
      LST_insert_tail(&fm_cb_pending_list, &(CallbackNode->NodeList));
    }

    status = FM_BUSY;
  }
  else
  { /* Flash manager is available */

    if ((CallbackNode != NULL) && (CallbackNode->Callback != NULL))
    {
      UTILS_ENTER_CRITICAL_SECTION();

      fm_running_cb = CallbackNode->Callback;

      UTILS_EXIT_CRITICAL_SECTION();
    }
    else
    {
      UTILS_ENTER_CRITICAL_SECTION();

      fm_running_cb = NULL;

      UTILS_EXIT_CRITICAL_SECTION();
    }

    status = FM_OK;
  }
  return status;
}

/**
  * @brief  Callback called by RF Timing Synchro module when a time window is available
  * @param  None
  * @retval None
  */
static void FM_WindowAllowed_Callback(void)
{
  fm_window_granted = true;

  LOG_INFO_SYSTEM("\r\nFM_WindowAllowed_Callback");

  /* Flash operation to be executed in background */
  FM_ProcessRequest();
}
Loading