| View previous topic :: View next topic | 
	
	
		| Author | Message | 
	
		| -Terppa- 
 
 
 Joined: 08 Jan 2018
 Posts: 60
 Location: Finland
 
 
			    
 
 | 
			
				| RAW microSD |  
				|  Posted: Mon Aug 07, 2023 6:52 am |   |  
				| 
 |  
				| 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: 9588
 Location: Greensville,Ontario
 
 
			    
 
 |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 07, 2023 9:37 am |   |  
				| 
 |  
				| 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: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 1:58 am |   |  
				| 
 |  
				| 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
    |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 2:22 am |   |  
				| 
 |  
				| 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: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 6:14 am |   |  
				| 
 |  
				| 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: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 7:31 am |   |  
				| 
 |  
				| 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: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 8:48 am |   |  
				| 
 |  
				| 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: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 10:07 am |   |  
				| 
 |  
				| 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: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 10:25 am |   |  
				| 
 |  
				| It is my bad.. Accidentally i wired up MicroSD chip select to my board "heartbeat" led   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: 19966
 
 
 
			    
 
 |  | 
	
		|  | 
	
		| -Terppa- 
 
 
 Joined: 08 Jan 2018
 Posts: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Aug 08, 2023 12:56 pm |   |  
				| 
 |  
				| Thank you very much those links! I’ll check them out. |  | 
	
		|  | 
	
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Wed Aug 09, 2023 3:35 am |   |  
				| 
 |  
				| 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: 60
 Location: Finland
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Aug 18, 2023 12:29 am |   |  
				| 
 |  
				| 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.
 
 | 
 |  | 
	
		|  | 
	
		|  |