CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

RAW microSD

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

RAW microSD
PostPosted: Mon Aug 07, 2023 6:52 am     Reply with quote

Hello!
What is the simplest way to add MicroSD card to handle large amount of data?
I don't need any File Allocation Table just raw data.
That's because i can dump necessary data over uart.
What kind of drivers i need?

I'm already read part of this:
https://www.ccsinfo.com/forum/viewtopic.php?t=53787

but every line talks FATxx- systems, but i don't need them.

I have 3v3- processor so i don't need any level translators.

Thank you for pushing a right direction.
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 07, 2023 7:45 am     Reply with quote

https://www.sparkfun.com/products/13712

is one simple, cheap possible solution.
I've never used it but it seems 'easy' !!
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Mon Aug 07, 2023 9:37 am     Reply with quote

The SD can just be added as a simple SPI device.
Key things:

Levels (already covered)
Power. The SD draws a surprising spike of power when it writes. Needs
a really good reservoir capacitor close by it's supply pins. Make sure
your supply can handle this spike.
Wiring. You need pull up resistors on CS, DATA_IN, DATA_OUT, DAT1, &
DAT2.
SDO on PIC to DATA_IN.
SDI on PIC to DATA_OUT.
SCK to SCLK
and some other suitable pin to CS.

You are looking at stuff you don't need to get involved with. As you say
those drivers are to handle FAT. The third link down at the start there is
to stuff about the MMC SD libraries. These are the only part you need.
mmc_spi.c
The only complexity with these is the speed switching. The point about
the SPI SD interface is it must start at a slow rate, negotiate how it
is going to talk to the card, and then switch up to the high speed.
The functions here handle reading a block, writing a block, etc. etc..
Just what you need. You do need to call mmc_init, since this actually
configures the SD to read/write on the SPI lines, and changes the speed.
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 1:58 am     Reply with quote

temtronic:
Thank you for your idea! It is nice little module, but final product has very small and even that is too big.

Ttelmah:
Thank you for info!
I have now driver called "mmcsd.c" (CCSC forum)

MCU is DSpic33ep512mc204

Now it is time to start coding and wondering Smile Shocked
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 2:22 am     Reply with quote

You should not need to pull any driver from the forum for this. The
mmcsd driver comes with the the compiler (drivers directory).
However you will have a slight problem. Your chip is later than this driver
was written for. So for SPI2 you need to add #pin_select statements, and
setup the spi as described here at the top of the forum (pin_select thread).
Then when the speed change has to occur, simply use the spi_speed
command instead of trying to tweak as shown in the driver.
So setup as:
Code:

#pin_select SCK2OUT = your_pin
#pin_select SCK2IN = your_pin
#pin_select SDO2 = your_pin
#pin_select SDI2 = your_pin
#use spi(SPI2,BITS=8,MODE=0, BAUD=400000, stream=mmcsd_spi)
#define MMCSD_SPI_XFER spi_xfer(mmcsd_spi, x)

//Then load mmcsd.c
//on your chip only SPI2 uses PPS

For SPI1, just remove the pin_select lines, and use the hardware SPI1 pins.

Then in the mmcsd code where it changes speed:
Code:

/// this would be a good time to set a higher clock speed, 20MHz
#if defined(MMCSD_SPI_HW)
   #if (getenv("CLOCK") <= 80000000)
      #define MMC_SPI_CLK_DIV SPI_CLK_DIV_4
   #else
      #if defined(SPI_CLK_DIV_8)
         #define MMC_SPI_CLK_DIV SPI_CLK_DIV_8
      #else
         #define MMC_SPI_CLK_DIV SPI_CLK_DIV_16
      #endif
   #endif
   #error/warning the next line will only work if using SPI1
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | MMC_SPI_CLK_DIV);
#endif

//Replace this with:

spi_speed(mmc_sd, 8000000);


Select the speed to suit what your hardware works comfortably with.
8MHz is usually fine. Some chips and with short lines will happily go
to 12MHz or more. Your chip supports 15Mbps max, but you need
well laid out short lines for this to work well.

Because you ar not using FAT, you don't have to worry about the MBR
stuff.

One comment, design however you are doing your I/O to the card to
avoid repeatedly using the same spot. So don't have the card using
something like a counter held at a fixed location at the bottom of
memory, and changing this every time you add a record. Try to think
of a way of flagging blocks as in-use with a single marker at the end
of each block. SD's are good compared to old memories in terms of
their write life, but not perfect. You still get things like SD security
cameras, killing the cards after a couple of years.
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 6:14 am     Reply with quote

Thank you very much Mr. Ttelmah for your help!

There is something progress:

CPU: DSPic33ep512mc204 (SPI1)

SDcard adapter wiring:
(4k7 is 4.7k resistor pull-up to 3v3)
Code:

CD:4k7
DAT1:4k7
DAT0/DO:4k7    -> (A9)
CMD/DI:4k7   -> (A4)
CLK:4k7      -> (C3)
DAT2:4k7
CAT3/CS:4k7     -> (B13)


CPU setup
Code:

#define SYSTEM_CLOCK      140M
#define MYCRYSTAL         16M

#device ICSP=1
#device ADC=10
//#device PSV=16         
//#build (STACK=512)
#device PASS_STRINGS=IN_RAM
//clear all RAM variables:
#ZERO_RAM
//skip list file (normally list is useless but may have handy in debug)
#nolist

//EXTERNAL clock setup DSPIC
#ifdef USEEXTERNALCLOCK
#warning CONFIRM YOUR EXTERNAL CLOCK SETUP
#fuses NOWDT                    //No Watch Dog Timer
#fuses CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
//#fuses ALTI2C1               //I2C1 mapped to ASDA1/ASCL1 pins
//#fuses ALTI2C2               //I2C2 mapped to ASDA2/ASCL2 pins
#fuses NOJTAG                   //JTAG disabled
#fuses PLLWAIT
#fuses CKSFSM
#fuses PR_PLL
#fuses PLLWAIT
#use delay(clock=SYSTEM_CLOCK,crystal=MYCRYSTAL)


SPI1 setup:
Code:

#ifndef MMCSD_SPI_XFER
   #use SPI(MASTER, SPI1, BITS=8, MSB_FIRST, MODE=0, baud=400000, stream=mmcsd_spi, FORCE_HW)
   #define MMCSD_SPI_XFER(x)  spi_xfer(mmcsd_spi, x)
#endif


There is something wrong.. Init function never get's end?
Code:

MMCSD_err mmcsd_init()
{
   unsigned int8
      i,
      r1;

#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\r\n\n\rTrying to init MicroSD module..");
#endif

   g_CRC_enabled = TRUE;
   g_mmcsdBufferAddress = 0;
.
.
.
   /* set block length to 512 bytes */
   mmcsd_select();
   r1 = mmcsd_set_blocklen(MMCSD_MAX_BLOCK_SIZE);
   if(r1 != MMCSD_GOODEC)
   {
#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rmmcsd_set_blocklen 0x%x",r1);
#endif
      mmcsd_deselect();
      return r1;
   }


It returns that place and print out:
mmcsd_set_blocklen 0x80

Something missing in init? If i pull out card, it returns: mmcsd_go_idle_state
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 7:31 am     Reply with quote

You are not showing that you are doing the modification to the init function.
Open mmcsd.c in the IDE.
edit it as I show.
Then select 'save', and when the IDE says this is a supplied file, select
'save with project'.
Then in the project, where you open this change the include to use ""
around the filename instead of <>.
Close your project, re-open, and make sure the copy being shown in the
project is the edited version.

I suspect you are not using the edited version in the actual compile.

The original divisor change in the supplied CCS file won't work with the
SPI on your chip.
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 8:48 am     Reply with quote

Oh, i'm sorry files in main.c

Code:

#include "hardwareprofile.h" //CPU setup
#include "globals.h" //nothing for MicroSD
#include "mmcsd.c" //copy of CCSC forum


Only edited part in mmscsd.c added debug lines, SPI1- setup.

Whole init function for MicroSD:
Code:

//________________________________________________________________________________________________________
MMCSD_err mmcsd_init()
{
   unsigned int8
      i,
      r1;

#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\r\n\n\rTrying to init MicroSD module..");
#endif

   g_CRC_enabled = TRUE;
   g_mmcsdBufferAddress = 0;

  #if defined(MMCSD_PIN_SCL)
   output_drive(MMCSD_PIN_SCL);
  #endif
  #if defined(MMCSD_PIN_SDO)
   output_drive(MMCSD_PIN_SDO);
  #endif
   output_drive(MMCSD_PIN_SELECT);
  #if defined(MMCSD_PIN_SDI)
   output_float(MMCSD_PIN_SDI);
  #endif

   mmcsd_deselect();
   delay_ms(15);
     
   /* begin initialization */
   i = 0;
   do
   {
      delay_ms(1);
      mmcsd_select();     
      r1=mmcsd_go_idle_state();
      mmcsd_deselect();
      i++;

      if(i==0xff)
      {
#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rmmcsd_go_idle_state");
#endif
         mmcsd_deselect();
         return r1;
      }
   } while(!bit_test(r1, 0));

   i = 0;
   do
   {
      delay_ms(1);
      mmcsd_select();
      r1=mmcsd_send_op_cond();
      mmcsd_deselect();
      i++;

      if(i==0xff)
      {
#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rmmcsd_send_op_cond");
#endif
         mmcsd_deselect();
         return r1;
      }
   } while(r1 & MMCSD_IDLE);

/* figure out if we have an SD or MMC */
   mmcsd_select();
   r1=mmcsd_app_cmd();
   r1=mmcsd_sd_send_op_cond();

   mmcsd_deselect();

   /* an mmc will return an 0x04 here */
   if(r1==0x04)
      g_card_type = MMC;
   else
      g_card_type = SD;

   /* set block length to 512 bytes */
   mmcsd_select();
   r1 = mmcsd_set_blocklen(MMCSD_MAX_BLOCK_SIZE);
   if(r1 != MMCSD_GOODEC)
   {
#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rCard type: %u",g_card_type);
   fprintf(MMCSDDEBUG,"\n\rmmcsd_set_blocklen: %u/%lu, return",r1,MMCSD_MAX_BLOCK_SIZE);
#endif
      mmcsd_deselect();
      return r1;
   }
   mmcsd_deselect();

//MOD 080823
//ORIGINAL:
/*
/// this would be a good time to set a higher clock speed, 20MHz
#if defined(MMCSD_SPI_HW)
   #if (getenv("CLOCK") <= 80000000)
      #define MMC_SPI_CLK_DIV SPI_CLK_DIV_4
   #else
      #if defined(SPI_CLK_DIV_8)
         #define MMC_SPI_CLK_DIV SPI_CLK_DIV_8
      #else
         #define MMC_SPI_CLK_DIV SPI_CLK_DIV_16
      #endif
   #endif
   #error/warning the next line will only work if using SPI1
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_XMIT_L_TO_H | MMC_SPI_CLK_DIV);
#endif
*/

//FOR DSPIC33EP512MC204 USE
//spi_speed(mmcsd_spi, 8000000);
spi_speed(mmcsd_spi, 8000000, SYSTEMCLKSPD);

   /* turn CRCs off to speed up reading/writing */
   mmcsd_select();
   r1 = mmcsd_crc_on_off(0);
   if(r1 != MMCSD_GOODEC)
   {
#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rmmcsd_crc_on_off: 0x%x",r1);
#endif
      mmcsd_deselect();
      return r1;
   }
   mmcsd_deselect();

   r1 = mmcsd_load_buffer();

   g_mmcsdPartitionOffset = 0;
   mmcsd_check_part(0x1EE);
   mmcsd_check_part(0x1DE);
   mmcsd_check_part(0x1CE);
   mmcsd_check_part(0x1BE);

#ifdef USEMMCSDDEBUG
   fprintf(MMCSDDEBUG,"\n\rmmmcsd_load_buffer");
#endif

   return r1;
}

It never reached end.. always returns "mmcsd_set_blocklen: 128"
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 10:07 am     Reply with quote

OK.

Is this a standard microSD card???
Problem is that the card is reporting that it's maximum block length is 128
bytes. The driver default is 512 bytes, which every SD card is meant to
support!....
The SD spec has the block lengths supported as 512, 1024 & 2048 bytes.
128, would only allow a maximum size of 512Kbyte.
The init is dropping out because the card is saying it can't accept the
512byte default length.
Or are you setting the block size to 128. in the load?. If so, change it
back to the default. The cards can't use a block length below 512.
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 10:25 am     Reply with quote

It is my bad.. Accidentally i wired up MicroSD chip select to my board "heartbeat" led Embarassed
It is fixed now and now i get message to terminal
"Trying to init MicroSD module..
mmcsd_send_op_cond" and return.

Without card message is same as previous:
"Trying to init MicroSD module..
mmcsd_go_idle_state
"

MicroSD card type is "Transcend, 16GB, SDHC" and circled number which says 10
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 11:08 am     Reply with quote

Transend,

Look at this thread:
[url]
https://stackoverflow.com/questions/955587/initialization-of-a-microsd-card-using-an-spi-interface
[/url]

Pause after sending the first command before trying to initialise.
A lot of the SDHC cards have this oddity.

This is also documented here:
[url]
https://community.nxp.com/t5/Vybrid-Processors/Power-up-timing-of-some-SDHC-cards/m-p/279285
[/url]

Wait for perhaps half a second before trying to talk to the card.
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Tue Aug 08, 2023 12:56 pm     Reply with quote

Thank you very much those links! I’ll check them out.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Wed Aug 09, 2023 3:35 am     Reply with quote

The original power up specifications in the SD card specs say that
we need to allow 1mSec and 74 clock cycles after power on. However
a lot of the SDHC cards have their own much slower timings. For example
Sandisk specifically require 500mSec on their HC cards for this.
The driver defaults to using the SD spec timing, so a lot of the HC cards
will not respond correctly unless you lengthen this time.
A 'caveat'....
-Terppa-



Joined: 08 Jan 2018
Posts: 59
Location: Finland

View user's profile Send private message

PostPosted: Fri Aug 18, 2023 12:29 am     Reply with quote

Some progress. Now i have different types of SD card's. Brands are Transcend, Hama, Kingston and Biltema. Size are 16Gb to 32Gb.

Mr. Ttelmah suggested "dummy" data function and after digging, coding and testing i'll get this for all cards:
Code:

Initialize SDHC..
CSD_STRUCTURE: 0
TAAC: E
NSAC: 0
TRAN_SPEED: 32
CCC: 5B5
READ_BL_LEN: 9
READ_BL_PARTIAL: 0
WRITE_BLK_MISALIGN: 0
READ_BLK_MISALIGN: 0
DSR_IMP: 0
C_SIZE: 1
VDD_R_CURR_MIN: 6
VDD_R_CURR_MAX: 3
VDD_W_CURR_MIN: 5
VDD_W_CURR_MAX: 2
C_SIZE_MULT: 2
ERASE_BLK_EN: 1
SECTOR_SIZE: 7F
WP_GRP_SIZE: 0
WP_GRP_ENABLE: 0
R2W_FACTOR: 2
WRITE_BL_LEN: 9
WRITE_BL_PARTIAL: 0
FILE_FORMAT_GRP: 0
COPY: 0
PERM_WRITE_PROTECT: 0
TMP_WRITE_PROTECT: 0
FILE_FORMAT: 0
CRC: 57
mmcsd_print_csd:0x00
Manufacturer ID: 27
OEM/Application ID: PH
OEM/Application ID: SD16G
Product Revision: 60
Serial Number: 00020
Manufacturer Date Code: 167
CRC-7 Checksum: 4F
mmcsd_print_cid:0x00

MicroSD init ready.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group