gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > SPI Command 0Bh (FAST) for faster read [Fixed, somehow..]

#105082 - Lick - Thu Oct 05, 2006 8:38 pm

The following code is a modified version of Stephen (sgstair)'s Read_Flash() function. The modification is that I'm trying to use the FAST instruction instead of the READ instruction. (For info, here.)
The code does not work as wanted, but my question is, does the DS support this instruction at all? Libnds seems to have excluded it from the #defines.

http://rafb.net/paste/results/JTJvtN50.html
Code:
void Read_FlashFast(int address, char * destination, int length) {
   int i;
    int dummy = 0;
   while(REG_SPICNT&0x80);
   REG_SPICNT=0x8900;
   REG_SPIDATA=0x0B; // fast read
   while(REG_SPICNT&0x80);
 
    // 3 times
   REG_SPIDATA=(address>>16)&255;
   while(REG_SPICNT&0x80);
   REG_SPIDATA=(address>>8)&255;
   while(REG_SPICNT&0x80);
   REG_SPIDATA=(address)&255;
   while(REG_SPICNT&0x80);
    // dummy
   REG_SPIDATA=(dummy)&255;
   while(REG_SPICNT&0x80);
 
   for(i=0;i<length;i++) {
      REG_SPIDATA=0;
      while(REG_SPICNT&0x80);
      destination[i]=REG_SPIDATA;
   }
   REG_SPICNT=0;
}

_________________
http://licklick.wordpress.com


Last edited by Lick on Sun Oct 08, 2006 3:43 pm; edited 2 times in total

#105085 - Lick - Thu Oct 05, 2006 8:56 pm

Okay, it -is- working as expected. I haven't measured the speeds, but the result is there.

The bug was this:
Code:
    printf("%u x %u x %u\n", NDSX_Firmware_GetShort(36),NDSX_Firmware_GetShort(38),NDSX_Firmware_GetLong(8));
    printf("%u %u - %u\n",
        NDSX_Firmware_GetShort(36), NDSX_Firmware_GetShort(38),
        NDSX_Firmware_GetLong(8));


If I comment out the second printf(), the application works and does not hang. WIth the second printf(), the application hangs -BEFORE- the first printf(). That's sick.

- Lick
_________________
http://licklick.wordpress.com

#105104 - tepples - Thu Oct 05, 2006 11:34 pm

Try getting all the results into variables and then printf()ing them. Also try iprintf() instead of printf() so that you don't need to bring in the floating-point emulator.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#105123 - HyperHacker - Fri Oct 06, 2006 7:50 am

Sounds like memory corruption.
_________________
I'm a PSP hacker now, but I still <3 DS.

#105413 - Lick - Sun Oct 08, 2006 3:41 pm

Okay just to report how it's going, it is all working now. The SPI command is working (!) and it should be faster than the readFirmware function in libnds (which doesn't work currently due to a small typo, but this is already fixed in r20).

The problem was probably something with the ARM9 cache, Wintermute told me. By putting DC_InvalidateRange(..); before each read, it was fixed. I'm not sure if this is the true solution but whatever it was, it hindered me to read the firmware many times, so as a work-around, now I have only a single (big) read.

I also wrestled with the FIFO queue, and if you read my blog, you'll find a new and useful tip! ;)

- Lick
_________________
http://licklick.wordpress.com

#105415 - Lick - Sun Oct 08, 2006 3:45 pm

To add to the previous post ^, here is the Arm7 code for faster reading:

Code:
void Read_FlashFast(u32 address, u8 *destination, u32 length) {
    u32 i;

    // Set SPI command
    //
    while(REG_SPICNT & SPI_BUSY);
    REG_SPICNT  = 0x8900;
    REG_SPIDATA = 0x0B;             // 0B = fast read, 03 = normal read
    while(REG_SPICNT & SPI_BUSY);

    // Command parameters
    //
    REG_SPIDATA=(address>>16)&255;  // Part 1 of address
    while(REG_SPICNT & SPI_BUSY);
    REG_SPIDATA=(address>>8)&255;   // Part 2 of address
    while(REG_SPICNT & SPI_BUSY);
    REG_SPIDATA=(address)&255;      // Part 3 of address
    while(REG_SPICNT & SPI_BUSY);
    REG_SPIDATA=0;                  // Dummy write, only when using SPI{0B}
    while(REG_SPICNT & SPI_BUSY);

    for(i=0; i<length; i++)
    {
        REG_SPIDATA = 0;
        while(REG_SPICNT & SPI_BUSY);
        destination[i] = REG_SPIDATA & 255;
    }

    REG_SPICNT = 0;
}

_________________
http://licklick.wordpress.com