Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12690 Discussions

Accessing qspi with a NIOS V application on a C10GX

agieson_cl
Novice
408 Views

Hi!

When attempting to read and write to a qspi chip on my C10GX board, writes do not seem to be working properly (assuming the reads are working properly). I am using the Generic QUAD SPI Controller II Intel FPGA IP, and have been able to boot my NIOS application from it to show that it is working properly. The problems arise when I am trying to read and write data to the qspi device.

For example, when writing 0x55 to the first page of NOR Flash memory (256 bytes), I get the following result when reading back the values:

indices 0-63: 0x55

indices 64-223: 0xFF

indices 224-255: 0x55

And when writing 0xAA to the second page of NOR Flash memory, I get the following result when reading back the values:

indices 0-31: 0xAA

indices 32-63: 0xFF

indices 64-95: 0xAA

indices 96-255: 0xFF

 

here's my code I'm using for this test, which works fine on a NIOS II application with a spi flash chip:

 

int flash_check(void) {
    printf("starting flash test\r\n");
    const unsigned int pageSize = 256;
    int flag = 0;

    struct flash_region *flash_info = {0, 0, 0, 0};

    alt_flash_fd* fd;
    fd = alt_flash_open_dev(GENERIC_QUAD_SPI_CONTROLLER2_0_AVL_MEM_NAME);  // from system.h
    if (fd == NULL) {
        printf("Flash initialization failed!\r\n");
        return 1;
    }

    char retdata[pageSize]; 
    int retval = 0;

    printf("erasing memory\r\n");
    retval = alt_qspi_controller2_erase_block(fd, 0);
    if (retval != 0) {
        printf("NOR Flash could not be erased.\r\n");
        flag = 1;
    }

    int num_regions = 0;

    retval = alt_qspi_controller2_get_info(fd, &flash_info, &num_regions);
    printf("retval=%d\r\n", retval);
    printf("num_regions=%d\r\n", num_regions);
   
    printf("flash region offset: 0x%0x\r\n", flash_info->offset);
    printf("flash region size: 0x%0x\r\n", flash_info->region_size);
    printf("flash region number of blocks: 0x%0x\r\n", flash_info->number_of_blocks);
    printf("flash region block size: 0x%0x\r\n\r\n", flash_info->block_size);

    printf("setting memory to 0x55 from 0x%08x - 0x%08x\r\n", 0, pageSize-1);
    memset(retdata, (char)0x55, pageSize);
    retval = alt_qspi_controller2_write_block(fd, 0, 0, retdata, pageSize);
    if (retval != 0) {
        printf("Could not write to flash memory.\r\n");
        flag = 1;
    }

    printf("setting memory to 0xaa from 0x%08x - 0x%08x\r\n", pageSize, pageSize*2-1);
    memset(retdata, (char)0xaa, pageSize);
    retval = alt_qspi_controller2_write_block(fd, 0, pageSize, retdata, pageSize);
    if (retval != 0) {
        printf("Could not write to flash memory.\r\n");
        flag = 1;
    }

    printf("reading memory 0x%08x - 0x%08x\r\n", 0, pageSize-1);
    retval = (int) alt_qspi_controller2_read(fd, 0, retdata, pageSize);
    for (unsigned int i = 0; i < pageSize; i++) {
        if ((retdata[i] & 0xFF) != 0x55) {
            printf("index: %d\tread value: 0x%02x\texpected value: 0x%02x\n\r", i, retdata[i] & 0xFF, 0x55);
            flag = 1;
        } else {
            printf("index: %d\tgot expected result!\r\n", i);
        }
    }

    printf("reading memory 0x%08x - 0x%08x\r\n", pageSize, pageSize*2-1);
    retval = (int) alt_qspi_controller2_read(fd, pageSize, retdata, pageSize);
    for (unsigned int i = 0; i < pageSize; i++) {
        if ((retdata[i] & 0xFF) != 0xaa) {
            printf("index: %d\tread value: 0x%02x\texpected value: 0x%02x\n\r", i, retdata[i] & 0xFF, 0xaa);
            flag = 1;
        } else {
            printf("index: %d\tgot expected result!\r\n", i);
        }
    }

    // erase the memory so the NOR Flash is empty for the customer
    printf("erasing memory\r\n");
    retval = alt_qspi_controller2_erase_block(fd, 0);
    if (retval != 0) {
        printf("Flash memory could not be erased.\r\n");
        flag = 1;
    }

    return flag;
}
 
Other potentially useful information:
NOR Flash part number: MT25QU256ABA8E12-1SIT
Active serial clock is set to internal 50 MHz oscillator under device and pin options
QSYS params for Generic QUAD SPI Controller II Intel FPGA IP:
- Disable dedicated active serial interface is not checked
- Enable SPI pins interface is checked
- Enable flash simulation model is not checked
- Configuration device type is set to MT25QU256
- Choose I/O mode is set to QUAD
- Number of chip selects used is set to 1 (there are no other devices hooked up to to qspi bus)

 

0 Kudos
1 Solution
agieson_cl
Novice
277 Views

Ok so I was able to fix the issue. The problem was the memory was being cached (or more accurately partially cached for some reason). In qsys I added an additional peripheral region for the qspi region and this allowed me to properly read and write to the NOR Flash as expected using the code in my original post. 

As a more permanent fix, I will be changing my niosv_g processor to a niosv_m processor, which does not allow data caching, as the ability to only create two peripheral regions is limiting. 

View solution in original post

0 Kudos
4 Replies
JingyangTeh
Employee
352 Views

Hi

Could you try :

 retval = alt_qspi_controller2_write_block(fd, pageSize,0 , retdata, pageSize);


Swapping the block_offset and the data_offset?

The block offset is the offset in the flash and the data offset is the array offset.


The definition of the write block is as follow:

int alt_qspi_controller2_write_block(alt_flash_dev *flash_info, int block_offset, int data_offset, const void *data, int length);


Regards

Jingyang, Teh


0 Kudos
agieson_cl
Novice
315 Views

I tried this and did not get successful results unfortunately -- there were not even partially correct results and all returned data was 0xff.

 
Additionally, while trying to debug the code, I've changed a few print statements without touching the read or write functions, and I noticed that the data returned changed. For example instead of getting:
Indices 0-63: 0x55
Indices 64-223: 0xFF
Indices 224-255: 0x55
I'm now getting:
Indices 0-95: 0xFF
Indices 96-159: 0x55
Indices 160-255: 0xFF
 
I'm not sure what could be causing the NOR Flash to read or write differently when changing unrelated parts of my code. 
 
Another debugging step I tried: setting the value at a certain index to the index. For example, using a counter to set 0x00 to 0x00, 0x01 to 0x01, 0x02 to 0x02 and so on...

results for block 0 bits 0 to 255:
Indices 0x00 - 0x1F: equal to the index
Indices 0x20 - 0xBF: 0xFF
Indices 0xC0 - 0xFF: equal to the index

results for block 0 bits 256 to 511:
Indices 0x00 - 0x7F: 0xFF
Indices 0x80 - 0x9F: equal to the index
Indices 0xA0 - 0xDF: 0xFF
Indices 0xE0 - 0xFF: equal to the index
 

from this I've gathered it is writing memory correctly, but is either not able to read or write certain sections at times. The sections it is able to read from and and write to do not change after rebooting the C10GX board or after reloading the same FPGA image and same NIOS V program. The sections it reads from and writes correctly to only changes when recompiling the code and uploading it to the device. 

 

0 Kudos
agieson_cl
Novice
278 Views

Ok so I was able to fix the issue. The problem was the memory was being cached (or more accurately partially cached for some reason). In qsys I added an additional peripheral region for the qspi region and this allowed me to properly read and write to the NOR Flash as expected using the code in my original post. 

As a more permanent fix, I will be changing my niosv_g processor to a niosv_m processor, which does not allow data caching, as the ability to only create two peripheral regions is limiting. 

0 Kudos
JingyangTeh
Employee
217 Views

Hi


I’m glad that your question has been addressed, I will now transition this thread to community support. If you have a new question, Please login to ‘https://supporttickets.intel.com/s/?language=en_US’, view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions.


Regards

Jingyang, Teh


0 Kudos
Reply