550 lines
18 KiB
C
550 lines
18 KiB
C
//###########################################################################
|
|
//
|
|
// FILE: erad.c
|
|
//
|
|
// TITLE: C28x ERAD driver.
|
|
//
|
|
//###########################################################################
|
|
|
|
#include "erad.h"
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_configBusComp
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_configBusComp(uint32_t base, ERAD_BusComp_Config config_params)
|
|
{
|
|
//
|
|
// Check if owner is APPLICATION or NO_OWNER
|
|
//
|
|
ASSERT((ERAD_getOwnership() == ERAD_OWNER_APPLICATION) ||
|
|
(ERAD_getOwnership() == ERAD_OWNER_NOOWNER));
|
|
|
|
//
|
|
// Check if the base is valid
|
|
//
|
|
ASSERT(ERAD_isValidBusCompBase(base));
|
|
|
|
//
|
|
// Check if the bus comparator is in ERAD_STATE_IDLE
|
|
//
|
|
ASSERT(ERAD_getBusCompStatus(base) == ERAD_STATE_IDLE);
|
|
|
|
//
|
|
// Write into necessary registers to configure the bus comparator
|
|
//
|
|
EALLOW;
|
|
HWREG(base + ERAD_O_HWBP_MASK) = config_params.mask;
|
|
HWREG(base + ERAD_O_HWBP_REF) = config_params.reference;
|
|
|
|
//
|
|
// Set the comparison mode and the CPU bus to be monitored
|
|
// Enable interrupt and CPU halt if specified in the parameters
|
|
//
|
|
HWREGH(base + ERAD_O_HWBP_CNTL) =
|
|
((uint16_t)config_params.comp_mode << ERAD_HWBP_CNTL_COMP_MODE_S) |
|
|
((uint16_t)config_params.bus_sel << ERAD_HWBP_CNTL_BUS_SEL_S) |
|
|
((uint16_t)config_params.enable_stop << ERAD_HWBP_CNTL_STOP_S) |
|
|
((uint16_t)config_params.enable_int << ERAD_HWBP_CNTL_RTOSINT_S);
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_configCounterInCountingMode
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_configCounterInCountingMode(uint32_t base,
|
|
ERAD_Counter_Config config_params)
|
|
{
|
|
//
|
|
// Check if owner is APPLICATION or NO_OWNER
|
|
//
|
|
ASSERT((ERAD_getOwnership() == ERAD_OWNER_APPLICATION) ||
|
|
(ERAD_getOwnership() == ERAD_OWNER_NOOWNER));
|
|
|
|
//
|
|
// Check if the base is valid
|
|
//
|
|
ASSERT(ERAD_isValidCounterBase(base));
|
|
|
|
//
|
|
// Check if the counter is in ERAD_STATE_IDLE
|
|
//
|
|
ASSERT(ERAD_getCounterStatus(base) == ERAD_STATE_IDLE);
|
|
|
|
//
|
|
// Write into registers to configure the counter
|
|
//
|
|
EALLOW;
|
|
|
|
HWREG(base + ERAD_O_CTM_REF) = config_params.reference;
|
|
|
|
if(config_params.event == ERAD_EVENT_NO_EVENT)
|
|
{
|
|
//
|
|
// If ERAD_EVENT_NO_EVENT is selected, clear the counter input select
|
|
// enable bit. The counter will count CPU cycles.
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) &= ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For any other value, set the event to be counted and counter input
|
|
// select enable bit.
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL) =
|
|
(((uint16_t)config_params.event << ERAD_CTM_INPUT_SEL_CNT_INP_SEL_S) &
|
|
ERAD_CTM_INPUT_SEL_CNT_INP_SEL_M);
|
|
|
|
HWREGH(base + ERAD_O_CTM_CNTL) |= ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
}
|
|
|
|
//
|
|
// Set the counter in Normal count mode
|
|
// Set the event mode as Rising edge or Active
|
|
// Enable interrupt, CPU halt and reset on match if specified in the
|
|
// parameters
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) =
|
|
(HWREGH(base + ERAD_O_CTM_CNTL) & (~(ERAD_CTM_CNTL_START_STOP_CUMULATIVE |
|
|
ERAD_CTM_CNTL_RTOSINT |
|
|
ERAD_CTM_CNTL_STOP |
|
|
ERAD_CTM_CNTL_RST_ON_MATCH |
|
|
ERAD_CTM_CNTL_EVENT_MODE |
|
|
ERAD_CTM_CNTL_START_STOP_MODE))) |
|
|
((uint16_t)config_params.enable_int << ERAD_CTM_CNTL_RTOSINT_S) |
|
|
((uint16_t)config_params.enable_stop << ERAD_CTM_CNTL_STOP_S) |
|
|
((uint16_t)config_params.event_mode << ERAD_CTM_CNTL_EVENT_MODE_S) |
|
|
((uint16_t)config_params.rst_on_match << ERAD_CTM_CNTL_RST_ON_MATCH_S);
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_configCounterInStartStopMode
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_configCounterInStartStopMode(uint32_t base,
|
|
ERAD_Counter_Config config_params,
|
|
ERAD_Counter_Input_Event start_event,
|
|
ERAD_Counter_Input_Event stop_event)
|
|
{
|
|
//
|
|
// Check if owner is APPLICATION or NO_OWNER
|
|
//
|
|
ASSERT((ERAD_getOwnership() == ERAD_OWNER_APPLICATION) ||
|
|
(ERAD_getOwnership() == ERAD_OWNER_NOOWNER));
|
|
|
|
//
|
|
// Check if the base is valid
|
|
//
|
|
ASSERT(ERAD_isValidCounterBase(base));
|
|
|
|
//
|
|
// Check if the counter is in IDLE state
|
|
//
|
|
ASSERT(ERAD_getCounterStatus(base) == ERAD_STATE_IDLE);
|
|
|
|
//
|
|
// Write into registers to configure the counter
|
|
//
|
|
EALLOW;
|
|
|
|
HWREG(base + ERAD_O_CTM_REF) = config_params.reference;
|
|
|
|
if(config_params.event == ERAD_EVENT_NO_EVENT)
|
|
{
|
|
//
|
|
// If ERAD_EVENT_NO_EVENT is selected, clear the counter input select
|
|
// enable bit. The counter will count CPU cycles.
|
|
// Set start and stop events
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) &= ~ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL) =
|
|
((uint16_t)start_event << ERAD_CTM_INPUT_SEL_STA_INP_SEL_S);
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL_2) |=
|
|
((uint16_t)stop_event << ERAD_CTM_INPUT_SEL_2_STO_INP_SEL_S);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For any other value, set the counter input select enable bit and
|
|
// configure the counter input, start event and stop event,
|
|
//
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) |= ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL) =
|
|
((uint16_t)config_params.event << ERAD_CTM_INPUT_SEL_CNT_INP_SEL_S) |
|
|
((uint16_t)start_event << ERAD_CTM_INPUT_SEL_STA_INP_SEL_S);
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL_2) |=
|
|
((uint16_t)stop_event << ERAD_CTM_INPUT_SEL_2_STO_INP_SEL_S);
|
|
|
|
}
|
|
|
|
//
|
|
// Set the counter in Normal count mode
|
|
// Set the event mode as Rising edge or Active
|
|
// Enable interrupt, CPU halt and reset on match if specified in the
|
|
// parameters
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) =
|
|
(HWREGH(base + ERAD_O_CTM_CNTL) & (~(ERAD_CTM_CNTL_START_STOP_CUMULATIVE |
|
|
ERAD_CTM_CNTL_RTOSINT |
|
|
ERAD_CTM_CNTL_STOP |
|
|
ERAD_CTM_CNTL_RST_ON_MATCH |
|
|
ERAD_CTM_CNTL_EVENT_MODE))) |
|
|
ERAD_CTM_CNTL_START_STOP_MODE |
|
|
((uint16_t)config_params.enable_int << ERAD_CTM_CNTL_RTOSINT_S) |
|
|
((uint16_t)config_params.enable_stop << ERAD_CTM_CNTL_STOP_S) |
|
|
((uint16_t)config_params.event_mode << ERAD_CTM_CNTL_EVENT_MODE_S) |
|
|
((uint16_t)config_params.rst_on_match << ERAD_CTM_CNTL_RST_ON_MATCH_S);
|
|
|
|
EDIS;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_configCounterInCumulativeMode
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_configCounterInCumulativeMode(uint32_t base,
|
|
ERAD_Counter_Config config_params,
|
|
ERAD_Counter_Input_Event start_event,
|
|
ERAD_Counter_Input_Event stop_event)
|
|
{
|
|
//
|
|
// Check if owner is APPLICATION or NO_OWNER
|
|
//
|
|
ASSERT((ERAD_getOwnership() == ERAD_OWNER_APPLICATION) ||
|
|
(ERAD_getOwnership() == ERAD_OWNER_NOOWNER));
|
|
|
|
//
|
|
// Check if the base is valid
|
|
//
|
|
ASSERT(ERAD_isValidCounterBase(base));
|
|
|
|
//
|
|
// Check if the counter is in IDLE state
|
|
//
|
|
ASSERT(ERAD_getCounterStatus(base) == ERAD_STATE_IDLE);
|
|
|
|
//
|
|
// Write into registers to configure the counter
|
|
//
|
|
EALLOW;
|
|
|
|
HWREG(base + ERAD_O_CTM_REF) = config_params.reference;
|
|
|
|
if(config_params.event == ERAD_EVENT_NO_EVENT)
|
|
{
|
|
//
|
|
// If ERAD_EVENT_NO_EVENT is selected, clear the counter input select
|
|
// enable bit. The counter will count CPU cycles.
|
|
// Set start and stop events
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) &= ~ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL) =
|
|
((uint16_t)start_event << ERAD_CTM_INPUT_SEL_STA_INP_SEL_S);
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL_2) |=
|
|
((uint16_t)stop_event << ERAD_CTM_INPUT_SEL_2_STO_INP_SEL_S);
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// For any other value, set the counter input select enable bit and
|
|
// configure the counter input, start event and stop event,
|
|
//
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) |= ERAD_CTM_CNTL_CNT_INP_SEL_EN;
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL) =
|
|
((uint16_t)config_params.event << ERAD_CTM_INPUT_SEL_CNT_INP_SEL_S) |
|
|
((uint16_t)start_event << ERAD_CTM_INPUT_SEL_STA_INP_SEL_S);
|
|
|
|
HWREGH(base + ERAD_O_CTM_INPUT_SEL_2) |=
|
|
((uint16_t)stop_event << ERAD_CTM_INPUT_SEL_2_STO_INP_SEL_S);
|
|
|
|
}
|
|
|
|
//
|
|
// Set the counter in Normal count mode
|
|
// Set the event mode as Rising edge or Active
|
|
// Enable interrupt, CPU halt and reset on match if specified in the
|
|
// parameters
|
|
//
|
|
HWREGH(base + ERAD_O_CTM_CNTL) =
|
|
(HWREGH(base + ERAD_O_CTM_CNTL) & (~(ERAD_CTM_CNTL_RTOSINT |
|
|
ERAD_CTM_CNTL_STOP |
|
|
ERAD_CTM_CNTL_RST_ON_MATCH |
|
|
ERAD_CTM_CNTL_EVENT_MODE))) |
|
|
ERAD_CTM_CNTL_START_STOP_MODE |
|
|
ERAD_CTM_CNTL_START_STOP_CUMULATIVE |
|
|
((uint16_t)config_params.enable_int << ERAD_CTM_CNTL_RTOSINT_S) |
|
|
((uint16_t)config_params.enable_stop << ERAD_CTM_CNTL_STOP_S) |
|
|
((uint16_t)config_params.event_mode << ERAD_CTM_CNTL_EVENT_MODE_S) |
|
|
((uint16_t)config_params.rst_on_match << ERAD_CTM_CNTL_RST_ON_MATCH_S);
|
|
|
|
EDIS;
|
|
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_configMask
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_configMask(ERAD_Mask mask, uint32_t instances, bool enable_int)
|
|
{
|
|
uint16_t bitpos;
|
|
uint16_t mask_tmp = (uint16_t)mask;
|
|
|
|
EALLOW;
|
|
|
|
if(mask_tmp < 4U)
|
|
{
|
|
bitpos = mask_tmp << 3U;
|
|
|
|
HWREG(ERAD_GLOBAL_BASE + ERAD_O_GLBL_EVENT_AND_MASK) =
|
|
(HWREG(ERAD_GLOBAL_BASE + ERAD_O_GLBL_EVENT_AND_MASK) |
|
|
(0xFFUL << bitpos)) & (~(instances << bitpos));
|
|
|
|
bitpos = mask_tmp;
|
|
|
|
if(enable_int)
|
|
{
|
|
HWREGH(ERAD_GLOBAL_BASE + ERAD_O_GLBL_AND_EVENT_INT_MASK) &=
|
|
~(1U << bitpos);
|
|
}
|
|
else
|
|
{
|
|
HWREGH(ERAD_GLOBAL_BASE + ERAD_O_GLBL_AND_EVENT_INT_MASK) |=
|
|
(1U << bitpos);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bitpos = (mask_tmp - 4U) << 3U;
|
|
|
|
HWREG(ERAD_GLOBAL_BASE + ERAD_O_GLBL_EVENT_OR_MASK) =
|
|
(HWREG(ERAD_GLOBAL_BASE + ERAD_O_GLBL_EVENT_OR_MASK) |
|
|
(0xFFUL << bitpos)) & (~(instances << bitpos));
|
|
|
|
bitpos = mask_tmp - 4U;
|
|
|
|
if(enable_int)
|
|
{
|
|
HWREGH(ERAD_GLOBAL_BASE + ERAD_O_GLBL_OR_EVENT_INT_MASK) &=
|
|
~(1U << bitpos);
|
|
}
|
|
else
|
|
{
|
|
HWREGH(ERAD_GLOBAL_BASE + ERAD_O_GLBL_OR_EVENT_INT_MASK) |=
|
|
(1U << bitpos);
|
|
}
|
|
}
|
|
EDIS;
|
|
}
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_profile
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_profile(ERAD_Profile_Params config_params)
|
|
{
|
|
ERAD_BusComp_Config buscomp1_params, buscomp2_params;
|
|
ERAD_Counter_Config counter_params;
|
|
|
|
//
|
|
// Clear any previous events
|
|
//
|
|
ERAD_clearBusCompEvent(config_params.busComp_base1);
|
|
ERAD_clearBusCompEvent(config_params.busComp_base2);
|
|
|
|
//
|
|
// Clear any previous events and overflow
|
|
//
|
|
ERAD_clearCounterEvent(config_params.counter_base);
|
|
ERAD_clearCounterOverflow(config_params.counter_base);
|
|
|
|
//
|
|
// Reset the counter
|
|
//
|
|
ERAD_resetCounter(ERAD_getCounterInstance(config_params.counter_base));
|
|
|
|
//
|
|
// Configure the first bus comparator
|
|
// No interrupt or CPU halt. Compare for equality. No mask.
|
|
// Reference is the address of the first instruction
|
|
//
|
|
buscomp1_params.bus_sel = config_params.bus_sel;
|
|
buscomp1_params.comp_mode = ERAD_BUSCOMP_COMPMODE_EQ;
|
|
buscomp1_params.enable_stop = 0;
|
|
buscomp1_params.enable_int = 0;
|
|
buscomp1_params.mask = 0x0;
|
|
buscomp1_params.reference = config_params.start_address;
|
|
ERAD_configBusComp(config_params.busComp_base1, buscomp1_params);
|
|
|
|
//
|
|
// Configure the second bus comparator
|
|
// No interrupt or CPU halt. Compare for equality. No mask.
|
|
// Reference is the address of the last instruction
|
|
//
|
|
buscomp2_params.bus_sel = config_params.bus_sel;
|
|
buscomp2_params.comp_mode = ERAD_BUSCOMP_COMPMODE_EQ;
|
|
buscomp2_params.enable_stop = 0;
|
|
buscomp2_params.enable_int = 0;
|
|
buscomp2_params.mask = 0x0;
|
|
buscomp2_params.reference = config_params.end_address;
|
|
ERAD_configBusComp(config_params.busComp_base2, buscomp2_params);
|
|
|
|
//
|
|
// Configure the counter
|
|
// No interrupt, no CPU halt, no reset on match, no reference.
|
|
// Counting the number of CPU cycles
|
|
// Start event is the first bus comparator and stop is the second
|
|
//
|
|
counter_params.enable_int = 0;
|
|
counter_params.enable_stop = 0;
|
|
counter_params.rst_on_match = 0;
|
|
counter_params.reference = 0x0;
|
|
counter_params.event_mode = ERAD_COUNTER_MODE_ACTIVE;
|
|
counter_params.event = ERAD_EVENT_NO_EVENT;
|
|
ERAD_Counter_Input_Event start = (ERAD_Counter_Input_Event)
|
|
(ERAD_BUSCOMP_BASE_TO_EVENT(config_params.busComp_base1));
|
|
ERAD_Counter_Input_Event stop = (ERAD_Counter_Input_Event)
|
|
(ERAD_BUSCOMP_BASE_TO_EVENT(config_params.busComp_base2));
|
|
ERAD_configCounterInStartStopMode(config_params.counter_base,
|
|
counter_params, start, stop);
|
|
|
|
//
|
|
// Enable the modules
|
|
//
|
|
ERAD_enableModules(ERAD_getBusCompInstance(config_params.busComp_base1) |
|
|
ERAD_getBusCompInstance(config_params.busComp_base2) |
|
|
ERAD_getCounterInstance(config_params.counter_base));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_enableInterruptAtAddress
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_enableInterruptOnAddressHit(ERAD_AddressHit_Params config_params,
|
|
uint32_t busComp_base)
|
|
{
|
|
ERAD_BusComp_Config buscomp_params;
|
|
|
|
//
|
|
// Clear any previous events
|
|
//
|
|
ERAD_clearBusCompEvent(busComp_base);
|
|
|
|
//
|
|
// Set the address and mask. Disable CPU halt
|
|
// and enable Interrupt
|
|
//
|
|
buscomp_params.reference = config_params.address;
|
|
buscomp_params.mask = config_params.mask;
|
|
buscomp_params.enable_stop = 0;
|
|
buscomp_params.enable_int = 1;
|
|
|
|
//
|
|
// Comparison mode is set to equality and the bus to be
|
|
// monitored is the Virtual Program Counter
|
|
//
|
|
buscomp_params.comp_mode = ERAD_BUSCOMP_COMPMODE_EQ;
|
|
buscomp_params.bus_sel = config_params.bus_sel;
|
|
|
|
//
|
|
// Configure the bus comparator
|
|
//
|
|
ERAD_configBusComp(busComp_base, buscomp_params);
|
|
|
|
//
|
|
// Enable the bus comparator
|
|
//
|
|
ERAD_enableModules(ERAD_getBusCompInstance(busComp_base));
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// ERAD_countEventHits
|
|
//
|
|
//*****************************************************************************
|
|
void
|
|
ERAD_countAddressHits(ERAD_AddressHit_Params config_params,
|
|
uint32_t busComp_base, uint32_t counter_base)
|
|
{
|
|
ERAD_BusComp_Config buscomp_params;
|
|
ERAD_Counter_Config counter_params;
|
|
|
|
//
|
|
// Clear any previous events and overflows
|
|
//
|
|
ERAD_clearBusCompEvent(busComp_base);
|
|
ERAD_clearCounterEvent(counter_base);
|
|
ERAD_clearCounterOverflow(counter_base);
|
|
|
|
//
|
|
// Reset the counter
|
|
//
|
|
ERAD_resetCounter(ERAD_getCounterInstance(counter_base));
|
|
|
|
//
|
|
// Configure the bus comparator
|
|
// No interrupt or CPU halt. Compare for equality. No mask.
|
|
// Reference is the address of the instruction to be counted
|
|
// Bus to be monitored is specified in the bus argument
|
|
//
|
|
buscomp_params.reference = config_params.address;
|
|
buscomp_params.mask = config_params.mask;
|
|
buscomp_params.comp_mode = ERAD_BUSCOMP_COMPMODE_EQ;
|
|
buscomp_params.enable_stop = 0;
|
|
buscomp_params.bus_sel = config_params.bus_sel;
|
|
buscomp_params.enable_int = 0;
|
|
ERAD_configBusComp(busComp_base, buscomp_params);
|
|
|
|
//
|
|
// Configure the counter
|
|
// No interrupt, no CPU halt, no reset on match, no reference.
|
|
// Counting the number of rising edges of the bus comparator event
|
|
//
|
|
counter_params.enable_int = 0;
|
|
counter_params.enable_stop = 0;
|
|
counter_params.event_mode = ERAD_COUNTER_MODE_RISING_EDGE;
|
|
counter_params.rst_on_match = 0;
|
|
counter_params.reference = 0x0;
|
|
counter_params.event = (ERAD_Counter_Input_Event)
|
|
(ERAD_BUSCOMP_BASE_TO_EVENT(busComp_base));
|
|
ERAD_configCounterInCountingMode(counter_base, counter_params);
|
|
|
|
//
|
|
// Enable the modules
|
|
//
|
|
ERAD_enableModules(ERAD_getBusCompInstance(busComp_base) |
|
|
ERAD_getCounterInstance(counter_base));
|
|
}
|
|
|
|
//
|
|
// End of file
|
|
//
|