/** ****************************************************************************** * @file tracer_emb.c * @author MCD Application Team * @brief This file contains embeded tracer control functions. ****************************************************************************** * @attention * *

© Copyright (c) 2018 STMicroelectronics. * All rights reserved.

* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "tracer_emb.h" #include "tracer_emb_hw.h" #include "string.h" /** @addtogroup TRACER_EMB * @{ */ /** @addtogroup TRACER_EMB * @{ */ /** @addtogroup TRACER_EMB * @{ */ /* Private enums -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /** @defgroup TRACER_EMB_Private_TypeDef EMB TRACER Private typedef * @{ */ typedef enum { TRACER_OVERFLOW_NONE, TRACER_OVERFLOW_DETECTED, TRACER_OVERFLOW_SENT } TRACER_OverFlowTypedef; /** * @} */ /** @defgroup TRACER_EMB_Private_TypeDef EMB TRACER Private typedef * @{ */ typedef enum { TRACER_OK, TRACER_KO } TRACER_StatusTypedef; /** * @} */ /** @defgroup TRACER_EMB_Private_TypeDef EMB TRACER Private typedef * @{ */ typedef struct { uint32_t PtrTx_Read; uint32_t PtrTx_Write; uint32_t SizeSent; uint32_t LowPower_Counter; volatile uint8_t Counter; const uint8_t *OverFlow_Data; uint8_t OverFlow_Size; uint8_t discontinue; TRACER_OverFlowTypedef OverFlow_Status; uint8_t PtrDataTx[TRACER_EMB_BUFFER_SIZE]; } TRACER_ContextTypedef; /** * @} */ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /** @defgroup TRACER_EMB_Private_Macros TRACE Private Macros * @{ */ #define TRACER_WRITE_DATA(_POSITION_,_DATA_) TracerContext.PtrDataTx[(_POSITION_)% TRACER_EMB_BUFFER_SIZE] = (_DATA_); \ (_POSITION_) = ((_POSITION_) + 1u) % TRACER_EMB_BUFFER_SIZE; #define TRACER_ENTER_CRITICAL_SECTION() uint32_t primask= __get_PRIMASK();\ __disable_irq(); #define TRACER_LEAVE_CRITICAL_SECTION() __set_PRIMASK(primask) /** * @} */ /* Private function prototypes -----------------------------------------------*/ /** @defgroup TRACER_EMB_Private_Functions TRACE Private Functions * @{ */ uint32_t TRACER_CallbackRX(uint8_t character, uint8_t error); /* Function prototypes -----------------------------------------------*/ uint8_t TRACER_EMB_ReadData(void); /** * @} */ /* Private variables ---------------------------------------------------------*/ /** @defgroup TRACER_EMB_Private_Variables TRACE Private Variables * @{ */ static TRACER_ContextTypedef TracerContext; /** * @} */ /* Exported functions ---------------------------------------------------------*/ /** @addtogroup TRACER_EMB_Exported_Functions * @{ */ void TRACER_EMB_Init(void) { /* initialize the Ptr for Read/Write */ memset(&TracerContext, 0, sizeof(TRACER_ContextTypedef)); /* Initialize trace BUS */ HW_TRACER_EMB_Init(); /* Initialize the lowpower aspect */ TRACER_EMB_LowPowerInit(); } void TRACER_EMB_Add(uint8_t *Ptr, uint32_t Size) { int32_t _writepos; uint8_t *data_to_write = Ptr; uint32_t index; /* Data processing */ TRACER_EMB_Lock(); _writepos = TRACER_EMB_AllocateBufer(Size); /* if allocation is ok, write data into the bufffer */ if (_writepos != -1) { /* initialize the Ptr for Read/Write */ for (index = 0u; index < Size; index++) { TRACER_WRITE_DATA(_writepos, data_to_write[index]); } } TRACER_EMB_UnLock(); /* Tx processing */ TRACER_EMB_SendData(); } #if TRACER_EMB_DMA_MODE == 1UL void TRACER_EMB_IRQHandlerDMA(void) { HW_TRACER_EMB_IRQHandlerDMA(); } #endif void TRACER_EMB_IRQHandlerUSART(void) { HW_TRACER_EMB_IRQHandlerUSART(); } void TRACER_EMB_WriteData(uint16_t pos, uint8_t data) { TracerContext.PtrDataTx[pos % TRACER_EMB_BUFFER_SIZE] = data; } void TRACER_EMB_StartRX(void (*callbackRX)(uint8_t, uint8_t)) { HW_TRACER_EMB_RegisterRxCallback(callbackRX); HW_TRACER_EMB_StartRX(); } int32_t TRACER_EMB_EnableOverFlow(const uint8_t *Data, uint8_t Size) { if(Size != 0) { TracerContext.OverFlow_Data = Data; TracerContext.OverFlow_Size = Size; return 0; } return -1; } uint8_t TRACER_EMB_ReadData() { return HW_TRACER_EMB_ReadData(); } /** * @} */ /** @defgroup TRACER_EMB_Private_Functions TRACE Private Functions * @{ */ /** * @brief callback called to end a transfert. * @param None. * @retval None. */ void TRACER_EMB_CALLBACK_TX(void) { TRACER_ENTER_CRITICAL_SECTION(); TracerContext.PtrTx_Read = (TracerContext.PtrTx_Read + TracerContext.SizeSent) % TRACER_EMB_BUFFER_SIZE; if((TracerContext.OverFlow_Data != NULL) && (TracerContext.OverFlow_Status == TRACER_OVERFLOW_DETECTED) && (TracerContext.discontinue == 0)) { TracerContext.OverFlow_Status = TRACER_OVERFLOW_SENT; HW_TRACER_EMB_SendData((uint8_t *)TracerContext.OverFlow_Data, TracerContext.OverFlow_Size); TRACER_LEAVE_CRITICAL_SECTION(); } else { TracerContext.LowPower_Counter--; TRACER_LEAVE_CRITICAL_SECTION(); TRACER_EMB_UnLock(); TRACER_EMB_SendData(); } } /** * @brief Lock the trace buffer. * @param None. * @retval None. */ void TRACER_EMB_Lock(void) { TRACER_ENTER_CRITICAL_SECTION(); TracerContext.Counter++; TRACER_LEAVE_CRITICAL_SECTION(); } /** * @brief UnLock the trace buffer. * @param None. * @retval None. */ void TRACER_EMB_UnLock(void) { TRACER_ENTER_CRITICAL_SECTION(); TracerContext.Counter--; TRACER_LEAVE_CRITICAL_SECTION(); } /** * @brief if buffer is not locked return a Begin / end @ to transfert over the media. * @param address begin of the data * @param address end of the data * @retval None. */ void TRACER_EMB_SendData(void) { uint32_t _begin; uint32_t _end; TRACER_ENTER_CRITICAL_SECTION(); if (0u == TracerContext.Counter) { _begin = TracerContext.PtrTx_Read; _end = TracerContext.PtrTx_Write; if (_begin != _end) { TRACER_EMB_Lock(); /* */ if (_end > _begin) { TracerContext.SizeSent = _end - _begin; TracerContext.discontinue = 0; } else /* _begin > _end */ { TracerContext.SizeSent = TRACER_EMB_BUFFER_SIZE - _begin; TracerContext.discontinue = 1; } TRACER_EMB_LowPowerSendData(); TracerContext.LowPower_Counter++; HW_TRACER_EMB_SendData(&(TracerContext.PtrDataTx[_begin]), TracerContext.SizeSent); } } /* Low power processing */ switch(TracerContext.LowPower_Counter) { case 1: TRACER_EMB_LowPowerSendData(); break; case 0 : TRACER_EMB_LowPowerSendDataComplete(); break; } TRACER_LEAVE_CRITICAL_SECTION(); } /** * @brief allocate space inside the buffer to push data * @param data size * @retval write position inside the buffer is -1 no space available. */ int32_t TRACER_EMB_AllocateBufer(uint32_t Size) { uint32_t _freesize; int32_t _pos = -1; TRACER_ENTER_CRITICAL_SECTION(); if (TracerContext.PtrTx_Write == TracerContext.PtrTx_Read) { // need to add buffer full managment _freesize = TRACER_EMB_BUFFER_SIZE; } else { if (TracerContext.PtrTx_Write > TracerContext.PtrTx_Read) { _freesize = TRACER_EMB_BUFFER_SIZE - TracerContext.PtrTx_Write + TracerContext.PtrTx_Read; } else { _freesize = TracerContext.PtrTx_Read - TracerContext.PtrTx_Write; } } if (_freesize > Size) { _pos = (int32_t)TracerContext.PtrTx_Write; TracerContext.PtrTx_Write = (TracerContext.PtrTx_Write + Size) % TRACER_EMB_BUFFER_SIZE; if(TRACER_OVERFLOW_SENT == TracerContext.OverFlow_Status) TracerContext.OverFlow_Status = TRACER_OVERFLOW_NONE; } else { if(TRACER_OVERFLOW_NONE == TracerContext.OverFlow_Status) TracerContext.OverFlow_Status = TRACER_OVERFLOW_DETECTED; } TRACER_LEAVE_CRITICAL_SECTION(); return _pos; } __weak void TRACER_EMB_LowPowerInit(void) { } __weak void TRACER_EMB_LowPowerSendData(void) { } __weak void TRACER_EMB_LowPowerSendDataComplete(void) { } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/