Tool/software:
Hello!
I am running into a issue when testing my EPI performance. I am using the EPI to interface with a Lattice FPGA.
Setup Details:
static int32_t SetEpiParams
(
EpiDriverConfigParamsType* params ///< EPI Parameter pointer
)
{
int32_t returnVal = -1;
if (params)
{
params->clkDiv = 64;
params->config = (EPI_GPMODE_CLKPIN | EPI_GPMODE_CLKGATE | EPI_GPMODE_FRAME50 | EPI_GPMODE_ASIZE_20 | EPI_GPMODE_DSIZE_8 | EPI_GPMODE_WRITE2CYCLE);
params->frameCount = 0;
params->addrMap = (EPI_ADDR_PER_BASE_NONE | EPI_ADDR_PER_BASE_A);
returnVal = 1;
}
return returnVal;
}
Starting Base Address:
#define EPI_PERIPH_ADDR 0xA0000000
The test I am doing, writes a random 8-bit values to offset 0 and then another random 8-bit to offset 1. Then I go back and read from offset 0 and offset 1. If the values read back on the inverse of the original values, that test passes, and the offset is incremented by 2, and the process continues.
The problem is that once my address equals 0xA0000110, the code freezes up when I try to perform a read. I have disconnected the FPGA, but still I can't read from this address, and the debugger itself wont step any further.
I suspect that I've setup the EPI incorrectly. I want it to be general purpose, 20 address bits, 8 data bits.
///////////////////////////////////////////////////////////////////////////////
/** @file "epi_drv.c"
-----------------------------------------------------------
@b Details
The external peripheral interface (EPI) is configured in general purpose
A20, D8 mode to interface with an external FPGA.
----------------------------------------------------------------------------------
-- Company: LASP, EGSE
-- Engineer: N. Madinger
-- Modified by N. Madinger
-- Create Date: 20 May 2025
-- Design Name: BETSI MCU
-- Project Name: BETSI
-- Target Devices: TIVA
-- Tool versions: CCS 12.5
@b
Description: This contains the initialization, and interface functions for the
EPI interface, as it relates to the general purpose interface with an external
FPGA.
Copyright 2025 (c) by: LASP
-----------------------------------------------------------
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
#include <string.h>
#include "epi_drv.h"
#include "epi_fpga_tempSensor.h"
#include "inc/hw_epi.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/epi.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
//#include "driverlib/uart.h"
//#include "utils/uartstdio.h"
// Constants
// Modular Variables
static EpiDriverSysType epiDriverSys;
// ============================================================================
// Private Functions
// ============================================================================
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Clears the modular variable.
*/
static int32_t ClearModVars
(
EpiDriverSysType* epiModVarPtr ///< Pointer to EPI driver modular variable
)
{
int32_t returnVal = -1;
if (epiModVarPtr)
{
returnVal = 1;
memset(epiModVarPtr,0,sizeof(EpiDriverSysType));
}
return returnVal;
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortA(void)
{
GPIOPinConfigure(GPIO_PA6_EPI0S8);
GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6);
GPIOPinConfigure(GPIO_PA7_EPI0S9);
GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_7);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortB(void)
{
GPIOPinConfigure(GPIO_PB2_EPI0S27);
GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_2);
GPIOPinConfigure(GPIO_PB3_EPI0S28);
GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortC(void)
{
GPIOPinConfigure(GPIO_PC4_EPI0S7);
GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4);
GPIOPinConfigure(GPIO_PC5_EPI0S6);
GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_5);
GPIOPinConfigure(GPIO_PC6_EPI0S5);
GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_6);
GPIOPinConfigure(GPIO_PC7_EPI0S4);
GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_7);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortG(void)
{
GPIOPinConfigure(GPIO_PG0_EPI0S11);
GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PG1_EPI0S10);
GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_1);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortH(void)
{
GPIOPinConfigure(GPIO_PH0_EPI0S0);
GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PH1_EPI0S1);
GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PH2_EPI0S2);
GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_2);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortK(void)
{
GPIOPinConfigure(GPIO_PK3_EPI0S3);
GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_3);
GPIOPinConfigure(GPIO_PK5_EPI0S31);
GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_5);
GPIOPinConfigure(GPIO_PK6_EPI0S25);
GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_6);
GPIOPinConfigure(GPIO_PK7_EPI0S24);
GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_7);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortL(void)
{
GPIOPinConfigure(GPIO_PL0_EPI0S16);
GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PL1_EPI0S17);
GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PL2_EPI0S18);
GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_2);
GPIOPinConfigure(GPIO_PL3_EPI0S19);
GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_3);
GPIOPinConfigure(GPIO_PL4_EPI0S26);
GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_4);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortM(void)
{
GPIOPinConfigure(GPIO_PM0_EPI0S15);
GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PM1_EPI0S14);
GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PM2_EPI0S13);
GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_2);
GPIOPinConfigure(GPIO_PM3_EPI0S12);
GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_3);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortN(void)
{
GPIOPinConfigure(GPIO_PN2_EPI0S29);
GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_2);
GPIOPinConfigure(GPIO_PN3_EPI0S30);
GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_3);
}
//=============================================================================
/**
@return
- void
Initializes specific port for EPI functionality.
*/
static void InitEpiPortQ(void)
{
GPIOPinConfigure(GPIO_PQ0_EPI0S20);
GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_0);
GPIOPinConfigure(GPIO_PQ1_EPI0S21);
GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_1);
GPIOPinConfigure(GPIO_PQ2_EPI0S22);
GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_2);
GPIOPinConfigure(GPIO_PQ3_EPI0S23);
GPIOPinTypeEPI(GPIO_PORTQ_BASE, GPIO_PIN_3);
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Configures EPI GPIO by configuring ports.
*/
static int32_t InitEpiGpio(void)
{
int32_t returnVal = -1;
InitEpiPortA();
InitEpiPortB();
InitEpiPortC();
InitEpiPortG();
InitEpiPortH();
InitEpiPortK();
InitEpiPortL();
InitEpiPortM();
InitEpiPortN();
InitEpiPortQ();
returnVal = 1;
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Sets the initial settings for the EPI parameters.
*/
static int32_t SetEpiParams
(
EpiDriverConfigParamsType* params ///< EPI Parameter pointer
)
{
int32_t returnVal = -1;
if (params)
{
params->clkDiv = 64;
params->config = (EPI_GPMODE_CLKPIN | EPI_GPMODE_CLKGATE | EPI_GPMODE_FRAME50 | EPI_GPMODE_ASIZE_20 | EPI_GPMODE_DSIZE_8 | EPI_GPMODE_WRITE2CYCLE);
params->frameCount = 0;
params->addrMap = (EPI_ADDR_PER_BASE_NONE | EPI_ADDR_PER_BASE_A);
returnVal = 1;
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Configures EPI GPIO by configuring ports.
*/
static int32_t InitEpiPerph
(
EpiDriverConfigParamsType* params ///< EPI Parameter pointer
)
{
int32_t returnVal = -1;
if (params)
{
//
// The EPI0 peripheral must be enabled for use.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0);
//
// Sets the usage mode of the EPI module.
// The general purpose 8-bit data mode will be used.
//
EPIModeSet(EPI0_BASE, EPI_MODE_GENERAL);
//EPI CLK is 1/2 of SysClk
EPIDividerSet(EPI0_BASE, params->clkDiv);
EPIConfigGPModeSet
(
EPI0_BASE,
params->config,
params->frameCount,
0
);
EPIAddressMapSet(EPI0_BASE, params->addrMap);
//epiDriverSys.epiConfigParams = (*params);
returnVal = 1;
}
return returnVal;
}
// ============================================================================
// Public Functions
// ============================================================================
//=============================================================================
/**
@return
- int32_t: positive value means success; negative value means error; 0 is invalid
Initializes the EPI interface to general purpose A20, D8 mode.
*/
int32_t InitEpi(void)
{
int32_t returnVal = -1;
returnVal = ClearModVars(&epiDriverSys);
if (0 < returnVal)
{
returnVal = InitEpiGpio();
if (0 < returnVal)
{
returnVal = SetEpiParams(&epiDriverSys.epiConfigParams);
if (0 < returnVal)
{
InitEpiPerph(&epiDriverSys.epiConfigParams);
epiDriverSys.epiDriverInitStatus = epiDriver_isInit;
}
}
}
return returnVal;
}//InitEpi
///////////////////////////////////////////////////////////////////////////////
/** @file "epi_test.c"
-----------------------------------------------------------
@b Details
The external peripheral interface (EPI) is configured in general purpose
A20, D8 mode to interface with an external FPGA.
----------------------------------------------------------------------------------
-- Company: LASP, EGSE
-- Engineer: N. Madinger
-- Modified by N. Madinger
-- Create Date: 23 May 2025
-- Design Name: BETSI MCU
-- Project Name: BETSI
-- Target Devices: TIVA
-- Tool versions: CCS 12.5
@b
Description: This contains the initialization, and interface functions for the
EPI interface, as it relates to the general purpose interface with an external
FPGA.
Copyright 2025 (c) by: LASP
-----------------------------------------------------------
*/
///////////////////////////////////////////////////////////////////////////////
// Includes
#include <string.h>
#include <stdlib.h>
#include "epi_test.h"
#include "epi_drv.h"
#include "epi_fpga_tempSensor.h"
#include "inc/hw_epi.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/epi.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
//#include "driverlib/uart.h"
//#include "utils/uartstdio.h"
// Constants
// Modular Variables
static EpiTestSysType epiTestSys;
// ============================================================================
// Private Functions
// ============================================================================
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Clears the modular variable.
*/
static int32_t ClearModVars
(
EpiTestSysType* epiModVarPtr ///< Pointer to EPI driver modular variable
)
{
int32_t returnVal = -1;
if (epiModVarPtr)
{
returnVal = 1;
memset(epiModVarPtr,0,sizeof(EpiTestSysType));
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Assigns peripheral base address to pointer;
*/
int32_t AssignAddrToPrt
(
void** ptr, ///< Reference to pointer
uint32_t addr ///< Base address
)
{
int32_t returnVal = -1;
if (ptr)
{
(*ptr) = ((void*)(addr));
returnVal = 1;
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Assigns peripheral structure pointers to peripheral base addresses.
*/
static int32_t SetPerphPointer
(
EpiPerphPtrsType* epiPerphsPtr ///< Pointer to EPI peripheral pointers
)
{
int32_t returnVal = -1;
if (epiPerphsPtr)
{
AssignAddrToPrt(((void**)(&epiPerphsPtr->tempSensorDevicePtr)), ((uint32_t)(ON_BOARD_TEMP_SENSOR_ADDR)));
returnVal = 1;
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
This function generates a pseudo-random number within the specified range.
*/
static int32_t GenterateRandInRange
(
uint32_t min, ///< The minimum value for the range
uint32_t max, ///< The maximum value for the range
uint32_t* randNumb ///< The random number is passed by reference
)
{
int32_t returnVal = -1;
if ((NULL != randNumb) && (min < max))
{
(*randNumb) = rand() % (max - min + 1) + min;
returnVal = 1;
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Assigns peripheral structure pointers to peripheral base addresses.
*/
static int32_t SetMemoryTestVals
(
EpiMemoryTestType* memTstPtr ///< Pointer to memory test elements
)
{
int32_t returnVal = -1;
uint32_t i = 0;
uint32_t randNumb = 0;
if (memTstPtr)
{
for (i = 0; i < MEM_TEST_ARRAY_SIZE; i++)
{
returnVal = GenterateRandInRange(0x00, 0xFF, &randNumb);
if (0 < returnVal)
{
memTstPtr->testArray[i].origVal = ((uint8_t)(randNumb));
memTstPtr->testArray[i].invertVal = ~(memTstPtr->testArray[i].origVal);
}
}
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Writes values to the test addresses.
*/
int32_t WriteToAddresses
(
uint32_t baseAddr, ///< Current base address
EpiMemoryTestType* memTstPtr ///< Pointer to memory test elements
)
{
int32_t returnVal = -1;
uint8_t* conductor = NULL;
if (memTstPtr)
{
returnVal = AssignAddrToPrt(((void**)(&conductor)),baseAddr);
if (0 < returnVal)
{
conductor[0] = memTstPtr->testArray[0].origVal;
conductor[1] = memTstPtr->testArray[1].origVal;
}
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Reads values from the test addresses.
*/
int32_t ReadFromAddresses
(
uint32_t baseAddr, ///< Current base address
uint8_t* value1, ///< First value read by reference
uint8_t* value2 ///< Second value read by reference
)
{
int32_t returnVal = -1;
uint8_t* conductor = NULL;
if ((NULL != value1) && (NULL != value2))
{
returnVal = AssignAddrToPrt(((void**)(&conductor)),baseAddr);
if (0 < returnVal)
{
(*value1) = conductor[0];
(*value2) = conductor[1];
returnVal = 1;
}
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that there is a logical inversion
* Negative value means that there was no logical inversion, or an error
Tests for a logical inversion amongst values.
*/
int32_t TestInversion
(
EpiMemoryTestType* memTstPtr, ///< Pointer to memory test elements
uint8_t value1, ///< First comparison value
uint8_t value2 ///< Second comparison value
)
{
int32_t returnVal = -1;
bool inversion = false;
if (memTstPtr)
{
inversion = ((memTstPtr->testArray[0].invertVal) == (value1));
if (inversion)
{
inversion = ((memTstPtr->testArray[1].invertVal) == (value2));
returnVal = 1;
}
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t
* Positive value means that execution was valid
* Negative value means that execution was invalid
Reads values from the test addresses and tests to see if these are inversions
of the original values.
*/
int32_t ReadAndTestFromAddresses
(
uint32_t baseAddr, ///< Current base address
EpiMemoryTestType* memTstPtr ///< Pointer to memory test elements
)
{
int32_t returnVal = -1;
uint8_t value1 = 0;
uint8_t value2 = 0;
if (memTstPtr)
{
returnVal = ReadFromAddresses(baseAddr, &value1, &value2);
if (0 < returnVal)
{
returnVal = TestInversion(memTstPtr,value1, value2);
}
}
return returnVal;
}
// ============================================================================
// Public Functions
// ============================================================================
//=============================================================================
/**
@return
- int32_t: positive value means success; negative value means error; 0 is invalid
Initializes the EPI interface test.
*/
int32_t InitEpiTest(void)
{
int32_t returnVal = -1;
returnVal = ClearModVars(&epiTestSys);
if (0 < returnVal)
{
returnVal = InitEpi();
if (0 < returnVal)
{
//returnVal = SetPerphPointer(&epiTestSys.epiPerphPtrs);
epiTestSys.epiTestStatus = epi_test_memory;
}
}
return returnVal;
}
//=============================================================================
/**
@return
- int32_t: positive value means success; negative value means error; 0 is invalid
Executes the EPI interface test;
*/
int32_t ExecuteEpiTest(void)
{
int32_t returnVal = -1;
uint8_t i = 0;
//volatile uint8_t temp = 0;
volatile TempCntrlReg0UseType temp;
uint32_t currentAddress = EPI_PERIPH_ADDR;
uint32_t offset = 0;
do
{
switch (epiTestSys.epiTestStatus)
{
case epi_test_init:
{
//epiTestSys.epiPerphPtrs.tempSensorDevicePtr->tempCntrlReg0.bits.enable = 0;
temp.byte = i;
epiTestSys.epiPerphPtrs.tempSensorDevicePtr->tempCntrlReg0.byte = i;
temp.byte = epiTestSys.epiPerphPtrs.tempSensorDevicePtr->tempCntrlReg0.byte;
//epiTestSys.epiPerphPtrs.tempSensorDevicePtr->tempCntrlReg1.byte = i+1;
i++;
}
break;
case epi_test_memory:
{
returnVal = SetMemoryTestVals(&epiTestSys.epiMemoryTest);
if (0 < returnVal)
{
returnVal = WriteToAddresses(currentAddress, &epiTestSys.epiMemoryTest);
if (0 < returnVal)
{
returnVal = ReadAndTestFromAddresses(currentAddress, &epiTestSys.epiMemoryTest);
returnVal = 1;
if (0 < returnVal)
{
offset += 2;
if ( offset >= MEMORY_TEST_TOTAL_REG)
{
offset = 0;
//Test complete if all valid
}
currentAddress += offset;
}
}
}
if (0 > returnVal)
{
epiTestSys.epiTestStatus = epi_test_error;
}
}
break;
case epi_test_config:
{
}
break;
case epi_test_read_temp:
{
}
break;
case epi_test_error:
{
}
break;
default:
{
}
break;
}
}while (epi_test_finished != epiTestSys.epiTestStatus);
returnVal = ((int32_t)(epiTestSys.epiTestStatus));
return returnVal;
}
