Strange EBI behaviour. XOR bit 2 and 3

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi, im having a very weird bug with my external memory. Any help on this would be much appreciated.

I have gotten everything up and running, and ive done memory tests on the external memory without problems... except..

when i run my memory test, and bit 2 and 3 are XOR (01 or 10), i read 00 back on those bits. but 00 becomes 00, and 11 becomes 11.

This happens with every combination of that bit 2 and 3 pattern, and only for bit 2 and 3.

Heres the code im using to read and write:
This is successfull for any value where bit 2 and 3 isnt XOR.

Example values are 0x1E, 0x2D, 0x33, 0xCC, 0xD2, 0xE1 and 0xFF, where all work.

Write function:

   EBI_ADDR.FULL = (uint32_t) 0x00004000;
   do 
   {
	   for(uint8_t j=0; j<7 && EBI_ADDR.A2 < 0x08; j++)  
      {	               
			__far_mem_enter_ISR();
	      __far_mem_write(EBI_ADDR.FULL, testarray[j]);
	      __far_mem_exit_ISR();  	
   	   EBI_ADDR.FULL++;
      }
   } while (EBI_ADDR.A2 < 0x08);

And here is the read function:

	EBI_ADDR.FULL = (uint32_t) 0x00004000;
   do 
   {
	   for(uint8_t j=0; j<7 && EBI_ADDR.A2 < 0x08; j++)  
      {	   
         __far_mem_enter_ISR();
		   uint8_t mem_read_var = __far_mem_read(EBI_ADDR.FULL);
		   __far_mem_exit_ISR();		
		   
		   if (mem_read_var != testarray[j])	   
	      {
   	      SRAM_ERR++;
		 		  
         }
		   
   	   EBI_ADDR.FULL++;
      }
   } while (EBI_ADDR.A2 < 0x08);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What are the purpose of __far_mem_enter_ISR() and __far_mem_exit_ISR() and where is the code for them? And what about __far_mem_write() and __far_mem_read()? Where is EBI_ADDR declared? It's difficult to see what might be wrong when you don't provide the code that is actually doing the work.

Gamu The Killer Narwhal
Portland, OR, US
_________________
Atmel Studio 6.2
Windows 8.1 Pro
Xplained boards mostly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

GTK, thanks for taking the time to answer my post. The EBI_ADDR is defined globally, and is a simple uint32 value where ive provided access to each byte with a union/struct:

typedef struct EBI_MEM_struct
{	   
   union
   {
      uint32_t FULL;
      struct
      {
	      uint8_t A0;
	      uint8_t A1;
	      uint8_t A2;
      };
   };
} EBI_MEM_t;

EBI_MEM_t EBI_ADDR;

The __far_mem functions are from the Atmel EBI driver, and i havent made any changes to it. Heres the code for those:

#define __far_mem_read(addr)             \
        (__extension__({                 \
		uint32_t temp32 = (uint32_t)(addr); \
		uint8_t result;                    \
		asm volatile(                      \
			"in __tmp_reg__, % 2"     "\n\t" \
			"out % 2, % C1"            "\n\t" \
			"movw r30, % 1"           "\n\t" \
			"ld % 0, Z"               "\n\t" \
			"out % 2, __tmp_reg__"    "\n\t" \
			: "=r" (result)                 \
			: "r" (temp32),                 \
			  "I" (_SFR_IO_ADDR(RAMPZ))     \
			: "r30", "r31"                  \
		);                                 \
		result;                            \
	}))

#define __far_mem_write(addr, data)      \
        (__extension__({                 \
      uint32_t temp32 = (uint32_t)(addr); \
      asm volatile(                      \
         "in __tmp_reg__, % 1"     "\n\t" \
         "out % 1, % C0"            "\n\t" \
         "movw r30, % 0"           "\n\t" \
         "st Z, % 2"               "\n\t" \
         "out % 1, __tmp_reg__"           \
         :                               \
         : "r" (temp32),                 \
           "I" (_SFR_IO_ADDR(RAMPZ)),    \
           "r" ((uint8_t)data)           \
         : "r30", "r31"                  \
      );                                 \
   }))

#define __far_mem_enter_ISR()  uint8_t volatile saved_rampz = RAMPZ; \
                              RAMPZ = 0;

#define __far_mem_exit_ISR()   RAMPZ = saved_rampz;

I also made a "manual mode" code, where i control the IO lines directly, its a bit slower than the EBI, but produces the same results. I suppose that means the problem isnt within the EBI itself, but theres something else going on...

void RAM_TESTRUN()
{
	RAM_RESET();
	RAM_WRITE();
   RAM_READ();
      
   usart_write_hex((SRAM_ERR>>16) & 0xFF);
	usart_write_hex((SRAM_ERR>>8) & 0xFF);
   usart_write_hex(SRAM_ERR & 0xFF);
   delay_us(1000);
	// Report success or failure.
	if (SRAM_ERR == 0) 
	{
	   usart_write_line((char*) "\nSuccess\n");  //Usart.c
      while(true) 
	   {
		   // Breakpoint for success.
		   asm("nop");
		}
	}
	else
	{
	   usart_write_line((char*) "\nFailure\n");  //Usart.c
	   while(true) 
	   {
	      // Breakpoint for failure.
	      asm("nop");
	   }
	}	
}

void RAM_RESET()
{
	PORTH.OUTCLR = EBI_CS0; //active low
   PORTH.OUTSET = EBI_RE;  //active low
   PORTH.OUTSET = EBI_WE;  //write when low, read when high
   PORTJ.DIR = 0xFF;       //write 
	
   // Fill SRAM with data.	
	for (EBI_ADDR.FULL = 0x00000000; EBI_ADDR.A2 < 0x08; EBI_ADDR.FULL++)
	{
		PORTK.OUT = EBI_ADDR.A2;
      PORTH.OUTSET = EBI_ALE2;
      PORTH.OUTCLR = EBI_ALE2;
      PORTK.OUT = EBI_ADDR.A1;
      PORTH.OUTSET = EBI_ALE1;
      PORTH.OUTCLR = EBI_ALE1;
      PORTK.OUT = EBI_ADDR.A0;
		
		PORTJ.OUT = HD4_0;
		PORTH.OUTCLR = EBI_WE;  //write when low, read when high		
		delay_ns(40);
		PORTH.OUTSET = EBI_WE;  //write when low, read when high
	}

}

void RAM_WRITE()
{
	PORTH.OUTCLR = EBI_CS0; //active low
   PORTH.OUTSET = EBI_RE;  //active low
   PORTH.OUTSET = EBI_WE;  //write when low, read when high
   PORTJ.DIR = 0xFF;       //write 
   
	EBI_ADDR.FULL = (uint32_t) 0x00000000;
   do 
   {
	   for(uint8_t j=0; j<7 && EBI_ADDR.A2 < 0x08; j++)  
      {	   
         PORTK.OUT = EBI_ADDR.A2;
         PORTH.OUTSET = EBI_ALE2;
         PORTH.OUTCLR = EBI_ALE2;
         PORTK.OUT = EBI_ADDR.A1;
         PORTH.OUTSET = EBI_ALE1;
         PORTH.OUTCLR = EBI_ALE1;
         PORTK.OUT = EBI_ADDR.A0;
   	
      	PORTJ.OUT = testarray[j];
		   delay_ns(200);
      	PORTH.OUTCLR = EBI_WE;  //write when low, read when high		
		   delay_ns(100);
         PORTH.OUTSET = EBI_WE;  //write when low, read when high	  
   	   EBI_ADDR.FULL++;
      }
   } while (EBI_ADDR.A2 < 0x08); 
   
}
	
void RAM_READ()
{   
   PORTH.OUTCLR = EBI_CS0; //active low
   PORTH.OUTSET = EBI_RE;  //active low
   PORTH.OUTSET = EBI_WE;  //write when low, read when high      
   PORTJ.DIR = 0x00;       //read
	// Read back from SRAM and verify.
	EBI_ADDR.FULL = (uint32_t) 0x00000000;
   do 
   {
	   for(uint8_t j=0; j<7 && EBI_ADDR.A2 < 0x08; j++)  
      {	   
         PORTK.OUT = EBI_ADDR.A2;
         PORTH.OUTSET = EBI_ALE2;
         PORTH.OUTCLR = EBI_ALE2;
         PORTK.OUT = EBI_ADDR.A1;
         PORTH.OUTSET = EBI_ALE1;
         PORTH.OUTCLR = EBI_ALE1;
         PORTK.OUT = EBI_ADDR.A0;
		 
		   delay_ns(200);
		   PORTH.OUTCLR = EBI_RE;  //active low
		   delay_ns(100);
		   uint8_t mem_read_var = PORTJ.IN;
		   delay_ns(50);
		   PORTH.OUTSET = EBI_RE;  //active low
		      
		   if (mem_read_var != testarray[j])	   	   
	      {
   	      SRAM_ERR++;	  
         }
		   
   	   EBI_ADDR.FULL++;
      }
   } while (EBI_ADDR.A2 < 0x08);   
   
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've used the Atmel EBI driver but never seen the the __far_mem_* macros. I looked over some code I wrote for huge fifos and found out why. It's because I used the hugemem service which provides hugemem_read8() and hugemem_write8(), where the "8" can also be a "16" or 32".

The fact that your manual code produces the same result points to a problem with the SDRAM or its interconnection to the XMEGA. Perhaps a short between the two data lines in question, as they pull down stronger than they pull up?

Gamu The Killer Narwhal
Portland, OR, US
_________________
Atmel Studio 6.2
Windows 8.1 Pro
Xplained boards mostly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

GTKNarwhal wrote:
Perhaps a short between the two data lines in question, as they pull down stronger than they pull up?

Yah, this was my problem. There was a small short between pin 2 and 3, didnt see it untill i used a proper magnifying glass.

Thanks for taking the time to review my problem.