PIC related Website

General discussion on mikroPascal PRO for dsPIC30/33 and PIC24.
Author
Message
Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#31 Post by Dany » 02 Aug 2012 19:37

2012-08-02: Changes are made to the "Fat32.." libraries: (see http://www.libstock.com/projects/view/58/fat or http://www.rosseeld.be/DRO/PIC/index.htm#fat_units.)

Fat32:
* Added the following routines:
Fat32_Read_File_Sector
Fat32_Replace_File_Sector
Fat32_Write_Sector
Fat32_Get_File_Size_Sectors
Fat32_CopyFile

Fat32_2:
* Uses only one SectorBuffer now: avoids writing conflicts in the same directory area. Saves a lot of ram when more than one file is handled.
* The routine "Fat32_Write_File_Sector" has been renamed into "Fat32_Replace_File_Sector" (more appropriate)
* The routine "Fat32_Write_Sector" has been added (same as "Fat32_WriteBuffer" but for whole sectors only).

2012-08-05:

Fat32 and Fat32_2:
Added the routines "Fat32_RmDir_All", "Fat32_Delete_All" and "Fat32_Delete_Files"
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#32 Post by yo2lio » 26 Aug 2012 09:45

Hello Dany,

I have a question: Did you know what is the maximum speed(KB/sec) to read some files from SDCARD, FAT32?
Let's say: MCU 16bit at 16MIPS, SPI 8Mbps, 10 files, total size of files 100KB.

Did you made this test before?
I want to put WEB page files on SD... but must be fast...
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#33 Post by Dany » 26 Aug 2012 11:32

yo2lio wrote:Hello Dany,

I have a question: Did you know what is the maximum speed(KB/sec) to read some files from SDCARD, FAT32?
Let's say: MCU 16bit at 16MIPS, SPI 8Mbps, 10 files, total size of files 100KB.

Did you made this test before?
I want to put WEB page files on SD... but must be fast...
Hi Yo2Lio,

No, I did not do some speed measurements yet. If you want I will do some. Coming soon.

What Fat version will you use? Fat32 or Fat32_2?

Anyway, I think you can gain some speed by using mE's Fat32 library, because it does not support long filenames. I know that this costs some time (and card space).
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#34 Post by yo2lio » 26 Aug 2012 11:38

Dany wrote:
What Fat version will you use? Fat32 or Fat32_2?
I will use FAT32. Thanks! Is not rush... I will made this tests also...
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#35 Post by Dany » 27 Aug 2012 17:11

yo2lio wrote:
Dany wrote:
What Fat version will you use? Fat32 or Fat32_2?
I will use FAT32. Thanks! Is not rush... I will made this tests also...
Hi Janni, I have some speed information for you.

Environment: P14FJGA002, running at 32 Mhz clock (8 Khz * 4), SPI clock is 8 Mhz, 4 GB "Integral" card.

6 tests were done where possible:

0: raw reading via the Fat32_Dev_Write_Sector routine, with addition of some small overhead: the buffer copied.
This is a reading NOT done via Fat32, so can only be used with swapfiles.
1: Reading via Fat32, 10 files of 10Kb each, buffer of 512 bytes
2: same as 1, but buffer of 10 bytes
3: same as 1 but with special "sector read" routine (only for Fat32 and Fat32_2)
4: Reading via Fat32, one file of 100K, buffer of 10 bytes
5: Same as 4, but buffer of 512 bytes

The results (in kByte/s):

Code: Select all

 Fat32_Library (mE),     Fat32,       Fat32_2
0:  158                  158           158
1:  121                  102           96
2:  96                   85            80
3:  --                   151           151
4:  101                  76            72
5:  128                  90            85
Last edited by Dany on 28 Aug 2012 09:16, edited 1 time in total.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#36 Post by yo2lio » 27 Aug 2012 17:22

Thank you very much Dany!
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#37 Post by yo2lio » 27 Aug 2012 19:56

Hi Dany,

In my opinion, the library is slow...
I optimized the SDMMC library, I use SPI2, you can change this with find and replace for SPI2...
Now, you can read one sector/ms... with SPI at 8MHz.
Can you test again with my code?

This is the library:

Code: Select all

unit SDMMC_SPI2;

function SDMMC_Init : boolean;
function SDMMC_ReadSector(Sector : dWord; var MMC_Buffer : array[512] of byte) : boolean;
function SDMMC_WriteSector(Sector : dWord; var MMC_Buffer : array[512] of byte) : boolean;
function SDMMC_ReadCsd(var data_for_registers : array[16] of byte) : boolean;
function SDMMC_ReadCid(var data_cid : array[16] of byte) : boolean;

const   CMD0  = $40 + 0;     // GO_IDLE_STATE
        CMD1  = $40 + 1;     // SEND_OP_COND
        CMD8  = $40 + 8;     // SEND_IF_COND
        CMD9  = $40 + 9;     // SEND_CSD
        CMD10 = $40 + 10;    // SEND_CID
        CMD12 = $40 + 12;    // STOP_TRANSMISSION
        CMD16 = $40 + 16;    // SET_BLOCKLEN
        CMD17 = $40 + 17;    // READ_SINGLE_BLOCK
        CMD18 = $40 + 18;    // READ_MULTIPLE_BLOCK
        CMD23 = $40 + 23;    // SET_BLOCK_COUNT
        CMD24 = $40 + 24;    // WRITE_BLOCK
        CMD25 = $40 + 25;    // WRITE_MULTIPLE_BLOCK
        CMD41 = $40 + 41;    // SEND_OP_COND (ACMD)
        CMD55 = $40 + 55;    // APP_CMD
        CMD58 = $40 + 58;    // READ_OCR

        TimeOutLimit = 10000;             // Set timeout limit based on clock

        sdMMC    = 1;                          // Multi Media Card (MMC)
        sdSD     = 2;                          // Secure Digital Card (SD)
        sdSDHC   = 4;                          // High Capacity Secure Digital Card (SDHC)

var SDMMC_CS : sbit; sfr; external;
    SDMMC_CS_dir : sbit; sfr; external;
    cardtype : byte;

implementation

var R18 : byte;

procedure SDMMC_Write(tx_data : byte);
begin
  asm
    MOV SPI2BUF,W0
  end;
  while SPI2STAT.1 = 1 do ;
  SPI2BUF := tx_data;
  while SPI2STAT.0 = 0 do ;
  asm
    MOV SPI2BUF,W0
  end;
end;

procedure SDMMC_Read;
begin
  asm
    MOV SPI2BUF,W0
  end;
  while SPI2STAT.1 = 1 do ;
  asm
    SETM SPI2BUF
  end;
  while SPI2STAT.0 = 0 do ;
  R18 := SPI2BUF;
end;

function SeekResponse(Required : Byte) : Byte;
var Index : Word;
begin
  Index := 0;
  while Index < $FFFF do
    begin
      SDMMC_Read;
      result := R18;
      if result = Required then break;
      inc(Index);
    end;
end;

function SendCmd(Cmd : Byte; Arg : dWord) : Byte;
var CRC,index : Byte;
begin
  if SeekResponse($FF) <> $FF then
    begin
      result := $FF; // wait for ready
      exit;
    end;
  SDMMC_Write(Cmd);             // Command
  SDMMC_Write(Highest(Arg));    // Argument[31..24]
  SDMMC_Write(Higher(Arg));     // Argument[23..16]
  SDMMC_Write(Hi(Arg));         // Argument[15..08]
  SDMMC_Write(Lo(Arg));         // Argument[07..00]
  CRC := $FF;                                   // Default CRC byte
  if Cmd = CMD0 then CRC := $95                           // CRC for CMD0($0)
  else if Cmd = CMD8 then CRC := $87;                           // CRC for CMD8($1AA)
  SDMMC_Write(CRC);
  Index := 0;
  while Index < 100 do
    begin                                   // Receive command response
      inc(index);
      SDMMC_Read;
      result := R18;
      if (result and $80) = 0 then break;   // Wait for a valid response in timeout of 100 attempts
    end;
end;

function SDMMC_ReadSector(Sector : dWord; var MMC_Buffer : array[512] of byte) : boolean;
var TimeOut : Byte;
begin
  result := false;
  if cardtype = 0 then exit;
  TimeOut := 0;
  if (cardtype and $04) = 0 then Sector := Sector shl 9; // MMC or SD - byte addressing (SDHC use block addressing)
  while result = false do
    begin
      SDMMC_CS := 0;
      delay_us(1);
      if SendCmd(CMD17, Sector) = $00 then      // Send Cmd 17
        if SeekResponse($FE) = $FE then         // Read start token
          begin
            asm
              PUSH W7
              PuSH W8
            end;
            W7 := @MMC_Buffer;
            W8 := 0;
            while true do                            // Read data block
              begin
                asm
                  MOV SPI2BUF,W0
                end;
                while SPI2STAT.1 = 1 do ;
                asm
                  SETM SPI2BUF
                end;
                while SPI2STAT.0 = 0 do ;
                asm
                  MOV SPI2BUF,W0
                  MOV.B W0,[W7++]
                end;
                Inc(W8);
                if W8.9 <> 0 then break;
              end;
            asm
              POP W8
              POP W7
            end;
            SDMMC_Read;                        // Read dummy CRC to conclude data block
            SDMMC_Read;
            result := true;                           // Read completed successfully
          end;
      SDMMC_CS := 1;
      delay_us(1);
      SDMMC_Read;                              // Clock SD/MMC to complete read
      if Inc(TimeOut) > 10 then break;
    end;
end;

function SDMMC_WriteSector(Sector : dWord; var MMC_Buffer : array[512] of byte) : boolean;
var Response : Byte;
    TimeOut : Byte;
begin
  result := false;
  if cardtype = 0 then exit;
  TimeOut := $00;
  if (cardtype and $04) = 0 then Sector := Sector shl 9; // MMC or SD - byte addressing (SDHC use block addressing)
  while result = false do
    begin
      SDMMC_CS := 0;
      delay_us(1);                            // Send Cmd 24
      if SeekResponse($FF) = $FF then    // Wait for ready
        if SendCmd(CMD24, Sector) = $00 then
          begin
            SDMMC_Write($FE);                // Write start token
            asm
              PUSH W7
              PuSH W8
            end;
            W7 := @MMC_Buffer;
            W8 := 0;
            while true do                            // Read data block
              begin
                asm
                  MOV SPI2BUF,W0
                end;
                while SPI2STAT.1 = 1 do ;
                asm
                  MOV.B [W7++],W0
                  MOV W0,SPI2BUF
                end;
                while SPI2STAT.0 = 0 do ;
                asm
                  MOV SPI2BUF,W0
                end;
                Inc(W8);
                if W8.9 <> 0 then break;
              end;
            asm
              POP W8
              POP W7
            end;
            SDMMC_Read;                // Send dummy CRC to conclude data block
            SDMMC_Read;
            SDMMC_Read;
            Response := R18;     // Data response token
            Response := Response and $1F;
            if Response = $05 then result := true;
          end;
      SDMMC_CS := 1;
      delay_us(1);
      SDMMC_Read;                      // Complete SPI transaction
      if Inc(TimeOut) > 10 then break;
    end;
end;

function SDMMC_ReadCid(var data_cid : array[16] of byte) : boolean;
var i : byte;
  begin
    result := false;
    SDMMC_CS := 0;
    delay_us(1);
    //--- read_CID command
    if SendCmd(CMD10, 0) = 0 then
    if SeekResponse($FE) = $FE then         // Read start token
      begin
        // read 16-byte CID
        for i := 0 to 15 do
          begin
            SDMMC_Read;
            data_cid[i] := R18;
          end;
        // read 2-byte CRC and discard it
        SDMMC_Read;
        SDMMC_Read;
        result := true;
      end;
    SDMMC_CS := 1;
    delay_us(1);
  end;

function SDMMC_ReadCsd(var data_for_registers : array[16] of byte) : boolean;
var i : byte;
  begin
    result := false;
    SDMMC_CS := 0;
    delay_us(1);
    //--- read_CID command
    if SendCmd(CMD9, 0) = 0 then
    if SeekResponse($FE) = $FE then         // Read start token
      begin
        // read 16-byte CID
        for i := 0 to 15 do
          begin
            SDMMC_Read;
            data_for_registers[i] := R18;
          end;
        // read 2-byte CRC and discard it
        SDMMC_Read;
        SDMMC_Read;
        result := true;
      end;
    SDMMC_CS := 1;
    delay_us(1);
  end;

function Cmd5541(BitSet : Boolean) : Byte;
begin
  result := SendCmd(CMD55, 0);
  if result > 1 then Exit
  else
    begin
      if BitSet <> 0 then result := SendCmd(CMD41, $40000000)
      else result := SendCmd(CMD41, 0);
    end;
end;

function SDMMC_Init_ : boolean;
var Index : Word;
    OCR : array[4] of Byte;
begin
  Clrwdt;
  result := true;
  cardtype := 0;
  SDMMC_CS := 1;                                        // Pull CS high
  delay_us(1);
  SDMMC_CS_dir := 0;
  Index := 0;
  while Index < 20 do                                        // Clock SD for min 80 cycles
    begin
      SDMMC_Read;
      inc(Index);
    end;
  SDMMC_CS := 0;  // Pull CS low
  delay_us(1);
  if SendCmd(CMD0, 0) = $01 then                // Send Cmd 0 - enter idle state
    if SendCmd(CMD8, $01AA) = $01 then             // SDC Version 2+
      begin
        for Index := 0 To 3 do
          begin
            SDMMC_Read;
            OCR[Index] := R18;
          end;
        if (OCR[2] = $01) and (OCR[3] = $AA) then           // SD Vdd range of 2.7 - 3.6 volts
          begin
            Index := TimeOutLimit;
            while Index > 0 do
              begin
                dec(Index);
                if Cmd5541(True) = 0 then break;
              end;
            if Index > 0 then                            // Cmd 55/41 successful with HCS bit set
              if SendCmd(CMD58, 0) = 0 then     // Send Cmd 58
                begin
                  for Index := 0 To 3 do
                    begin
                      SDMMC_Read;
                      OCR[Index] := R18;
                    end;
                  // CCS[30] bit in the OCR set
                  if (OCR[0] and $40) > 0 then cardtype := sdSDHC              // Init successful - SDHC (3)
                  else cardtype := sdSD;                // Init successful - SD (2)
                end;
          end
      end
    else                                               // SD Version 1 or MMC
      begin
        if Cmd5541(False) <= 1 then
          begin
            cardtype := sdSD;                         // Init successful - SD (2)
            Index := TimeOutLimit;
            while Index > 0 do
              begin
                dec(Index);
                if Cmd5541(True) = 0 then break;
              end;
          end         // Wait for leaving idle state
        else
          begin
            cardtype := sdMMC;                        // Init successful - MMC (1)
            Index := TimeOutLimit;
            while Index > 0 do
              begin
                dec(Index);
                if SendCmd(CMD1, 0) = 0 then break;    // Wait for leaving idle state
              end;
          end;
      end;
  if Index = 0 then result := false
  else SendCmd(CMD16, $0200);
  SDMMC_CS := 1;
  delay_us(1);
  SDMMC_Read;    // Clock SD/MMC to complete
end;

function SDMMC_Init : boolean;
var Index : byte;
begin
  Index := 0;
  while Index < 5 do
    begin
      result := SDMMC_Init_;
      if cardtype <> 0 then break;
      inc(index);
    end;
  if cardtype <> 0 then result := true
  else result := false;
end;

end.
Last edited by yo2lio on 28 Aug 2012 09:57, edited 1 time in total.
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#38 Post by Dany » 28 Aug 2012 09:15

yo2lio wrote:Can you test again with my code?
Ok, we'll do. :D
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#39 Post by yo2lio » 28 Aug 2012 09:18

Thanks!
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#40 Post by yo2lio » 28 Aug 2012 09:58

Dany, I found a bug in my code, I corrected this...
Please use corrected code. Thanks and sorry for trouble...
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#41 Post by Dany » 28 Aug 2012 10:19

Hi Yo2Lio,

Bad news: using the new version of SDMMC_SPI2 makes the pic restart continously. The older version I used (attached) of SDMMC_SPI2 works perfectly...
Attachments
_SDMMC_SPI2.zip
(2.5 KiB) Downloaded 189 times
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#42 Post by yo2lio » 28 Aug 2012 10:22

OK, did you use corrected code?
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#43 Post by Dany » 28 Aug 2012 10:22

yo2lio wrote:OK, did you use corrected code?
Still have to try the corrected code... :oops:
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

Dany
Posts: 3854
Joined: 18 Jun 2008 11:43
Location: Nieuwpoort, Belgium
Contact:

Re: PIC related Website

#44 Post by Dany » 28 Aug 2012 10:58

Hi Yo2lio, it works fine now!.

The speeds are indeed significantly higher:

method (with Fat32) in Kb/s

0: 227 with buffercopy, 263 without buffercopy (only read activities)
1: 116
2: 95
3: 184
4: 99
5: 123

So, the raw speed seems to be 263 kbytes/second. Is that what you expected?
Last edited by Dany on 28 Aug 2012 13:16, edited 1 time in total.
Kind regards, Dany.
Forget your perfect offering. There is a crack in everything, that's how the light gets in... (L. Cohen)
Remember when we were young? We shone like the sun. (David Gilmour)

yo2lio
Posts: 1878
Joined: 19 Sep 2006 12:57
Location: Romania, Arad City
Contact:

Re: PIC related Website

#45 Post by yo2lio » 28 Aug 2012 11:06

Thanks Dany!
Best regards, Florin Andrei Medrea.

http://www.microelemente.ro/
http://www.microelemente.ro/produse-si-servicii/
http://www.microelemente.ro/custom-software/

mail : florin@microelemente.ro

Post Reply

Return to “mikroPascal PRO for dsPIC30/33 and PIC24 General”