393 lines
9.1 KiB
C
393 lines
9.1 KiB
C
/**
|
|
******************************************************************************
|
|
* @file tracer_emb.c
|
|
* @author MCD Application Team
|
|
* @brief This file contains embeded tracer control functions.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© Copyright (c) 2018 STMicroelectronics.
|
|
* All rights reserved.</center></h2>
|
|
*
|
|
* 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****/
|
|
|