blob: ae549b4003d4ae3a56792ca57c230201cd07d614 [file] [log] [blame]
/*
* Copyright 2018 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "fsl_common.h"
#include "serial_manager.h"
#if (defined(SERIAL_PORT_TYPE_SWO) && (SERIAL_PORT_TYPE_SWO > 0U))
#include "serial_port_swo.h"
/*******************************************************************************
* Definitions
******************************************************************************/
#ifndef NDEBUG
#if (defined(DEBUG_CONSOLE_ASSERT_DISABLE) && (DEBUG_CONSOLE_ASSERT_DISABLE > 0U))
#undef assert
#define assert(n)
#endif
#endif
typedef struct _serial_swo_state
{
serial_manager_callback_t txCallback;
void *txCallbackParam;
uint32_t port;
} serial_swo_state_t;
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
serial_manager_status_t Serial_SwoInit(serial_handle_t serialHandle, void *serialConfig)
{
serial_swo_state_t *serialSwoHandle;
serial_port_swo_config_t *swoConfig;
uint32_t prescaler;
assert(serialConfig);
assert(serialHandle);
if (SERIAL_PORT_SWO_HANDLE_SIZE < sizeof(serial_swo_state_t))
{
return kStatus_SerialManager_Error;
}
swoConfig = (serial_port_swo_config_t *)serialConfig;
assert(swoConfig->baudRate <= swoConfig->clockRate);
assert((swoConfig->clockRate / swoConfig->baudRate) <= TPI_ACPR_PRESCALER_Msk);
assert((TPI->DEVID & (TPI_DEVID_NRZVALID_Msk | TPI_DEVID_MANCVALID_Msk)) != 0U);
serialSwoHandle = (serial_swo_state_t *)serialHandle;
serialSwoHandle->port = swoConfig->port;
prescaler = swoConfig->clockRate / swoConfig->baudRate - 1U;
/* enable the ITM and DWT units */
CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk;
if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) == 0U)
{
return kStatus_SerialManager_Error;
}
/* Lock access */
ITM->LAR = 0xC5ACCE55U;
/* Disable ITM */
ITM->TER &= ~(1U << swoConfig->port);
ITM->TCR = 0U;
/* select SWO encoding protocol */
TPI->SPPR = swoConfig->protocol;
/* select asynchronous clock prescaler */
TPI->ACPR = prescaler & 0xFFFFU;
/* allow unprivilege access */
ITM->TPR = 0U;
/* enable ITM */
ITM->TCR = ITM_TCR_ITMENA_Msk | ITM_TCR_SYNCENA_Msk
#ifdef ITM_TCR_TraceBusID_Msk
| ITM_TCR_TraceBusID_Msk
#elif defined(ITM_TCR_TRACEBUSID_Msk)
| ITM_TCR_TRACEBUSID_Msk
#else
#endif
| ITM_TCR_SWOENA_Msk | ITM_TCR_DWTENA_Msk;
/* enable the port bits */
ITM->TER = 1U << swoConfig->port;
return kStatus_SerialManager_Success;
}
serial_manager_status_t Serial_SwoDeinit(serial_handle_t serialHandle)
{
serial_swo_state_t *serialSwoHandle;
assert(serialHandle);
serialSwoHandle = (serial_swo_state_t *)serialHandle;
/* disable ITM */
ITM->TER &= ~(1U << serialSwoHandle->port);
return kStatus_SerialManager_Success;
}
serial_manager_status_t Serial_SwoWrite(serial_handle_t serialHandle, uint8_t *buffer, uint32_t length)
{
serial_swo_state_t *serialSwoHandle;
uint8_t *strAddr;
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
serial_manager_callback_message_t msg;
#endif
assert(serialHandle);
assert(buffer);
assert(length);
serialSwoHandle = (serial_swo_state_t *)serialHandle;
assert((ITM->TCR & ITM_TCR_ITMENA_Msk) != 0U);
assert((ITM->TER & (1U << serialSwoHandle->port)) != 0U);
strAddr = buffer;
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
msg.buffer = buffer;
msg.length = length;
#endif
while (length)
{
/* wait FIFO ready */
while (ITM->PORT[serialSwoHandle->port].u32 == 0U)
{
}
length -= 1U;
ITM->PORT[serialSwoHandle->port].u8 = *strAddr;
strAddr++;
}
#if (defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
if (NULL != serialSwoHandle->txCallback)
{
serialSwoHandle->txCallback(serialSwoHandle->txCallbackParam, &msg, kStatus_SerialManager_Success);
}
#endif
return kStatus_SerialManager_Success;
}
#if !(defined(SERIAL_MANAGER_NON_BLOCKING_MODE) && (SERIAL_MANAGER_NON_BLOCKING_MODE > 0U))
serial_manager_status_t Serial_SwoRead(serial_handle_t serialHandle, uint8_t *buffer, uint32_t length)
{
return kStatus_SerialManager_Error;
}
#endif
serial_manager_status_t Serial_SwoCancelWrite(serial_handle_t serialHandle)
{
return kStatus_SerialManager_Error;
}
serial_manager_status_t Serial_SwoInstallTxCallback(serial_handle_t serialHandle,
serial_manager_callback_t callback,
void *callbackParam)
{
serial_swo_state_t *serialSwoHandle;
assert(serialHandle);
serialSwoHandle = (serial_swo_state_t *)serialHandle;
serialSwoHandle->txCallback = callback;
serialSwoHandle->txCallbackParam = callbackParam;
return kStatus_SerialManager_Success;
}
serial_manager_status_t Serial_SwoInstallRxCallback(serial_handle_t serialHandle,
serial_manager_callback_t callback,
void *callbackParam)
{
return kStatus_SerialManager_Error;
}
void Serial_SwoIsrFunction(serial_handle_t serialHandle)
{
}
#endif