Using W25Q256 on Audio shield

Status
Not open for further replies.

Sandro

Well-known member
Hi all, I'm experimenting a W25Q256FV 16-pin SOIC 300-mil on Audio shield Rev B (on teensy 3.6, clock 240MHz), in order to store audio files to be played. Actually I have connected the flash chip with short wires:

Flash_wires.jpg

In write operation I never experimented issues, while reading I've (really NOT frequent) problems (reading errors maybe?): anyone can help me to go a bit deeper and maybe understand what is wrong? Maybe I could try adding a decupling capacitor between Vcc and GND pins close to the chip...

I have also designed an adaptor:

flash32M.JPG

but... before making it I'd like to hear some opinion/tip.
Thanks a lot for any idea!
 
I've tried before and I didn't get anywhere. I tried the Teensy 3.6 and it did not work. I also tried the Teensy 4.0 using the beta audio adapter that allows a T4 to use revision A/B/C audio shields with no luck. Here is the thread:

Now, when I put the version B of the audio shield on the Teensy 3.6, I could install the 3.6 Teensy Transfer for the Audio Shield, and it could access the files (T4 right now can't use Teensy Transfer because it doesn't have the RAW HID USB support):

But as I said in the thread, using SerialFlash did not work (I have used SerialFlash when I had it hooked up outside of the audio shield).

I haven't gotten too far into trying various things. I do have some ideas. Some come from the Better SPI bus design paper:

Here are some of the things I've thought about:
  • I wonder whether changing the SCLK and MOSI pins on the 3.x shields affects SerialFlash. I've tried different orderings of setting the MOSI/SCLK and initializing the SPI bus to no avail. At some point, I plan to solder a memory chip to a revision D audio shield to see if that works;
  • I want to add pull-up resistors to both pins 6 (flash memory) and 10 (sd card) to see if that helps. Possibly also hard-wiring pin 10 to 3.3v;
  • I just got in some chips for tri-stating, but I don't have a breakout setup like you do (yet). However, if it does need to have a tri-state setup, that kind of ruins using it on the audio board;
  • With other SPI devices, I have had to play with the SPI clock speed and processor bus speed. However, as I've said, I think I've been able to use the chip outside of the audio shield, so it seems something the audio shield may be doing. However, as I re-read the thread, I see I had problems when the 3.2 speed was faster than 96Mhz, so you might try setting the 3.6 speed down to 24Mhz to see if it works.

I bought this SOIC-8 to DIP adapter made by Sparkfun. I bought the adapter and the flash memory at , and sold by digi-key:

The chips I just got from digi-key to do the tri-state tests are:
 
Last edited:
Hi Michael, thank you for your answer; I didn't get if you are talking about W25Q256 32M 16-pin chip or about the W25Q128 16M 8-pin chip (which is not my case); I'm using SerialFlash in my code.
Maybe I'm too optimistic, but I belive that there is only some simple electric issues (signal reflections... interferences) because the chip works better by shortening the wires: in a first assembly I had connected the chip using 20mm wires and the result was quite bad; now, with 8-10mm wires the behave is much better.
Since my first post I've added a 100nF capacitor between Vcc and GND and now, after reading the page "Better SPI bus design paper" you suggested, also removed the SD card from the socket on audio board to avoid any possible interference on SPI bus... Let's see, tomorow I'll continue. I'll also test a lower clock speed, even if my application requires 240MHz to offer full performance.
 
Hi Michael, thank you for your answer; I didn't get if you are talking about W25Q256 32M 16-pin chip or about the W25Q128 16M 8-pin chip (which is not my case);
I have the W25Q128JVSIQ (128 megabits, 16 megabytes), but I suspect there may be similar issues with other flash memory chips. But if you are soldering the chip on the audio board, you have to use an 8-pin chip.

Note, I am a software guy, not a hardware guy. So it might be something else completely. I am just guessing at the causes.

If you aren't soldering the board directly onto the audio shield, it may make sense to put it on its own board. That would eliminate issues caused by the audio shield.

I do wonder whether the 3.6 built-in micro SD card would be competitive with the flash memory. On the 3.6, it uses its own SPI bus, so you don't have interference with other devices on the SPI bus. It uses quad SPI instead of the 1 bit SPI used by either the audio shield SD card or flash memory connection. In my case, the primary Teensy I'm using is the Teensy 4.0, and it is harder to access the pins for the micro SD card reader underneath the Teensy. And with a micro SD card, you can go to 32GB or so in terms of memory. When the audio shield was designed, we only had 1 bit SPI external micro SD card readers.

Looking at the schematic for the audio adapter (which I hadn't before now), I see there is a 10k pull-up resistor between 3.3v and each of the 6 and 10 pins, so in theory, you should not need an additional pull-up resistor. Pins 7 (hold in single SPI or IO3 in quad SPI) and 3 (WP in single SPI or IO2 in quad SPI) of the memory chip are wired to 3.3v, so you are pretty much limited to single SPI.

Similarly, for the micro SD card, 2 of the pins (DAT1, DAT2) are not connected.

And yeah, I probably forgot to take out the SD card when I was doing the initial tests.
 
Last edited:
I do wonder whether the 3.6 built-in micro SD card would be competitive with the flash memory. On the 3.6, it uses its own SPI bus, so you don't have interference with other devices on the SPI bus. It uses quad SPI instead of the 1 bit SPI used by either the audio shield SD card or flash memory connection. In my case, the primary Teensy I'm using is the Teensy 4.0, and it is harder to access the pins for the micro SD card reader underneath the Teensy.

This is so important to me! I didn't know this fact of quad SPI... Maybe it means that reading data rate from micro SD card on Teensy is comparable/faster than from flash memory soldered on Audio shield.. :rolleyes: I'll try very soon to switch my code from flash memory chip to Teensy/local micro SD card, and compare both.

And with a micro SD card, you can go to 32GB or so in terms of memory.
Yes this is a great plus of micro SD... much more memory than I need by the way but... it's not a disadvantage!
 
This is so important to me! I didn't know this fact of quad SPI... Maybe it means that reading data rate from micro SD card on Teensy is comparable/faster than from flash memory soldered on Audio shield.. :rolleyes: I'll try very soon to switch my code from flash memory chip to Teensy/local micro SD card, and compare both.


Yes this is a great plus of micro SD... much more memory than I need by the way but... it's not a disadvantage!

Be sure to use a fast SD-HC card for your tests. Also format the card just before doing the test so the filesystem is not fragmented.

I'm not sure whether the software or hardware support SD-XC cards (i.e. >= 64GB) and the exFat file system used for 64GB and greater..

Another advantage of micro SD cards is you can take them off of the Teensy and read them directly on your computer.

But if you were still wanting to do flash, FrankB posted a 'parallel SPI flash' library. I have not used it (and in fact had forgotten about it until this thread started and I noticed a reference to it). You won't be able to use the audio card, since that does not hook up the extra pins:
 
Be sure to use a fast SD-HC card for your tests. Also format the card just before doing the test so the filesystem is not fragmented.

Good suggestion! I had not considered this!

I'm not sure whether the software or hardware support SD-XC cards (i.e. >= 64GB) and the exFat file system used for 64GB and greater..

For my application, the midi expander:
https://forum.pjrc.com/threads/57897-queued-Lilla

100M for file system is more than enough!! :eek:

But if you were still wanting to do flash, FrankB posted a 'parallel SPI flash' library. I have not used it (and in fact had forgotten about it until this thread started and I noticed a reference to it). You won't be able to use the audio card

Could also be interesting if I coud "replace" the Audio shield codec with an SPDIF output but, as long as I have experimented, SPDIF cannot replce the Audio shield: I experiment bad audio "clicks" with SPDIF, with the intense audio activity of my application; also should be checked if 'parallel SPI flash' library is compatible with SPDIF. Besides, I need stereo and 16bit accuracy (no way for PCM output, I belive).

Let's see: in my library I'm replacing all flash reading procedures with SD procedures ... next, after the necessary debugging, I'll be ready to do some tests :cool:

Thank you Michael!
 
Last edited:
Note, the original post is about the Teensy 3.2 and the audio shield SD card.

I suspect that with either the built-in SD card or flash memory using SPI quad that it would be much faster. Ultimately, both are just flash memory ports that can transfer up to 4 bits at a time. A micro SD card is just a flash memory chip with the pins brought out.

It ultimately will likely depend on several things:
  • The exact speed of the micro SD card or the flash memory;
  • Whether you have to slow down the SPI bus for the card/flash memory;
  • Whether you have to slow down the processor speed because the Teensy is running too fast;
  • Whether or not the driver works with interrupts enabled, or it disables interrupts while dealing with the flash;
  • If there are other things on the SPI bus;
  • Caching behavior of the Teensy 4.0 (which in turn depends on which memory bank you are using and whether you have to flush the cache); (or)
  • If you have hardware SPI optimization enabled (this is different between the Teensy 3.6 and 4.0).

Of course the only way to know for certain is to try it.
 
Last edited:
Note, the original post is about the Teensy 3.2 and the audio shield SD card.

Hi Michael,
I had not notice that!

So.. thank you for your detailed analysis: at the moment I would remain on Teensy 3.6, or maybe switch to T4.0 in a next release; and for all the topics you point out I have no answers... I can only try to modify my code and see what happend using the SD card on my Teensy 3.6.... Even if it seems that I've reached a good point with the 32MB chip: with this cabling

View attachment 18351

(really not so nice to see!!) my device is working good: not any clicks or other problems after 1 hr of sound tests. This seems to confirm that in the previous arrangement there were electric problems.


About switching my code from flash memory to SD, I unfortunately don't understand how play_SD_raw works... So this change will take long time. Don't even know what help to ask, because my library is too long and I don't want to annoy anyone. In a nutshell, I started with some trivial Ctrl-C / Ctrl-V from play_SD_raw, replacing this code:

Code:
    rawfile = SerialFlash.open(filename);
    AudioStartUsingSPI();
    if(!rawfile)
        AudioStopUsingSPI();

with this:

Code:
#if defined(HAS_KINETIS_SDHC)
    if (!(SIM_SCGC3 & SIM_SCGC3_SDHC))
        AudioStartUsingSPI();
    #else
        Serial.println("failed!");
        AudioStartUsingSPI();
    #endif

    __disable_irq();
    rawfile = SD.open(filename);
    __enable_irq();
    if (!rawfile)
    {
        //Serial.println("unable to open file");
        #if defined(HAS_KINETIS_SDHC)
            if (!(SIM_SCGC3 & SIM_SCGC3_SDHC))
                AudioStopUsingSPI();
        #else
            AudioStopUsingSPI();
        #endif
        return false;
    }

Is it a good start-point?
 
Sorry, here:
Code:
#else
        Serial.println("failed!");
        AudioStartUsingSPI();
 #endif

Serial.println("failed!") is a refuse.

Ok, in order to understand something about playSDraw, first I'll look for the meaning of these values:
HAS_KINETIS_SDHC
SIM_SCGC3
SIM_SCGC3_SDHC
 
Last edited:

The attached pic was this:
FLASH OK.jpg

In these day I went on with my tests... and this assembly showed some limit: with intense use of the chip some errors appares. I guess if a small PCB with its groun plane could help data transmission. In the meanwhile I'm trying to switch my code to playSDraw.
 
I suspect that with either the built-in SD card or flash memory using SPI quad that it would be much faster. Ultimately, both are just flash memory ports that can transfer up to 4 bits at a time. A micro SD card is just a flash memory chip with the pins brought out.

Hi Michael,
I made some tests with micro SD built on Teensy 3.6, clock 180 MHz; I played with play_SD_raw, modifying the lenght of the data array read from SD, as follows.

The "core" part of play_SD_raw.cpp, a bit modified in order to change the number of samples read from SD, is:
Code:
if (rawfile.available())
    {
        blocks ++;
        t = micros();
        rawfile.seek(x); //  uint32_t x is declared as private in the header .h
        n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 2); // int16_t basket[1000] is declared inside update()
        for (i=n/2; i < AUDIO_BLOCK_SAMPLES; i++)
            basket[i] = 0;
        x += AUDIO_BLOCK_SAMPLES * 2;
        for(uint16_t i =0; i < AUDIO_BLOCK_SAMPLES; i++)
            block->data[i] = basket [i];
        transmit(block);
        if (!(blocks % 200))
            Serial.println(micros() - t);
    }

Using the code above, the lap time micros() - t is 8-9 microseconds and this is a very, very good value!:D

But, if I change a bit the number of samples read, from (AUDIO_BLOCK_SAMPLES * 2) to (AUDIO_BLOCK_SAMPLES * 4):
Code:
if (rawfile.available())
    {
        blocks ++;
        t = micros();
        rawfile.seek(x); //  uint32_t x is declared as private in the header .h
        n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 4); // int16_t basket[1000] is declared inside update()
        for (i=n/2; i < AUDIO_BLOCK_SAMPLES; i++)
            basket[i] = 0;
        x += AUDIO_BLOCK_SAMPLES * 2;
        for(uint16_t i =0; i < AUDIO_BLOCK_SAMPLES; i++)
            block->data[i] = basket [i];
        transmit(block);
        if (!(blocks % 200))
            Serial.println(micros() - t);
    }

than micros() - t rises up to 552-644 microseconds...

Do you know what happens? why this huge fall of performance?

Thank you
 
than micros() - t rises up to 552-644 microseconds...

Do you know what happens? why this huge fall of performance?

Only 9 us is a suspiciously low time for a SD card sector read. Are sure you're really capturing a representative sample of the actual times? Would be much better to compute the min, average and max times and print those 3 numbers. As I understand this code, it seems you're printing only a single measurement every 200th run and ignoring everything that happens in the other 199 cases. A min/avg/max report covering all 200 would show a clearer picture of what's really happening.

On the slow performance, it the SD card has to fetch another sector, and especially if a FAT sector needs to be read as well as a data sector, you can expect the operation to take some time.

One thing you might try if you're using the SD card by SPI (not the builtin SD socket on Teensy 3.6) is the experimental SD optimizations. Edit SD_t3.h to enable that code. It caches several sectors. But it was written before Teensy 3.6 and 4.0, so it only supports SPI access to the card. It's also read-only, which is most of the reason it's considered experimental. But it's really useful to compare against the default SD library code if you're seeing performance issues.
 
Only 9 us is a suspiciously low time for a SD card sector read. Are sure you're really capturing a representative sample of the actual times? Would be much better to compute the min, average and max times and print those 3 numbers. As I understand this code, it seems you're printing only a single measurement every 200th run and ignoring everything that happens in the other 199 cases. A min/avg/max report covering all 200 would show a clearer picture of what's really happening.

On the slow performance, it the SD card has to fetch another sector, and especially if a FAT sector needs to be read as well as a data sector, you can expect the operation to take some time.

One thing you might try if you're using the SD card by SPI (not the builtin SD socket on Teensy 3.6) is the experimental SD optimizations. Edit SD_t3.h to enable that code. It caches several sectors. But it was written before Teensy 3.6 and 4.0, so it only supports SPI access to the card. It's also read-only, which is most of the reason it's considered experimental. But it's really useful to compare against the default SD library code if you're seeing performance issues.

Hi Paul, thank you for your answer; I started adding some lines in order to get min, max and average times, and the result was so strange (for me!), that I decided to see each value; this is my code, normal speed playback:
Code:
void AudioPlaySdRawMod::update(void)
   {
        t = micros();
        rawfile.seek(x);
        n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 2);
        for (i = n/2; i < AUDIO_BLOCK_SAMPLES; i++)
            basket[i] = 0;
        x += AUDIO_BLOCK_SAMPLES * 2; // uint32_t x, defined in header
        for(i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
            block->data[i] = basket [i];
        t_array[blocks] = micros() - t; // uint16_t t_array[256], defined in header
        transmit(block);
        blocks ++; // uint32_t blocks, defined in header
        if (blocks == 1000)
        {
            for(i = 0; i < 1000; i++)
                {
                    Serial.print(i);
                    Serial.print("  ");
                    Serial.println(t_array[i]);
                }
            Serial.println();
            Serial.println();
            Serial.println();
            blocks = 0;
        }
    }
    else
    {
        rawfile.close();
        AudioStopUsingSPI();
        playing = false;
    }
    release(block);
}

and this is the result:
Code:
0  211
1  7
2  210
3  7
4  212
5  7
6  212
7  8
8  212
9  7
10  212
11  7
12  211
13  7
14  211
15  7
16  213
17  7
18  213
19  8
20  2138
21  7
22  212
23  7
24  211
25  8
26  211
27  8
28  213
29  7
30  213
... and so on

Using the following code (playback at double speed):
Code:
void AudioPlaySdRawMod::update(void)
   {
        t = micros();
        rawfile.seek(x);
        n = rawfile.read(basket, AUDIO_BLOCK_SAMPLES * 4);
        for (i = n/2; i < AUDIO_BLOCK_SAMPLES; i++)
            basket[i] = 0;
        x += AUDIO_BLOCK_SAMPLES * 4; // uint32_t x, defined in header
        for(i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
            block->data[i] = basket [2 * i];
        t_array[blocks] = micros() - t; // uint16_t t_array[256], defined in header
        transmit(block);
        blocks ++; // uint32_t blocks, defined in header
        if (blocks == 1000)
        {
            for(i = 0; i < 1000; i++)
                {
                    Serial.print(i);
                    Serial.print("  ");
                    Serial.println(t_array[i]);
                }
            Serial.println();
            Serial.println();
            Serial.println();
            blocks = 0;
        }
    }
    else
    {
        rawfile.close();
        AudioStopUsingSPI();
        playing = false;
    }
    release(block);
}

the output is more uniform:
Code:
0  211
1  211
2  211
3  212
4  211
5  211
6  211
7  211
8  211
9  214
10  210
11  213
12  213
13  212
14  213
15  213
16  212
17  213
18  213
19  212
20  212
21  211
22  210
23  213
24  213
25  212
26  212
27  213
28  216
29  213
30  213
... and so on

All these tests have been done with a Sandisk ultra 32GB not recently formatted: tomorrow I'll do a deep format and will repeat all tests.
About trying SD_t3.h I belive this a bit too difficult for me; at this point I think I'll make a small PCB with a ground-plane for W25Q256, to be mounted on the Audio board, than see what happens.
 
For completeness: after formatting, using normal speed playback, the report shows more or less same values and same behave:
Code:
0  218
1  7
2  217
3  7
4  2143
5  7
6  217
7  7
8  217
9  8
10  217
11  7
12  217
13  7
14  217
15  7
16  215
17  7
18  2141
19  7
20  215
21  7
22  217
23  7
24  217
25  7
26  217
27  8
28  217
29  8
30  217
 
Not sure if this is the reason, am using my phone to write this answer and can't look at the internal SD Code - but it would explain the behaviour if the SD lib internally buffers one block - which 512 Bytes. In your upper version of your code, you read 128*2=256 bytes, the half of a block - which may be got read already and thus is much faster for every 2nd read.
 
Not sure if this is the reason, am using my phone to write this answer and can't look at the internal SD Code - but it would explain the behaviour if the SD lib internally buffers one block - which 512 Bytes. In your upper version of your code, you read 128*2=256 bytes, the half of a block - which may be got read already and thus is much faster for every 2nd read.

I got it...Ok, thank you Frank for the explantion!
 
Same thought here - but in glancing the code misread 'AUDIO_BLOCK_SAMPLES * 2' as requesting two blocks …

That explains the "playback at double speed" read having that same time on each time measure.

Just for ref this thread has notes on using 8 MB psRAM on SPI at 80 MHz : PC-Engine-emulator-PSRAM-experiment
 
Going back to W25Q256..

I read on Audio shield schematics (where an 8-pin flash memory IC is contemplated), that "RST" is indicated. While on 8pin ICs (like W25Q128) /RESET and /HOLD use the same pin, on W25Q256 (16pin) /HOLD and RESET/ are separated on different pins:
W25Q256.JPG

Does anybody know which of them must be connected to 3.3V? Both? only /RESET?
thank you
 
Last edited:
Both /RESET and /HOLD need to be connected to 3.3V.

Good, thank you Neurofun. I'm designing a small pcb for the W25Q256, with a groudplane, to be soldered toghether with the Audio shield (on top, or below) ... let's see how it will perform.
 
Last edited:
A bad mistake I did here... i had connected the flash chip GND pin to Analog GND... shame on me.

The attached pic was this:
View attachment 18396

In these day I went on with my tests... and this assembly showed some limit: with intense use of the chip some errors appares. I guess if a small PCB with its groun plane could help data transmission. In the meanwhile I'm trying to switch my code to playSDraw.

Anyway, now the small PCB is done; i'm testing it, seems working fine.
shield.jpg
 
Status
Not open for further replies.
Back
Top