Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

SPI speed problem on PIC32

Status
Not open for further replies.

electroman2000

Member level 2
Joined
Feb 3, 2015
Messages
44
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Activity points
496
Hi, I have a problem with SPI speed on PIC32. I'm using a PIC32MX795F512, mounted on testing board "EasyPIC Fusion v7" from mikroelettronica. So I can execute a physical debug, with timer and pheripherals response ecc. So, of course, I use mikroC for programming this PIC.
I write a series of byte in the SD card using the MMC library of mikroC. For a maximum speed, I'm writing on sector.
The problem is that the SPI doesn't reach the max speed allowed. In the data sheet the max speed is 25 Mbps, so about 3 MBps (the SD is a SDHC with a min speed of 10 MBps ). In mikroC, I set PBCLK=SYSCLK, and divider=8, where SPI_clock=PBCLK/divider. So, because SYSCLK is 80 Mhz, the calculated speed is 80/8=10 Mbps = 1,25 MBps.
If I count, with a timer, the time for writing a given package of byte, I obtain the actual speed is 156 kBps. You can notice that 156 kBps*8=1,25 Mbps. So I have a divisor factor 8, but I don't know when it come from.
In the debug mode I check every register involving the PBCLK speed, the divisor to obtain the SPI clock and all values are ok. Also I check if the timer counter is right, confronting it with the chronometrous of my smarthpone, and it is.
Can you help me?
 

Please show us the code of a program that only drives the SPI peripheral (just sending dummy values is fine) that demonstrates your problem. (In other words we don't need to see all of the code that controls the driving of the SD card as that is not relevant to how fast the SPI SCK is going.)
Have you put a scope on the SCK pin and measured the frequency?
Don't get confused between the SCK frequency and the throughput of bytes - even if you are using DMA there is typically a small gap between SPI exchanges, but the SCK frequency is correct.
Susan
 

Thank you Susan for reply.
Ths is the most important part of code:

Code:
SPI3_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, 80, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

FAT32_Init();

SPI3_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, 8, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_HIGH, _SPI_ACTIVE_2_IDLE);

TMR1=0;
                       tempoin=TMR1;
                       

                       for(i=0;i<10;i++){
                                         Mmc_Write_Sector(sc1+i, stringa1);
                                         Mmc_Write_Sector(sc2+i, stringa2);
                                         Mmc_Write_Sector(sc3+i, stringa3);
                                         }
                       
                       tempoOUT=TMR1;
                       T1CON.F15=0; // timer1 OFF

I don't write the part of code that verify the corectness of SD initialization, the declaration ect.

The three string is a 512 bytes string filled with character. I iniziatilize SPI with low speed, then if initialization of SD card has success I reinitialize the SPI at higher speed. I don't use any form of DMA, only writing on sector. I write 10 sector for each file so 5 kb a file so 15 kb in total.
The timerin and timerout that you see count the write time. There is a counter variabile that increase itself each time the counter overflow and generate an interrupt (don't showed in code). With the values of this counter, timerin and timerout I can calculate the write time for writing 15 kb and then the write speed. As I said this velocity is 156 KBps, a 8 time lower than my setting.
Unfortunately I don't have an oscilloscope, and also in the board that I use the socket of microSD is a shield soldered on board so it is not accessible by probe. But I think the method of timer is almost good. You can think that also timer1 is affected by time problem, because even timer1 use PBCLK. For verifying this, I made a simple chronometer of 5 seconds and confronted it with the chronometer of my smarthpone. It works properly.
So the time measurement is OK, and also the value of PBCLK is OK (because timer1, that use PBCLK, works properly). So the problem is during the division of PBCLK for obtaining SPICLK. This operation is done by SPIxBRG register, that I have verified and contain a correct value.
So I don't know what else I can do to figure what is going on.
Thanks for help
 

What that tells me is that you are trying to measure the overall transfer rate with the SD card that includes all of the overhead within functions that you have not shown - in particular the Mmc_Write_Sector function.
The title of this thread is about the SPI clock speed and this is completely masked by all of the other (hidden) code. Unless you can measure the SCK frequency, you cannot really tell that there is an issue with the SPI peripheral.
Susan
 

that includes all of the overhead within functions that you have not shown

He cannot show the functions because it is mikroC PRO PIC32 library functions and they are compiled libraries and mikroE doresn't provide source code for their libraries.
 

To summarize your test setup, you are measuring SD card sector write speed, not SPI data rate. The sector write involves interaction with the card, wait for command acceptance, wait for internal completion of the first sector before starting the second. The test surely doesn't show SPI data rate.

I could tell more about effective SD card handling, multiple versus single sector transfers etc. You need to know the internal working of flash based media to understand it. There are application notes from memory manufacturers e.g. Sandisk. But I have no idea how far the mikroC libraries are considering these things or just doing basic (slow) single sector transfers.

To check SPI speed without an oscilloscope, you would perform generic SPI communication rather than calling the MMC library. Although mikroC libraries are closed from your eyes, you can still look at machine code and register contents in debugging.
 
Thanks everybody for answering. Of course I know that I need to look into the mikroC functions to know better what they do, but as milan.rakij says, mikroC doesn't permit to show the content of its functions.
@FvM: it's right that SPI clock doens't coincide with byte rate. But a factor 8 is too high. If I undesrstand well, the control bit is two, one at begin and one at end of 8 bit transmission. So for transmitting 8 bit of data it should transmit 10 bit in total. This not explain the factor 8 of division.
The card support a minium speed of 10 Mbyte/s, the setting is for writing 3 Mbyte/s, I don't think handling command of SPI could take much time.

Can you show a custom code for performing generic SPI communication rather than calling the MMC library, as you said?

- - - Updated - - -

Sorry for double post, I can't edit my previous message due to time limit.
I want to add that in a previous try with Proteus and PIC18F (64 mhz clock), with the same function of mikroC for writing on sector, the write speed was correct.

Is it possible that CRC routine slow down the byte rate? And, if yes, why in proteus this not appened (the mikroC functions are the same)
 
Last edited:

I want to add that in a previous try with Proteus and PIC18F (64 mhz clock), with the same function of mikroC for writing on sector, the write speed was correct.
The comparison presumes that Proteus models the internal SD controller timing (e.g. flash write speed) which is rather unrealistic.

I must confess that I don't know which part of the observed SD transfer rate is determined by SD processing. Just wanted to mention that it can be a considerable amount. As a first check you could compare SD sector read against write. Reading is much faster.
 

So can anyone tell me how I can write a routine for writing into the sectors of SD card without using the mikroC functions?
 

So can anyone tell me how I can write a routine for writing into the sectors of SD card without using the mikroC functions?
You can do by using existing SD card libraries, e.g. FatFs. To test the SPI speed on its own, you can however use the basic MikroC SPI functions.
 
Or use the fact that you are dealing with a PIC32 device, look at the data sheets and write to the registers directly.
Assuming you have the SPI peripheral set up, and that you can use a blocking exchange, you exchange a value the code is along the lines of:
Code:
while( SPIxSTATbits.SPITBF);  // Wait for the SPI buffer to be free to write to
SPIxBUF = txValue;               // Start the exchange by sending a value
while( !SPIxSTATbits.SPIRBF); // wait for the exchange to complete
rxValue = SPIxBUF;               // Get the value we were just sent
(BTW, I don't know the MikroC syntax - this is XC32 but it should be obvious how to translate it.)
You will not get much faster. If you have multiple values to send and receive, then setting up a couple of DMA channels will let the exchanges follow one another as fast as the hardware can handle them.
If you want to put your timing reads of TMR1 around that, then it will tell you approximately how long it takes to exchange 1 byte via the SPI peripheral. Everything else is overhead in determining the values to send and interpreting what is received.
Susan
 
yes, now I understand that maybe call this problem "SPI problem" isn't right at all, the problem is the write speed. But a reduced speed of 8x is too much even considering the handling protocol of MMC. So finally I think the problem is the MMC functions of mikroC.

Thanks a lot for code, I will try it
 

I tryied the code. I set a divisor of 4, so the SPI clock is 80 Mhz (PBCLK) /4, = 20 Mhz. So 20 Mbps; for 1 byte, 8 bit, it should be take 400 ns. If I use a timer with resolution 12,5 ns (timer with prescaler = 1 and PBCLK=80 Mhz), I obtain (for your portion of code) 850 ns, about twice the theoretical value.
 

I think that you need to:
1) make absolutely sure that the system clock and peripheral clocks are running at the speed you think they are (they probably are, but I've seen many people spending hours troubleshooting when there is some very basic issue such as this)
2) to look at the assembler code that the compiler is generating and work out the code overhead from that
3) accurately measure the SCK signal on the pin, but unfortunately that really needs a scope (and I know you say you don't have one)
Of course there is another angle to all of this: does it really matter? I don't think you have mentioned the SD card that you are using, but is there a problem you are actually experiencing with the transfers not being fast enough? (There is a tendency to try to optimise a system by assuming that everything must be optimal - when there is always just one part that is the bottleneck and speeding up any other aspect is just a waste of time.)
Susan
 
1) yes, I'm pretty sure. I tested the PBCLK with timer1 using the chronometer of my smartphone. I did this simple but efficient (almost I think) test: my SYSCLK is 80 Mhz, and the divisor of PBCLK is 1, so PBCLK is 80 mhz too. Timer1 use PBLK; I have set the prescaler 256, so I obtain a period of 3,2 us for timer1. Putting PR=65535, the overflow trigger at 209 ms (3,2 us * 65535). Basing on this calculation I made a chronometer that count 5 second, using interrupt. At the begin the LED B0 turn on, and after a 24 interrupt (24*209 ms = 5 s) LED B1 turn on. I simple start my smartphone chronometer when LED B0 turn on and stop it when LED B1 turn on. It report 5 seconds. I think this try wih an external chronometer is good for assure that the SYSCLK and PBCLK is effectively 80 Mhz.

2) It's hard because I don't know very well assembler (last time I used it was 5 years ago), but I will try

3) yes :(

The SD card is a 8 GB Kingston SDHC, that I have formatted with SDformatter software. I don't thing it is a problem of SD card, because in one of my try I generated the image of SD card on PC and the showed speed was 40 MB/s
 

Just thinking about this and I'm wondering if you are worried about the speed thing unnecessarily.
In your first posting you say
(the SD is a SDHC with a min speed of 10 MBps )
Did you take this to mean that you (as the card driving device) must meet this minimum speed?
From what I know about SD cards (which I will admit is a bit limited), that speed is the specification of the minimum transfer rate the cards themselves must be able to meet. In other words, you can design a host device knowing that the SD card is able to work at least that fast. However it does NOT mean that it cannot work slower.
My understanding is that the SD card will generally accept the commands and data to (say) write a sector (which is often the slowest operation) into a buffer within the card and then carry out the operation. This means that you can use whatever SPI clock speed you can generate and also exchange values via the SPI interface at whatever speed you can manage and it will work.
If you have a application that must be able to save data at a certain rate, that is when the minimum transfer rates come in: the SD card must be able to accept/deliver data at that rate (and hence the minimum transfer speed is important to let you select the required class of SD card) and THEN you need to make sure your hardware can also match the required rate.
However it is the application that drives this and not the SD card itself. I don't think you have told us what your application is doing and what the minimum transfer rate it requires.
Susan
 
In other words, you can design a host device knowing that the SD card is able to work at least that fast. However it does NOT mean that it cannot work slower.
yes, of course. My english is not perfect, so I can't really explain well. I referred to the minium speed reported here https://en.wikipedia.org/wiki/Secure_Digital


However it is the application that drives this and not the SD card itself. I don't think you have told us what your application is doing and what the minimum transfer rate it requires.
Susan
I need at least 800 kB/s.

Hovewer, I put this question on official microchip forum, and the problem seems to be the mutisector write, that can dramatically increase the speed. Unfortunately I found a code write for a non specified platform (MPLAB I think) and now I have to port for my application. This is so hard (1000 lines code) but I will try to port only the function that I need (multi sector write)
 

I see that you finally arrived at the root of the problem. You'll hardly achieve 800 kB/s in single sector writes. I referred to the point in post #6.

Technically, it's simple to write larger blocks of raw data using a multi sector write command. A problem arises if you want to do this within a FAT file system which also involves updating the directory entries and file allocation tables, without keeping huge amounts of administrative data, e.g. FAT copies in RAM. This is done in mass storage drivers of full featured operation systems, but it's usually inappropriate in small embedded systems due to lack of resources.

A possible FAT compatible solution is to allocate continuous data blocks by placeholder files and write to through low level (multi) secor write commands, bypassing the file system.
 
Finally I understand how to modify the fatFS for adapt it to my system.
But I have a little poblem. After I properly modified the "platform dependent" section with correct SPI and chip select pin, I tryied to compile. I obtained an error about windows.h and tchar.h, included in file integer.h. But in integer.h I see the ifdef, and I want compile the "embedded" section, not the windows section. If I try to delete the ifdef, I obtained this error: " ';' expected but 'fs_type' found ". This come from typedef struct of ff.h.
On the internet there are project with identical structure, and it works perfectly; I only changed the SPI and chip select, and it doesn't work.
I attach my whole project. Anyone have some ideas?
 

Attachments

  • prova PIC32 fatFS.zip
    125.4 KB · Views: 78

Finally I have found what I *think* might be the problem you are having.
However it really would have been nice to know the actual source file, ine number and full error message to help track this down.
I *think* you are trying to compile the "ff.c" file which include the ff.h which, as you say, includes the integer.h file.
That type of error often occurs where a typedef is missing. the first reference to 'fs_type' I can see is in the FATFS struct in the ff.h file where it is declared to be of type "BYTE".
BYTE is a typedef of 'unsigned char' declared in "integer.h". However looking at that, I can't see how it would NOT be used as long as you do not have a "_WIN32" symbol defined.
I'm not clear what you have done when you say you removed the "#ifdef" - does that mean you removed the whole section to the matching "#else" and also the matching "#endif"? If so then you should have been left with the typedef in the "integer.h" file and all should have been well.
Susan
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top