Microchip® Advanced Software Framework

Quick Start Guide for the XMEGA EBI Driver

This is the quick start guide for the EBI Driver, with step-by-step instructions on how to configure and use the driver for specific use cases.

The section described below can be compiled into e.g. the main application loop or any other function that might use the EBI functionality.

Basic usage of the EBI driver

Basic usage of the EBI driver would be to interface external SRAM/SDRAM. Our specific use case will cover usage of SDRAM.

Interfacing SDRAM

A basic use case for the EBI driver would be to interface SDRAM, and in this specific case, interfacing the on-board 8 MB SDRAM chip of the XMEGA A1 Xplained board. The module is connected in three-port mode, utilizing 12 address lines. The timing information in the configuration of the device is specific to this chip. You may directly use the source code if you are using the same chip (or board), otherwise you should refer to the SDRAM chip's data sheet for specific timing information.

Prerequisites

To be able to interface the external SDRAM module, the Data in Huge Data Memory Space (hugemem) module must be included and enabled. This is done by selecting the hugemem module from ASF, and including the line

#define CONFIG_HAVE_HUGEMEM

in your source code. We also need some information about our chip, such as address start, size of usable memory, refresh rate and initialization delay.

#define BOARD_EBI_SDRAM_BASE 0x800000UL
#define BOARD_EBI_SDRAM_SIZE 0x800000UL
#define BOARD_EBI_SDRAM_REFRESH (16 * 2 * sysclk_get_per2_hz() / 1000000)
#define BOARD_EBI_SDRAM_INITDLY (100 * 2 * sysclk_get_per2_hz() / 1000000)

Include string.h for memset() and strlen() functions:

#include <string.h>

Setup steps

Code

Workflow

After the board has been initialized, we need to initialize the EBI driver. We need two configuration structures to configure the driver:

memset(&cs_config, 0, sizeof(struct ebi_cs_config));
memset(&sdram_config, 0, sizeof(struct ebi_sdram_config));
Note
It is important to zero out the config struct using memset, so that we do not produce any unwanted behavior.

We set up the EBI driver for three-port, 12 address line SDRAM operation:

We set the chip select mode to SDRAM, address space size to 8 MB, and the base address:

We want normal SDRAM operation:

ebi_sdram_set_mode(&cs_config, EBI_CS_SDMODE_NORMAL_gc);

SDRAM is organized in rows and columns, and we want 12 rows and 10 columns:

The timing information for our device is:

  • CAS Latency - 3 clock cycles
  • Mode delay - 2 clock cycles
  • Row cycle delay - 7 clock cycles
  • Row pre-charge delay - 7 clock cycles
  • Write recovery delay - 1 clock cycle
  • Self refresh to active delay - 7 clock cycles
  • Row to column delay - 7 clock cycles
  • Refresh period - Dependent on frequency, see Prerequisites.
  • Init delay - Dependent on frequency, see Prerequisites.

Set all timing information:

Our configuration is complete, now we write it to the device:

And enable the chip select for the device:

Now we wait for the EBI driver to initialize and be ready for use:

while (!ebi_sdram_is_ready()) {
// Wait
}
Note
Not waiting for the EBI to become ready will result in undefined behavior.

Example usage code

The EBI is now configured and running. We will write a string to memory, and read it back again.

Code

#define DATA_SIZE 32
uint8_t data[DATA_SIZE] = "This data written to SDRAM";
uint8_t read_data[DATA_SIZE];
uint8_t i;
ptr = BOARD_EBI_SDRAM_BASE;
memset(read_data, 0, DATA_SIZE);
for(i = 0; i < strlen(data); i++) {
hugemem_write8(ptr, data[i]);
ptr = ptr + sizeof(uint8_t);
}
ptr = BOARD_EBI_SDRAM_BASE;
for(i = 0; i < strlen(data); i++) {
read_data[i] = (uint8_t)hugemem_read8(ptr);
ptr = ptr + sizeof(uint8_t);
}

Workflow

We declare the size of our data chucks, a hugemem-pointer which we will use to point to SDRAM, a chuck of data, and a chuck to read into.

#define DATA_SIZE 32
uint8_t data[DATA_SIZE] = "This data written to SDRAM";
uint8_t read_data[DATA_SIZE];
uint8_t i;

We point the pointer to the beginning of SDRAM.

ptr = BOARD_EBI_SDRAM_BASE;

We zero out the read_data variable to make sure its empty.

memset(read_data, 0, DATA_SIZE);

We now write the data to SDRAM.

for(i = 0; i < strlen(data); i++) {
hugemem_write8(ptr, data[i]);
ptr = ptr + sizeof(uint8_t);
}

The ptr variable now points to the end of the string, so reset it.

ptr = BOARD_EBI_SDRAM_BASE;

We now read the data back into the read_data chuck:

for(i = 0; i < strlen(data); i++) {
read_data[i] = (uint8_t)hugemem_read8(ptr);
ptr = ptr + sizeof(uint8_t);
}

The read_data variable now contains the same as the data variable.