390 lines
9.5 KiB
C
390 lines
9.5 KiB
C
/*
|
|
* emif_init.c
|
|
*
|
|
* Created on: 20 íîÿá. 2023 ã.
|
|
* Author: seklyuts
|
|
*/
|
|
|
|
#include "f28x_project.h"
|
|
|
|
#define TEST_PASS 0xABCDABCD
|
|
#define TEST_FAIL 0xDEADDEAD
|
|
#define ASRAM_CS2_START_ADDR 0x100000
|
|
#define ASRAM_CS2_SIZE 0x100000
|
|
#define STEP 0x100
|
|
#define EMIF1 0
|
|
#define EMIF2 1
|
|
#define MEM_D_WIDTH 1 // 16Bit Memory Interface
|
|
#define TURN_AROUND_TIME 0 // Turn Around time of 2 Emif Clock
|
|
#define RD_SETUP_TIME 0 // Read Setup time of 1 Emif Clock
|
|
#define RD_STROBE_TIME 3 // Read Strobe time of 4 Emif Clock
|
|
#define RD_HOLD_TIME 0 // Read Hold time of 1 Emif Clock
|
|
#define WR_SETUP_TIME 0 // Write Hold time of 1 Emif Clock
|
|
#define WR_STROBE_TIME 0 // Write Setup time of 1 Emif Clock
|
|
#define WR_HOLD_TIME 0 // Write Hold time of 1 Emif Clock
|
|
#define EXTEND_WAIT 0 // Disable Extended Wait
|
|
#define STROBE_SEL 0 // Disable Strobe Mode.
|
|
#define WAIT_POLAR_INV 0
|
|
#define WAIT_COUNT 0
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
Uint16 ErrCount = 0;
|
|
Uint32 TEST_STATUS;
|
|
int i;
|
|
|
|
|
|
//
|
|
// Function Prototypes
|
|
//
|
|
extern void setup_emif1_pinmux_async_16bit(Uint16);
|
|
|
|
//
|
|
// mem_read_write - This function performs simple read/write word accesses
|
|
// to memory.
|
|
//
|
|
uint16_t Arr1[256], Arr2[256];
|
|
|
|
char
|
|
mem_read_write(Uint32 start_addr, Uint32 mem_size, Uint16 step)
|
|
{
|
|
unsigned long mem_rds;
|
|
unsigned long mem_wds;
|
|
long *XMEM_ps;
|
|
Uint32 i;
|
|
|
|
//
|
|
//Write data
|
|
//
|
|
XMEM_ps = (long *)start_addr;
|
|
|
|
//
|
|
//Fill memory
|
|
//
|
|
mem_wds = 0x01234567;
|
|
for (i=0; i < mem_size; i+=step)
|
|
{
|
|
*XMEM_ps = mem_wds;
|
|
if(i < 256) Arr1[i] = mem_wds & 0x1FF;
|
|
XMEM_ps += step;
|
|
mem_wds += 0x11111111;
|
|
}
|
|
|
|
//
|
|
//Verify memory
|
|
//
|
|
mem_wds = 0x01234567;
|
|
XMEM_ps = (long *)start_addr;
|
|
for (i=0; i < mem_size; i+=step)
|
|
{
|
|
mem_rds = *XMEM_ps;
|
|
if( (mem_rds & 0x1FF) != (mem_wds & 0x1FF) )
|
|
{
|
|
if(i < 256) Arr2[i] = mem_rds & 0x1FF;
|
|
}
|
|
XMEM_ps+= step;
|
|
mem_wds += 0x11111111;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// mem_data_walk - This function performs a walking 0 & 1 on data lines for
|
|
// SRAM RD & WR
|
|
//
|
|
char
|
|
mem_data_walk(Uint32 start_addr, Uint32 mem_size)
|
|
{
|
|
unsigned long sram_rd;
|
|
unsigned long sram_wd;
|
|
unsigned long i;
|
|
int k;
|
|
int m;
|
|
unsigned long *XM_p;
|
|
unsigned long *XMEM_p;
|
|
|
|
XM_p = (unsigned long *)start_addr;
|
|
|
|
for (i=0; i < mem_size; i=i+64)
|
|
{
|
|
for (m=0; m < 2; m++)
|
|
{
|
|
//
|
|
//Write loop
|
|
//
|
|
XMEM_p = XM_p;
|
|
sram_wd = 0x01;
|
|
for (k=0; k < 32; k++)
|
|
{
|
|
if(m==0)
|
|
{
|
|
*XMEM_p++ = sram_wd;
|
|
}
|
|
else
|
|
{
|
|
*XMEM_p++ = ~sram_wd;
|
|
}
|
|
sram_wd = sram_wd<<1;
|
|
}
|
|
|
|
//
|
|
//Read loop
|
|
//
|
|
XMEM_p = XM_p;
|
|
sram_wd = 0x01;
|
|
for (k=0; k < 32; k++)
|
|
{
|
|
sram_rd = *XMEM_p;
|
|
if(m==1)
|
|
{
|
|
sram_rd = ~sram_rd;
|
|
}
|
|
if(sram_rd != sram_wd)
|
|
{
|
|
return(1);
|
|
}
|
|
XMEM_p++;
|
|
sram_wd=sram_wd<<1;
|
|
}
|
|
}
|
|
XM_p = XMEM_p;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// mem_addr_walk - This function performs a toggle on each address bit.
|
|
//
|
|
char
|
|
mem_addr_walk(Uint32 start_addr, Uint32 addr_size)
|
|
{
|
|
unsigned long sram_rd;
|
|
unsigned long sram_wd;
|
|
unsigned int k;
|
|
unsigned long xshift;
|
|
unsigned long *XM_p;
|
|
unsigned long *XMEM_p;
|
|
|
|
XM_p = (unsigned long *)start_addr;
|
|
|
|
//
|
|
//Write loop
|
|
//
|
|
xshift = 0x00000001;
|
|
sram_wd = 0x00;
|
|
for (k=0; k < addr_size; k++)
|
|
{
|
|
XMEM_p = (unsigned long *)(start_addr + xshift);
|
|
*XMEM_p = sram_wd++;
|
|
xshift = xshift<<1;
|
|
}
|
|
|
|
//
|
|
//Read loop
|
|
//
|
|
XMEM_p = XM_p;
|
|
xshift = 0x00000001;
|
|
sram_wd = 0x00;
|
|
for (k=0; k < addr_size; k++)
|
|
{
|
|
XMEM_p = (unsigned long *)(start_addr + xshift);
|
|
sram_rd = *XMEM_p;
|
|
if(sram_rd != sram_wd)
|
|
{
|
|
return(1);
|
|
}
|
|
|
|
xshift = xshift<<1;
|
|
sram_wd++;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
//
|
|
// mem_data_size - This function performs different data type
|
|
// (HALFWORD/WORD) access.
|
|
//
|
|
char
|
|
mem_data_size(Uint32 start_addr, Uint32 size_to_check)
|
|
{
|
|
unsigned short mem_rds;
|
|
unsigned long mem_rdl;
|
|
unsigned short mem_wds;
|
|
unsigned long mem_wdl;
|
|
int i;
|
|
|
|
short *XMEM_ps;
|
|
long *XMEM_pl;
|
|
|
|
//
|
|
//Write data short
|
|
//
|
|
XMEM_ps = (short *)start_addr;
|
|
mem_wds = 0x0605;
|
|
|
|
for (i=0; i < 2; i++)
|
|
{
|
|
*XMEM_ps++ = mem_wds;
|
|
mem_wds += 0x0202;
|
|
}
|
|
|
|
//
|
|
//Write data long
|
|
//
|
|
XMEM_pl = (long *)XMEM_ps;
|
|
mem_wdl = 0x0C0B0A09;
|
|
for (i=0; i < 2; i++)
|
|
{
|
|
*XMEM_pl++ = mem_wdl;
|
|
mem_wdl += 0x04040404;
|
|
}
|
|
|
|
//
|
|
//Read data short
|
|
//
|
|
XMEM_ps = (short *)start_addr;
|
|
mem_wds = 0x0605;
|
|
for (i=0; i < 6; i++)
|
|
{
|
|
mem_rds = *XMEM_ps;
|
|
if( mem_rds != mem_wds)
|
|
{
|
|
return(1);
|
|
}
|
|
XMEM_ps++;
|
|
mem_wds += 0x0202;
|
|
}
|
|
|
|
//
|
|
//Read data long
|
|
//
|
|
XMEM_pl = (long *)start_addr;
|
|
mem_wdl = 0x08070605;
|
|
for (i=0; i < 3; i++)
|
|
{
|
|
mem_rdl = *XMEM_pl;
|
|
if(mem_rdl != mem_wdl)
|
|
{
|
|
return(1);
|
|
}
|
|
XMEM_pl++;
|
|
mem_wdl += 0x04040404;
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
void emif_init(void)
|
|
{
|
|
char ErrCount_local;
|
|
//
|
|
//Configure to run EMIF1 on full Rate (EMIF1CLK = CPU1SYSCLK)
|
|
//
|
|
EALLOW;
|
|
ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 0x0;
|
|
EDIS;
|
|
|
|
EALLOW;
|
|
//
|
|
// Grab EMIF1 For CPU1
|
|
//
|
|
Emif1ConfigRegs.EMIF1MSEL.all = 0x93A5CE71;
|
|
if(Emif1ConfigRegs.EMIF1MSEL.all != 0x1)
|
|
{
|
|
ErrCount++;
|
|
}
|
|
|
|
//
|
|
//Disable Access Protection (CPU_FETCH/CPU_WR/DMA_WR)
|
|
//
|
|
Emif1ConfigRegs.EMIF1ACCPROT0.all = 0x0;
|
|
if(Emif1ConfigRegs.EMIF1ACCPROT0.all != 0x0)
|
|
{
|
|
ErrCount++;
|
|
}
|
|
|
|
//
|
|
// Commit the configuration related to protection. Till this bit remains set
|
|
// content of EMIF1ACCPROT0 register can't be changed.
|
|
//
|
|
Emif1ConfigRegs.EMIF1COMMIT.all = 0x1;
|
|
if(Emif1ConfigRegs.EMIF1COMMIT.all != 0x1)
|
|
{
|
|
ErrCount++;
|
|
}
|
|
|
|
//
|
|
// Lock the configuration so that EMIF1COMMIT register can't be
|
|
// changed any more.
|
|
//
|
|
Emif1ConfigRegs.EMIF1LOCK.all = 0x1;
|
|
if(Emif1ConfigRegs.EMIF1LOCK.all != 1)
|
|
{
|
|
ErrCount++;
|
|
}
|
|
|
|
EDIS;
|
|
|
|
//
|
|
//Configure GPIO pins for EMIF1
|
|
//
|
|
setup_emif1_pinmux_async_16bit(0);
|
|
|
|
Emif1Regs.ASYNC_WCCR.bit.WP0 = 0;
|
|
|
|
//
|
|
//Configure the access timing for CS3 space
|
|
//
|
|
Emif1Regs.ASYNC_CS3_CR.all = (EMIF_ASYNC_ASIZE_16 | // 16Bit Memory
|
|
// Interface
|
|
EMIF_ASYNC_TA_1 | // Turn Around time
|
|
// of 2 Emif Clock
|
|
EMIF_ASYNC_RHOLD_1 | // Read Hold time
|
|
// of 1 Emif Clock
|
|
EMIF_ASYNC_RSTROBE_4 | // Read Strobe time
|
|
// of 4 Emif Clock
|
|
EMIF_ASYNC_RSETUP_1 | // Read Setup time
|
|
// of 1 Emif Clock
|
|
EMIF_ASYNC_WHOLD_8 | // Write Hold time
|
|
// of 1 Emif Clock
|
|
EMIF_ASYNC_WSTROBE_32 | // Write Strobe time
|
|
// of 1 Emif Clock
|
|
EMIF_ASYNC_WSETUP_1 | // Write Setup time
|
|
// of 1 Emif Clock
|
|
EMIF_ASYNC_EW_ENABLE | // Extended Wait
|
|
// Disable.
|
|
EMIF_ASYNC_SS_ENABLE // Strobe Select Mode
|
|
// Disable.
|
|
);
|
|
|
|
//
|
|
//Check basic RD/WR access to CS2 space
|
|
//
|
|
ErrCount_local = mem_read_write(ASRAM_CS2_START_ADDR, ASRAM_CS2_SIZE, STEP);
|
|
ErrCount = ErrCount + ErrCount_local;
|
|
|
|
//
|
|
//Address walk checks (Tested for Memory with address width of 16bit)
|
|
//
|
|
// ErrCount_local = mem_addr_walk(ASRAM_CS2_START_ADDR, 16);
|
|
// ErrCount = ErrCount + ErrCount_local;
|
|
|
|
//
|
|
//Data walk checks
|
|
//
|
|
// ErrCount_local = mem_data_walk(ASRAM_CS2_START_ADDR, ASRAM_CS2_SIZE);
|
|
// ErrCount = ErrCount + ErrCount_local;
|
|
|
|
//
|
|
//Data size checks
|
|
//
|
|
// ErrCount_local = mem_data_size(ASRAM_CS2_START_ADDR, 4);
|
|
// ErrCount = ErrCount + ErrCount_local;
|
|
|
|
if (ErrCount == 0x0)
|
|
{
|
|
TEST_STATUS = TEST_PASS;
|
|
}
|
|
}
|
|
|