Hi,
What should the HalCoGen settings be for being able to access the ADRAM connected to EMIF on the TI Hercules RM48L952ZWT Rev E board? (i.e., under EMIF General, EMIF SDRAM, EMIF ASYNC1, 2, 3). Thank you.
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi Thank you. In your spreadsheet, where are these values configured in HalCoGen (I did not see fields for them):
EMIF CLK Freq 60 MHz
EMIF CLK tc 16.66666667 ns
T_RFC (Trfc/tc)-1 3
T_RP (Trp/tc)-1 1
T_RCD (Trcd/tc)-1 1
T_WR (Twr/tc)-1 1
T_RAS (Tras/tc)-1 2
T_RC (Trc/tc)-1 3
T_RRD (Trrd/tc)-1 0
T_XS (Txsr/tc)-1 4
In HalCoGen in the EMIFSDRAM tabs, what about the fields:
Refresh period, refresh cycles, CAS latency, Banks and Page size? The SDRAM part is what came on the TI RM48L952 Rev E Hercules board. I think this is the datasheet for what comes on the I board? : 1563.IS42S16400F-7BL.pdf
Hi Tammy,
The EMIF clock is configured through the clock module, highlighted below
Note I put two arrows - you can see VCLK3 will also affect EMAC and USB when you reduce this frequency to 55MHz or less...
But this is the internal bus clock interface. The clock that controls the USB bus (external) timings and that needs to be 48MHz is VCLKA3.
So don't be (too) concerned about this unless you find it affects your USB bus bandwidth - which I doubt it will..
Reason I point this out is that it alarmed me a bit to see the EMIF and USB tied together in the clock diagram, because I know the USB module needs a 48MHz clock. But the I realized that this is the VCLKA3 clock for the USB core, the clock that is shared with EMIF is for the internal USB register interface. So the only thing that might happen is you may see the USB slow down, although I doubt that you wil because a 50+MHz 32-bit wide internal bus for a 12MBit/s external serial data link still gives a healthy ratio.
The spreadsheet takes the 'ns' parameter values that are pulled from the SDRAM datasheet and calculates the bit field values from them for the EMIF control registers. It's basically a matter of dividng the 'ns' requirement of the DRAM by the EMIF frequency, and then adjusting (usually subtract 1) to match the register bit field format.
HalCoGen also takes the 'ns' parameter values from the SDRAM datasheet and computes the bit field values. So the spreadsheet is something you can use to check your inputs to HalCoGen against; but the SDRAM datasheet is the golden reference.
Most of the other non-'ns' parameters are on the first page of the SDRAM datasheet.
- 4096 refresh cycles every 64 ms (Com, Ind, A1
grade) or 16ms (A2 grade)
-Programmable CAS latency (2, 3 clocks)
(At 55MHz - you can go with only 2 cycles of CAS latency)
- Configuration 1M x 16 x 4 banks
(i.e. 4 banks)
- Column Addresses A0-A7
(i.e. pagesize_256 .. this is 'obscure' in halcogen - but if you look at the TRM description of PAGESIZE in the SDCR register, you can see this means that the memory has 8 column address lines.... )
Hi Thank you. On the Hercules board we have it is an IS42S16400F07 COM type of SDRAM. We have configured as you described above using HalCoGen 4.03.00 HalCoGen Project uploaded here: 2112.HalCoGen.zip
And we tried both basic TI emif SDRAM 32 and 16 BIT tests, and we cannot write to the SDRAM at all. Should we upgrade to 4.04.00 HalCoGen and see if there is an issue with the emif drivers. Or is there something about the TI Hercules board we missed i.e., under EMIF or R4-MPU-PMU tabs? Thank you again.
(EMIF SDRAM Test Code we got from TI site)
/**
* @defgroup EMIF SDRAM BSP Tests
* @{
* @file emif_sdram_BSPTests.c
* @brief BSP Integration tests using EMIF/SDRAM device drivers
*/
/* Include Files */
#include "emif.h"
#include "sys_mpu.h"
#include "pinmux.h"
#include "app_serial.h"
/* Definitions and Globals*/
#define EMIF 0xFCFFE800
#define NUM_EMIF_ASYC_CS 3 /*No of Chip Select*/
#define EMIF_CS0_ADDRMAP_START 0x80000000
#define EMIF_CS0_ADDRMAP_END 0x87FFFFFC
#define EMIF_CS2_ADDRMAP_START 0x60000000
#define EMIF_CS2_ADDRMAP_END 0x63FFFFFC
#define EMIF_CS3_ADDRMAP_START 0x64000000
#define EMIF_CS3_ADDRMAP_END 0x67FFFFFC
#define EMIF_CS4_ADDRMAP_START 0x68000000
#define EMIF_CS4_ADDRMAP_END 0x6BFFFFFC
#define NO_OF_WORDS (0x00800000 / 4) // defines the size of the external RAM = 8MB
/* External Functions */
extern void EMIF_ASYNC_MEM_CONFIG ( unsigned int ASYNC_Mem_Config,
unsigned int ASYNC_MEM_READ_CONF,
unsigned int ASYNC_MEM_WRITE_CONF,
unsigned int ASYNC_MEM_TURN_ARND_CYC,
unsigned int Chip_Sel);
extern void FILL_EMIF_MEMORY_32BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern void FILL_EMIF_MEMORY_16BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern void FILL_EMIF_MEMORY_8BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int CHECK_EMIF_MEMORY_32BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int CHECK_EMIF_MEMORY_16BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int CHECK_EMIF_MEMORY_8BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern void FILL_EMIF_MEMORY_32BIT_ADR ( unsigned int Start_Address,
unsigned int No_Of_Words);
extern unsigned int CHECK_EMIF_MEMORY_32BIT_ADR ( unsigned int Start_Address,
unsigned int No_Of_Words);
extern void FILL_EMIF_MEMORY_BACKWARD ( unsigned int *Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern void ENDLESS_EMIF_MEMORY_READ_16BIT ( unsigned int Start_Address );
extern unsigned int TEST_EMIF_MEMORY_32BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int TEST_EMIF_MEMORY_16BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int TEST_EMIF_MEMORY_8BIT ( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern);
extern unsigned int TEST_EMIF_MEMORY_ADR ( unsigned int Start_Address,
unsigned int No_Of_Words);
/* Local Functions Functions */
/** @fn void EMIF_BSPTest(void)
* @brief EMIF BSP test, sdram starts at 0x8000 0000
*/
void EMIF_BSPTest(void)
{
unsigned int i=0;
unsigned short *SRAM_ptr = ( unsigned short *)0x80000000;
i = TEST_EMIF_MEMORY_16BIT(EMIF_CS0_ADDRMAP_START, NO_OF_WORDS, 0x56785678);
if (i == 0)
{
App_SerPrintf( "SDRAM Test ......................................... PASS! \r\n");
}
else
{
App_SerPrintf( "SDRAM Test ......................................... FAIL! \r\n \r\n");
}
// if (i == 0) {
// i = TEST_EMIF_MEMORY_16BIT(EMIF_CS0_ADDRMAP_START, NO_OF_WORDS, 0x12345678);
// }
//if (i == 0) {
// i = TEST_EMIF_MEMORY_16BIT(EMIF_CS2_ADDRMAP_START, NO_OF_WORDS, 0x55AA66BB);
//}
}
void FILL_EMIF_MEMORY_8BIT(unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned char *Addr = (unsigned char *) Start_Address;
while(No_Of_Words > 0)
{
#if defined (_TMS470_LITTLE) || defined(__little_endian__)
*Addr++ = (Pattern & 0x000000FF);
*Addr++ = (Pattern & 0x0000FF00)>>8;
*Addr++ = (Pattern & 0x00FF0000)>>16;
*Addr++ = (Pattern & 0xFF000000)>>24;
#else
*Addr++ = (Pattern & 0xFF000000)>>24;
*Addr++ = (Pattern & 0x00FF0000)>>16;
*Addr++ = (Pattern & 0x0000FF00)>>8;
*Addr++ = (Pattern & 0x000000FF);
#endif
No_Of_Words--;
}
}
void FILL_EMIF_MEMORY_16BIT(unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned short *Addr = (unsigned short *) Start_Address;
while(No_Of_Words > 0)
{
#if defined (_TMS470_LITTLE) || defined(__little_endian__)
*Addr++ = (Pattern & 0x0000FFFF);
*Addr++ = (Pattern & 0xFFFF0000)>>16;
#else
*Addr++ = (Pattern & 0xFFFF0000)>>16;
*Addr++ = (Pattern & 0x0000FFFF);
#endif
No_Of_Words--;
}
}
void FILL_EMIF_MEMORY_32BIT(unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int *Addr = (unsigned int *) Start_Address;
while(No_Of_Words > 0)
{
*Addr++ = Pattern;
No_Of_Words--;
}
}
void FILL_EMIF_MEMORY_32BIT_ADR(unsigned int Start_Address,
unsigned int No_Of_Words)
{
unsigned int *Addr = (unsigned int *) Start_Address;
while(No_Of_Words > 0)
{
*Addr++ = Start_Address++;
No_Of_Words--;
}
}
void FILL_EMIF_MEMORY_BACKWARD(unsigned int *Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
while(No_Of_Words > 0)
{
*Start_Address-- = Pattern;
No_Of_Words--;
}
}
unsigned int CHECK_EMIF_MEMORY_8BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int ReadPattern;
unsigned char *Addr = (unsigned char *) Start_Address;
while(No_Of_Words > 0)
{
#if defined (_TMS470_LITTLE) || defined(__little_endian__)
ReadPattern = *Addr++ << 0;
ReadPattern += *Addr++ << 8;
ReadPattern += *Addr++ << 16;
ReadPattern += *Addr++ << 24;
#else
ReadPattern = *Addr++ << 24;
ReadPattern += *Addr++ << 16;
ReadPattern += *Addr++ << 8;
ReadPattern += *Addr++;
#endif
if (ReadPattern != Pattern)
{
return ((unsigned int)Addr);
}
No_Of_Words--;
}
return (0);
}
unsigned int CHECK_EMIF_MEMORY_16BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int ReadPattern;
unsigned short *Addr = (unsigned short *) Start_Address;
while(No_Of_Words > 0)
{
#if defined (_TMS470_LITTLE) || defined(__little_endian__)
ReadPattern = *Addr++;
ReadPattern += *Addr++ << 16;
#else
ReadPattern = *Addr++ << 16;
ReadPattern += *Addr++;
#endif
if (ReadPattern != Pattern)
{
return ((unsigned int)Addr);
}
No_Of_Words--;
}
return (0);
}
unsigned int CHECK_EMIF_MEMORY_32BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int ReadPattern;
unsigned int *Addr = (unsigned int *) Start_Address;
while(No_Of_Words > 0)
{
ReadPattern = *Addr++;
if (ReadPattern != Pattern)
{
return ((unsigned int)Addr);
}
No_Of_Words--;
}
return (0);
}
unsigned int CHECK_EMIF_MEMORY_32BIT_ADR( unsigned int Start_Address,
unsigned int No_Of_Words)
{
unsigned int ReadPattern;
unsigned int *Addr = (unsigned int *) Start_Address;
while(No_Of_Words > 0)
{
ReadPattern = *Addr++;
if (ReadPattern != Start_Address)
{
return (Start_Address);
}
No_Of_Words--;
Start_Address++;
}
return (0);
}
void Ext_Async_Mem_Write(unsigned int* Ext_Mem_Address_Ptr,
unsigned int* Data_To_Write_Ptr,
unsigned int No_Of_32BitData)
{
while(No_Of_32BitData > 0)
{
*Ext_Mem_Address_Ptr++ = *Data_To_Write_Ptr++;
No_Of_32BitData--;
}
}
unsigned int Calc_CheckSum(unsigned int *Data_To_Write_Ptr,unsigned int No_Of_32BitData)
{
unsigned int CheckSum;
CheckSum = 0;
while(No_Of_32BitData > 0)
{
CheckSum = CheckSum + *Data_To_Write_Ptr++;
No_Of_32BitData--;
}
return CheckSum;
}
void ENDLESS_EMIF_MEMORY_READ_16BIT( unsigned int Start_Address)
{
unsigned short volatile ReadPattern;
unsigned short *Addr = (unsigned short *) Start_Address;
while(1)
{
ReadPattern = *Addr;
}
}
unsigned int TEST_EMIF_MEMORY_32BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int error;
// Fill the EMIF Memory with data Patterns using 32 bit accesses
FILL_EMIF_MEMORY_32BIT(Start_Address, No_Of_Words,Pattern);
// check the EMIF Memory Patterns using 32 bit accesses
error = CHECK_EMIF_MEMORY_32BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 16 bit accesses
error = CHECK_EMIF_MEMORY_16BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 8 bit accesses
error = CHECK_EMIF_MEMORY_8BIT (Start_Address, No_Of_Words,Pattern);
return (error);
}
unsigned int TEST_EMIF_MEMORY_16BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int error;
// Fill the EMIF Memory with data Patterns using 16 bit accesses
FILL_EMIF_MEMORY_16BIT(Start_Address, No_Of_Words,Pattern);
// Check the EMIF Memory Patterns using 32 bit accesses
error = CHECK_EMIF_MEMORY_32BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 16 bit accesses
error = CHECK_EMIF_MEMORY_16BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 8 bit accesses
error = CHECK_EMIF_MEMORY_8BIT (Start_Address, No_Of_Words,Pattern);
return (error);
}
unsigned int TEST_EMIF_MEMORY_8BIT( unsigned int Start_Address,
unsigned int No_Of_Words,
unsigned int Pattern)
{
unsigned int error;
// Fill the EMIF Memory with data Patterns using 8 bit accesses
FILL_EMIF_MEMORY_8BIT(Start_Address, No_Of_Words,Pattern);
// Check the EMIF Memory Patterns using 32 bit accesses
error = CHECK_EMIF_MEMORY_32BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 16 bit accesses
error = CHECK_EMIF_MEMORY_16BIT (Start_Address, No_Of_Words,Pattern);
if (error) return (error);
// Check the EMIF Memory Patterns using 8 bit accesses
error = CHECK_EMIF_MEMORY_8BIT (Start_Address, No_Of_Words,Pattern);
return (error);
}
unsigned int TEST_EMIF_MEMORY_ADR ( unsigned int Start_Address,
unsigned int No_Of_Words)
{
unsigned int error;
// Fill the EMIF Memory with an incremented number using 32 bit accesses
FILL_EMIF_MEMORY_32BIT_ADR(Start_Address, No_Of_Words);
// Check the EMIF Memory against an incremented number using 32 bit accesses
error = CHECK_EMIF_MEMORY_32BIT_ADR (Start_Address, No_Of_Words);
return (error);
}
Hi. Thank you. Yes it is in the Micrium bsp.c file -
...
/* Biolase BSP initialization */
muxInit(); /* initialize muliplexing configuration */
/* Initialize memory protection unit.
* Region configurations are selected using MPU Tab in HALCoGen.
* MPU is enabled in mpuInit function if "Enable MPU" in GUI is selected */
_mpuInit_();
_mpuEnable_();
emif_SDRAMInit(); // initialize the SDRAM over EMIF
....
Could the order we initialize the drivers above be a problem? Should anyting else be initialized before we initialize emif sdram? do you want me to move it back into the sys_main.c and run the test from there and see if we get a different result? Could within the context of the OS task, access to this region is blocked?
Hi Anthony. Thank you. I had a breakpoint in CCS as you suggested and after executing emif_SDRAMInit(). WHen I tried to fill some data into the emif SDRAM region, came back with an error. See screen shots below for the Fill and the Error.
Just checked the TI board, the sdram off jumper is not populated, so that looks Ok. So it looks like either there is something off with the board, or with the initialization code we generated with halcogen. Do you have a Rev E version of the RM48L952ZWT board to do a quick check that HalCoGen is producing the same result for you as us, or if we need to go with a different version of HalCoGen code? What about the sys_link.cmd file autogenerated from HalCoGen that we modified manually. Do you think this looks Ok also? Or should we remove the edits that we made?
MEMORY
{
VECTORS (X) : origin=0x00000000 length=0x00000020
FLASH0 (RX) : origin=0x00000020 length=0x0017FFE0
FLASH1 (RX) : origin=0x00180000 length=0x00180000
STACKS (RW) : origin=0x08000000 length=0x00000900
RAM (RW) : origin=0x08000900 length=0x0003f700
/* USER CODE BEGIN (2) */
SDRAM (RW) : origin=0x80000000 length=0x00800000
/* USER CODE END */
}
/* USER CODE BEGIN (3) */
--heap_size 0x7F0000
/* USER CODE END */
/*----------------------------------------------------------------------------*/
/* Section Configuration */
SECTIONS
{
.intvecs : {} > VECTORS
.text : {} > FLASH0 | FLASH1
.const : {} > FLASH0 | FLASH1
.cinit : {} > FLASH0 | FLASH1
.pinit : {} > FLASH0 | FLASH1
.bss : {} > RAM
.data : {} > RAM
.sysmem : {} > RAM
FEE_TEXT_SECTION : {} > FLASH0 | FLASH1
FEE_CONST_SECTION : {} > FLASH0 | FLASH1
FEE_DATA_SECTION : {} > RAM
/* USER CODE BEGIN (4) */
.sysmem : {} > SDRAM
/* USER CODE END */
}
/* USER CODE BEGIN (5) */
/* USER CODE END */
Thank you again.
Hi Tammy,
I need to read up on what .sysmem get's used for - but it looks like it's the only section you are putting in SDRAM and I'm not even sure the priority of this versus the prior statement putting .sysmem in on chip RAM. Obviously, anything that is going to be stored in SDRAM will need to be copied at runtime or uninitialized.
But these things should not prevent you from accessing SDRAM through the debugger.
If you actually open a memory window to inspect the SDRAM, (rather than fill) what does the data that is read back look like? It's hard to say what's going on from the generic 'mismatch' errror but if we see the data values then the pattern there might give some insight. Of course it might not... so at some point we might need to get a binary from you and run it here.
Hi Anthony. Thank you. Should I remove what we added to sys_link.cmd? We thought from onother TI blog on RM48 SDRAM it was required. I sent you our HalCoGen code already, do you need me to upload this again? Here is the binary (.out in zip file): 2072.BiolasePFB_ProductionBoard.zip
And here is the memory window screen shot after the debugger executes emif_SDRAMInit():
Hi Anthony. There was something weird now we saw. When we run the emif test (test code above) we are putting 56785678 in SDRAM. When we run with CCS and debugging session. The region stays as 0, and we get a fail back, memory browser shows 00000000 and if we keep going SDRAM is never updated. But when we stop the debugger, and do a restart (CTRL SHIFT 5) and hit go, then in the memory browser, the test data is in this region. Why did the test data not show up in the emif SDRAM until after we restarted the debug session?
That is what the issue was. PINMMR29[8] needs to be 0 and the code sets it to '1' (leaves it that way actually) unless you check the box.
So the label is wrong in HalCoGen. Apologies for that - I'll file a ticket on the issue.
BTW - I notice that mux init is being called twice, once before main and again in the BSP init. You can probably remove the 2nd function call.
EDIT: ticket # is SDOCM00115693