| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				| PIC18F47J53 CCS C Compiler 5.090 mmcsd.c library issue |  
				|  Posted: Fri Jul 31, 2020 9:57 am |   |  
				| 
 |  
				| Hi, 
 I have defined a SPI on this pins in order to manage a MicroSD:
 
  	  | Code: |  	  | #PIN_SELECT SDO2=PIN_D2 #PIN_SELECT SDI2=PIN_D3
 #PIN_SELECT SCK2=PIN_D4
 
 #define MMCSD_PIN_SCK      PIN_D4 //o
 #define MMCSD_PIN_MISO     PIN_D3 //i
 #define MMCSD_PIN_MOSI     PIN_D2 //o
 #define MMCSD_PIN_SELECT   PIN_D0 //o
 
 #ifndef MMCSD_SPI_HW
 #use spi(MASTER,SPI2, DI=MMCSD_PIN_MISO, DO=MMCSD_PIN_MOSI, CLK=MMCSD_PIN_SCK, BITS=8, MSB_FIRST, MODE=3, baud=400000)
 #endif
 
 | 
 I configure ports this way:
 
  	  | Code: |  	  | void config_port()
 {
 
 LATE = 0b00000000;
 PORTE = 0b00000000;
 LATD = 0b00001000;
 PORTD = 0b00001000;
 LATC = 0b00000000;
 PORTC = 0b00000000;
 LATB = 0b00001000;
 PORTB = 0b00001000;
 LATA = 0b00000000;
 PORTA = 0b00000000;
 set_tris_a(0b00100110);
 set_tris_b(0b11111011);
 set_tris_c(0b11111111);
 INTCON2 = 0b10000000;
 }
 
 | 
 When I go to DeepSleep I set :
 
  	  | Code: |  	  | output_low(PIN_D2);  //MOSI
 output_low(PIN_D3);  //MISO
 output_low(PIN_D4);  //SCK
 output_low(PIN_D0);  //CS
 
 | 
 But PIN_D4 during deepsleep remains high (3.3 V) and the MicroSD consumes about 2mA... Why??
 
 Please I need help for an important project.
 
 Regards,
 
 Marco
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jul 31, 2020 10:08 am |   |  
				| 
 |  
				| Because in Mode3, the SPI idles high. The pin is under the control of the SPI peripheral, and not available for normal I/O.
 
 The clock being high should not cause the card to consume extra current.
 This depends on how the card is initialised. You can program an SD to
 automatically sleep when the clock stops. However don't know how the
 default SD library sets things up.
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jul 31, 2020 10:13 am |   |  
				| 
 |  
				|  	  | Code: |  	  | /////////////////////////////////////////////////////////////////////////
 ////                           mmcsd_m.c                             ////
 ////                                                                 ////
 ////   This driver is a modified version of CCS C compiler mmcsd.c   ////
 ////   file, now it supports all types of cards: MMC, SD and SDHC.   ////
 ////                                                                 ////
 ////               https://simple-circuit.com/                       ////
 ////               contact@simple-circuit.com                        ////
 ////                                                                 ////
 /////////////////////////////////////////////////////////////////////////
 ////                                                                 ////
 ////    This is a low-level driver for MMC and SD cards.             ////
 ////                                                                 ////
 //// --User Functions--                                              ////
 ////                                                                 ////
 //// mmcsd_init(): Initializes the media.                            ////
 ////                                                                 ////
 //// mmcsd_read_byte(a, p)                                           ////
 ////  Reads a byte from the MMC/SD card at location a, saves to      ////
 ////  pointer p.  Returns 0 if OK, non-zero if error.                ////
 ////                                                                 ////
 //// mmcsd_read_data(a, n, p)                                        ////
 ////  Reads n bytes of data from the MMC/SD card starting at address ////
 ////  a, saves result to pointer p.  Returns 0 if OK, non-zero if    ////
 ////  error.                                                         ////
 ////                                                                 ////
 //// mmcsd_flush_buffer()                                            ////
 ////  The two user write functions (mmcsd_write_byte() and           ////
 ////  mmcsd_write_data()) maintain a buffer to speed up the writing  ////
 ////  process.  Whenever a read or write is performed, the write     ////
 ////  buffer is loaded with the specified page and only the          ////
 ////  contents of this buffer is changed.  If any future writes      ////
 ////  cross a page boundary then the buffer in RAM is written        ////
 ////  to the MMC/SD and then the next page is loaded into the        ////
 ////  buffer.  mmcsd_flush_buffer() forces the contents in RAM       ////
 ////  to the MMC/SD card.  Returns 0 if OK, non-zero if errror.      ////
 ////                                                                 ////
 //// mmcsd_write_byte(a, d)                                          ////
 ////  Writes data byte d to the MMC/SD address a.  Intelligently     ////
 ////  manages a write buffer, therefore you may need to call         ////
 ////  mmcsd_flush_buffer() to flush the buffer.                      ////
 ////                                                                 ////
 //// mmcsd_write_data(a, n, p)                                       ////
 ////  Writes n bytes of data from pointer p to the MMC/SD card       ////
 ////  starting at address a.  This function intelligently manages    ////
 ////  a write buffer, therefore if you may need to call              ////
 ////  mmcsd_flush_buffer() to flush any buffered characters.         ////
 ////  returns 0 if OK, non-zero if error.                            ////
 ////                                                                 ////
 //// mmcsd_read_block(a, s, p)                                       ////
 ////  Reads an entire page from the SD/MMC.  Keep in mind that the   ////
 ////  start of the read has to be aligned to a block                 ////
 ////  (Address % 512 = 0).  Therefore s must be evenly divisible by  ////
 ////  512.  At the application level it is much more effecient to    ////
 ////  to use mmcsd_read_data() or mmcsd_read_byte().  Returns 0      ////
 ////  if successful, non-zero if error.                              ////
 ////                                                                 ////
 //// mmcsd_write_block(a, s, p):                                     ////
 ////  Writes an entire page to the SD/MMC.  This will write an       ////
 ////  entire page to the SD/MMC, so the address and size must be     ////
 ////  evenly  divisble by 512.  At the application level it is much  ////
 ////  more effecient to use mmcsd_write_data() or mmcsd_write_byte().////
 ////  Returns 0 if successful, non-zero if error.                    ////
 ////                                                                 ////
 //// mmcsd_print_cid(): Displays all data in the Card Identification ////
 ////                     Register. Note this only works on SD cards. ////
 ////                                                                 ////
 //// mmcsd_print_csd(): Displays all data in the Card Specific Data  ////
 ////                     Register. Note this only works on SD cards. ////
 ////                                                                 ////
 ////                                                                 ////
 //// --Non-User Functions--                                          ////
 ////                                                                 ////
 //// mmcsd_go_idle_state(): Sends the GO_IDLE_STATE command to the   ////
 ////                        SD/MMC.                                  ////
 //// mmcsd_send_op_cond(): Sends the SEND_OP_COND command to the     ////
 ////                        SD. Note this command only works on SD.  ////
 //// mmcsd_send_if_cond(): Sends the SEND_IF_COND command to the     ////
 ////                        SD. Note this command only works on SD.  ////
 //// mmcsd_sd_status(): Sends the SD_STATUS command to the SD. Note  ////
 ////                     This command only works on SD cards.        ////
 //// mmcsd_send_status(): Sends the SEND_STATUS command to the       ////
 ////                       SD/MMC.                                   ////
 //// mmcsd_set_blocklen(): Sends the SET_BLOCKLEN command along with ////
 ////                        the desired block length.                ////
 //// mmcsd_app_cmd(): Sends the APP_CMD command to the SD. This only ////
 ////                   works on SD cards and is used just before any ////
 ////                   SD-only command (e.g. send_op_cond()).        ////
 //// mmcsd_read_ocr(): Sends the READ_OCR command to the SD/MMC.     ////
 //// mmcsd_crc_on_off(): Sends the CRC_ON_OFF command to the SD/MMC  ////
 ////                      along with a bit to turn the CRC on/off.   ////
 //// mmcsd_send_cmd(): Sends a command and argument to the SD/MMC.   ////
 //// mmcsd_get_r1(): Waits for an R1 response from the SD/MMC and    ////
 ////                  then saves the response to a buffer.           ////
 //// mmcsd_get_r2(): Waits for an R2 response from the SD/MMC and    ////
 ////                  then saves the response to a buffer.           ////
 //// mmcsd_get_r3(): Waits for an R3 response from the SD/MMC and    ////
 ////                  then saves the response to a buffer.           ////
 //// mmcsd_get_r7(): Waits for an R7 response from the SD/MMC and    ////
 ////                  then saves the response to a buffer.           ////
 //// mmcsd_wait_for_token(): Waits for a specified token from the    ////
 ////                          SD/MMC.                                ////
 //// mmcsd_crc7(): Generates a CRC7 using a pointer to some data,    ////
 ////                and how many bytes long the data is.             ////
 //// mmcsd_crc16(): Generates a CRC16 using a pointer to some data,  ////
 ////                and how many bytes long the data is.             ////
 ////                                                                 ////
 /////////////////////////////////////////////////////////////////////////
 ////        (C) Copyright 2007 Custom Computer Services              ////
 //// This source code may only be used by licensed users of the CCS  ////
 //// C compiler.  This source code may only be distributed to other  ////
 //// licensed users of the CCS C compiler.  No other use,            ////
 //// reproduction or distribution is permitted without written       ////
 //// permission.  Derivative programs created using this software    ////
 //// in object code form are not restricted in any way.              ////
 /////////////////////////////////////////////////////////////////////////
 
 #ifndef MMCSD_C
 #define MMCSD_C
 
 /////////////////////
 ////             ////
 //// User Config ////
 ////             ////
 /////////////////////
 
 #include <stdint.h>
 
 #PIN_SELECT SDO2=PIN_D2
 #PIN_SELECT SDI2=PIN_D3
 #PIN_SELECT SCK2=PIN_D4
 
 #define MMCSD_PIN_SCK      PIN_D4 //o
 #define MMCSD_PIN_MISO     PIN_D3 //i
 #define MMCSD_PIN_MOSI     PIN_D2 //o
 #define MMCSD_PIN_SELECT   PIN_D0 //o
 
 #ifndef MMCSD_SPI_HW
 #use spi(MASTER,SPI2, DI=MMCSD_PIN_MISO, DO=MMCSD_PIN_MOSI, CLK=MMCSD_PIN_SCK, BITS=8, MSB_FIRST, MODE=3, baud=400000)
 #endif
 
 ////////////////////////
 ////                ////
 //// Useful Defines ////
 ////                ////
 ////////////////////////
 
 enum MMCSD_err
 {MMCSD_GOODEC = 0,
 MMCSD_IDLE = 0x01,
 MMCSD_ERASE_RESET = 0x02,
 MMCSD_ILLEGAL_CMD = 0x04,
 MMCSD_CRC_ERR = 0x08,
 MMCSD_ERASE_SEQ_ERR = 0x10,
 MMCSD_ADDR_ERR = 0x20,
 MMCSD_PARAM_ERR = 0x40,
 RESP_TIMEOUT = 0x80};
 
 #define GO_IDLE_STATE 0
 #define SEND_OP_COND 1
 #define SEND_IF_COND 8
 #define SEND_CSD 9
 #define SEND_CID 10
 #define SD_STATUS 13
 #define SEND_STATUS 13
 #define SET_BLOCKLEN 16
 #define READ_SINGLE_BLOCK 17
 #define WRITE_BLOCK 24
 #define SD_SEND_OP_COND 41
 #define APP_CMD 55
 #define READ_OCR 58
 #define CRC_ON_OFF 59
 
 #define IDLE_TOKEN 0x01
 #define DATA_START_TOKEN 0xFE
 
 #define MMCSD_MAX_BLOCK_SIZE 512
 
 ////////////////////////
 ///                  ///
 /// Global Variables ///
 ///                  ///
 ////////////////////////
 
 uint8_t g_mmcsd_buffer[MMCSD_MAX_BLOCK_SIZE];
 
 int1 g_CRC_enabled;
 int1 g_MMCSDBufferChanged;
 
 uint32_t g_mmcsdBufferAddress;
 
 enum _card_type{MMC, SDSC, SDHC} g_card_type;
 
 /////////////////////////////
 ////                     ////
 //// Function Prototypes ////
 ////                     ////
 /////////////////////////////
 
 MMCSD_err mmcsd_init();
 MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr);
 MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr);
 MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr);
 MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr);
 MMCSD_err mmcsd_go_idle_state(void);
 MMCSD_err mmcsd_send_op_cond(void);
 MMCSD_err mmcsd_send_if_cond(uint8_t r7[]);
 MMCSD_err mmcsd_print_csd();
 MMCSD_err mmcsd_print_cid();
 MMCSD_err mmcsd_sd_status(uint8_t r2[]);
 MMCSD_err mmcsd_send_status(uint8_t r2[]);
 MMCSD_err mmcsd_set_blocklen(uint32_t blocklen);
 MMCSD_err mmcsd_read_single_block(uint32_t address);
 MMCSD_err mmcsd_write_single_block(uint32_t address);
 MMCSD_err mmcsd_sd_send_op_cond(void);
 MMCSD_err mmcsd_app_cmd(void);
 MMCSD_err mmcsd_read_ocr(uint8_t* r1);
 MMCSD_err mmcsd_crc_on_off(int1 crc_enabled);
 MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg);
 MMCSD_err mmcsd_get_r1(void);
 MMCSD_err mmcsd_get_r2(uint8_t r2[]);
 MMCSD_err mmcsd_get_r3(uint8_t r3[]);
 MMCSD_err mmcsd_get_r7(uint8_t r7[]);
 MMCSD_err mmcsd_wait_for_token(uint8_t token);
 uint8_t mmcsd_crc7(char *data, uint8_t length);
 //uint16_t mmcsd_crc16(char *data, uint8_t length);  // Not needed --> commented
 void mmcsd_select();
 void mmcsd_deselect();
 
 /// Fast Functions ! ///
 
 MMCSD_err mmcsd_load_buffer(void);
 MMCSD_err mmcsd_flush_buffer(void);
 MMCSD_err mmcsd_move_buffer(uint32_t new_addr);
 MMCSD_err mmcsd_read_byte(uint32_t addr, char* data);
 MMCSD_err mmcsd_write_byte(uint32_t addr, char data);
 
 //////////////////////////////////
 ////                          ////
 //// Function Implementations ////
 ////                          ////
 //////////////////////////////////
 
 int8 MMCSD_SPI_XFER(int8 spi_data) {
 #ifdef MMCSD_SPI_HW
 return SPI_Read(spi_data);
 #else
 return spi_xfer(spi_data);
 #endif
 }
 
 MMCSD_err mmcsd_init()
 {
 uint8_t
 i,
 r1,
 r3[4];
 
 g_CRC_enabled = TRUE;
 g_mmcsdBufferAddress = 0;
 
 output_drive(MMCSD_PIN_SELECT);
 
 #ifdef MMCSD_SPI_HW
 SETUP_SPI(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_64 | SPI_XMIT_L_TO_H);
 #else   // Software SPI
 output_drive(MMCSD_PIN_SCK);
 output_drive(MMCSD_PIN_MOSI);
 output_float(MMCSD_PIN_MISO);
 #endif
 
 mmcsd_deselect();
 delay_ms(250);
 for(i = 0; i < 10; i++)                        // Send 80 cycles
 MMCSD_SPI_XFER(0xFF);
 
 /* begin initialization */
 i = 0;
 do
 {
 delay_ms(1);
 mmcsd_select();
 r1 = mmcsd_go_idle_state();
 mmcsd_deselect();
 i++;
 if(i == 0xFF) {
 if (r1 == 0)
 return 1;
 else
 return r1;
 }
 } while(r1 != MMCSD_IDLE);
 
 i = 0;
 do
 {
 delay_ms(1);
 mmcsd_select();
 r1 = mmcsd_send_op_cond();
 mmcsd_deselect();
 i++;
 } while((r1 & MMCSD_IDLE) && i != 0xFF);
 if(i == 0xFF) {
 delay_ms(100);
 mmcsd_select();
 r1 = mmcsd_go_idle_state();
 mmcsd_deselect();
 delay_ms(100);
 mmcsd_select();
 r1 = mmcsd_send_if_cond(r3);
 mmcsd_deselect();
 if(r1 != MMCSD_IDLE)
 return r1;
 }
 
 /* figure out if we have an SD or MMC */
 i = 0;
 do {
 mmcsd_select();
 r1=mmcsd_app_cmd();
 r1=mmcsd_sd_send_op_cond();
 mmcsd_deselect();
 delay_ms(100);
 i++;
 } while((r1 == MMCSD_IDLE) && (i != 0xFF));
 if(r1 == MMCSD_IDLE)
 return r1;
 
 /* an mmc will return an 0x04 here */
 if(r1 == 0x04)
 g_card_type = MMC;
 else {
 g_card_type = SDSC;
 mmcsd_select();
 r1 = mmcsd_read_ocr(r3);
 mmcsd_deselect();
 if(r1 != MMCSD_ILLEGAL_CMD) {
 r1 = r3[3];
 if(bit_test(r1, 6))                  // If bit 30 of the OCR register is 1 (CCS is 1) ==> SDHC type
 g_card_type =  SDHC;
 }
 }
 
 /* set block length to 512 bytes */
 mmcsd_select();
 r1 = mmcsd_set_blocklen(MMCSD_MAX_BLOCK_SIZE);
 mmcsd_deselect();
 if(r1 != MMCSD_GOODEC)
 return r1;
 
 /// this would be a good time to set a higher clock speed, 20MHz
 #ifdef MMCSD_SPI_HW
 setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4);
 #else
 #use spi(MASTER, DI=MMCSD_PIN_MISO, DO=MMCSD_PIN_MOSI, CLK=MMCSD_PIN_SCK, BITS=8, MODE=3)
 #endif
 
 // Turn OFF CRC check, some card return 0 (MMCSD_GOODEC) and some others return 0x04 (MMCSD_ILLEGAL_CMD)
 mmcsd_select();
 r1 = mmcsd_crc_on_off(FALSE);
 mmcsd_deselect();
 r1 = mmcsd_load_buffer();
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_read_data(uint32_t address, uint16_t size, uint8_t* ptr)
 {
 MMCSD_err r1;
 uint16_t i;  // counter for loops
 
 for(i = 0; i < size; i++)
 {
 r1 = mmcsd_read_byte(address++, ptr++);
 if(r1 != MMCSD_GOODEC)
 return r1;
 }
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_read_block(uint32_t address, uint16_t size, uint8_t* ptr)
 {
 MMCSD_err ec;
 uint16_t i; // counter for loops
 
 // send command
 mmcsd_select();
 ec = mmcsd_read_single_block(address);
 if(ec != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return ec;
 }
 
 // wait for the data start token
 ec = mmcsd_wait_for_token(DATA_START_TOKEN);
 if(ec != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return ec;
 }
 
 // read in the data
 for(i = 0; i < size; i += 1)
 ptr[i] = MMCSD_SPI_XFER(0xFF);
 
 /*  if(g_CRC_enabled)   // already FALSE
 {
 // check the crc
 if(make16(MMCSD_SPI_XFER(0xFF), MMCSD_SPI_XFER(0xFF)) != mmcsd_crc16(g_mmcsd_buffer, MMCSD_MAX_BLOCK_SIZE))
 {
 mmcsd_deselect();
 return MMCSD_CRC_ERR;
 }
 }
 else
 { */
 /* have the card transmit the CRC, but ignore it */
 MMCSD_SPI_XFER(0xFF);
 MMCSD_SPI_XFER(0xFF);
 //   }
 mmcsd_deselect();
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_write_data(uint32_t address, uint16_t size, uint8_t* ptr)
 {
 MMCSD_err ec;
 uint16_t i;  // counter for loops
 
 for(i = 0; i < size; i++)
 {
 ec = mmcsd_write_byte(address++, *ptr++);
 if(ec != MMCSD_GOODEC)
 return ec;
 }
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_write_block(uint32_t address, uint16_t size, uint8_t* ptr)
 {
 MMCSD_err ec;
 uint16_t i;
 
 // send command
 mmcsd_select();
 ec = mmcsd_write_single_block(address);
 if(ec != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return ec;
 }
 
 // send a data start token
 MMCSD_SPI_XFER(DATA_START_TOKEN);
 
 // send all the data
 for(i = 0; i < size; i += 1)
 {
 MMCSD_SPI_XFER(ptr[i]);
 }
 
 // if the CRC is enabled we have to calculate it, otherwise just send an 0xFFFF
 /*   if(g_CRC_enabled)   // already FALSE
 MMCSD_SPI_XFER(mmcsd_crc16(ptr, size));
 else
 {   */
 MMCSD_SPI_XFER(0xFF);
 MMCSD_SPI_XFER(0xFF);
 //   }
 
 // get the error code back from the card; "data accepted" is 0bXXX00101
 ec = mmcsd_get_r1();
 if(ec & 0x0A)
 {
 mmcsd_deselect();
 return ec;
 }
 
 // wait for the line to go back high, this indicates that the write is complete
 while(MMCSD_SPI_XFER(0xFF) == 0);
 mmcsd_deselect();
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_go_idle_state(void)
 {
 mmcsd_send_cmd(GO_IDLE_STATE, 0);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_send_op_cond(void)
 {
 mmcsd_send_cmd(SEND_OP_COND, 0);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_send_if_cond(uint8_t r7[])
 {
 mmcsd_send_cmd(SEND_IF_COND, 0x1AA);
 
 return mmcsd_get_r7(r7);
 }
 
 MMCSD_err mmcsd_print_csd()
 {
 uint8_t
 buf[16],
 i,
 r1;
 
 // MMCs don't support this command
 if(g_card_type == MMC)
 return MMCSD_PARAM_ERR;
 
 mmcsd_select();
 mmcsd_send_cmd(SEND_CSD, 0);
 r1 = mmcsd_get_r1();
 if(r1 != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return r1;
 }
 
 r1 = mmcsd_wait_for_token(DATA_START_TOKEN);
 if(r1 != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return r1;
 }
 
 for(i = 0; i < 16; i++)
 buf[i] = MMCSD_SPI_XFER(0xFF);
 mmcsd_deselect();
 /*
 printf("\r\nCSD_STRUCTURE: %X", (buf[0] & 0x0C) >> 2);
 printf("\r\nTAAC: %X", buf[1]);
 printf("\r\nNSAC: %X", buf[2]);
 printf("\r\nTRAN_SPEED: %X", buf[3]);
 printf("\r\nCCC: %lX", (make16(buf[4], buf[5]) & 0xFFF0) >> 4);
 printf("\r\nREAD_BL_LEN: %X", buf[5] & 0x0F);
 printf("\r\nREAD_BL_PARTIAL: %X", (buf[6] & 0x80) >> 7);
 printf("\r\nWRITE_BLK_MISALIGN: %X", (buf[6] & 0x40) >> 6);
 printf("\r\nREAD_BLK_MISALIGN: %X", (buf[6] & 0x20) >> 5);
 printf("\r\nDSR_IMP: %X", (buf[6] & 0x10) >> 4);
 printf("\r\nC_SIZE: %lX", (((buf[6] & 0x03) << 10) | (buf[7] << 2) | ((buf[8] & 0xC0) >> 6)));
 printf("\r\nVDD_R_CURR_MIN: %X", (buf[8] & 0x38) >> 3);
 printf("\r\nVDD_R_CURR_MAX: %X", buf[8] & 0x07);
 printf("\r\nVDD_W_CURR_MIN: %X", (buf[9] & 0xE0) >> 5);
 printf("\r\nVDD_W_CURR_MAX: %X", (buf[9] & 0x1C) >> 2);
 printf("\r\nC_SIZE_MULT: %X", ((buf[9] & 0x03) << 1) | ((buf[10] & 0x80) >> 7));
 printf("\r\nERASE_BLK_EN: %X", (buf[10] & 0x40) >> 6);
 printf("\r\nSECTOR_SIZE: %X", ((buf[10] & 0x3F) << 1) | ((buf[11] & 0x80) >> 7));
 printf("\r\nWP_GRP_SIZE: %X", buf[11] & 0x7F);
 printf("\r\nWP_GRP_ENABLE: %X", (buf[12] & 0x80) >> 7);
 printf("\r\nR2W_FACTOR: %X", (buf[12] & 0x1C) >> 2);
 printf("\r\nWRITE_BL_LEN: %X", ((buf[12] & 0x03) << 2) | ((buf[13] & 0xC0) >> 6));
 printf("\r\nWRITE_BL_PARTIAL: %X", (buf[13] & 0x20) >> 5);
 printf("\r\nFILE_FORMAT_GRP: %X", (buf[14] & 0x80) >> 7);
 printf("\r\nCOPY: %X", (buf[14] & 0x40) >> 6);
 printf("\r\nPERM_WRITE_PROTECT: %X", (buf[14] & 0x20) >> 5);
 printf("\r\nTMP_WRITE_PROTECT: %X", (buf[14] & 0x10) >> 4);
 printf("\r\nFILE_FORMAT: %X", (buf[14] & 0x0C) >> 2);
 printf("\r\nCRC: %X", buf[15]);
 */
 return r1;
 }
 
 MMCSD_err mmcsd_print_cid()
 {
 uint8_t
 buf[16],
 i,
 r1;
 
 // MMCs don't support this command
 if(g_card_type == MMC)
 return MMCSD_PARAM_ERR;
 
 mmcsd_select();
 mmcsd_send_cmd(SEND_CID, 0);
 r1 = mmcsd_get_r1();
 if(r1 != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return r1;
 }
 r1 = mmcsd_wait_for_token(DATA_START_TOKEN);
 if(r1 != MMCSD_GOODEC)
 {
 mmcsd_deselect();
 return r1;
 }
 
 for(i = 0; i < 16; i++)
 buf[i] = MMCSD_SPI_XFER(0xFF);
 mmcsd_deselect();
 /*
 printf("\r\nManufacturer ID: %X", buf[0]);
 printf("\r\nOEM/Application ID: %c%c", buf[1], buf[2]);
 printf("\r\nOEM/Application ID: %c%c%c%c%c", buf[3], buf[4], buf[5], buf[6], buf[7]);
 printf("\r\nProduct Revision: %X", buf[8]);
 printf("\r\nSerial Number: %X%X%X%X", buf[9], buf[10], buf[11], buf[12]);
 printf("\r\nManufacturer Date Code: %X%X", buf[13] & 0x0F, buf[14]);
 printf("\r\nCRC-7 Checksum: %X", buf[15]);
 */
 return r1;
 }
 
 MMCSD_err mmcsd_sd_status(uint8_t r2[])
 {
 uint8_t i;
 
 mmcsd_select();
 mmcsd_send_cmd(APP_CMD, 0);
 r2[0]=mmcsd_get_r1();
 mmcsd_deselect();
 
 mmcsd_select();
 mmcsd_send_cmd(SD_STATUS, 0);
 
 for(i = 0; i < 64; i++)
 MMCSD_SPI_XFER(0xFF);
 
 mmcsd_deselect();
 
 return mmcsd_get_r2(r2);
 }
 
 MMCSD_err mmcsd_send_status(uint8_t r2[])
 {
 mmcsd_send_cmd(SEND_STATUS, 0);
 
 return mmcsd_get_r2(r2);
 }
 
 MMCSD_err mmcsd_set_blocklen(uint32_t blocklen)
 {
 mmcsd_send_cmd(SET_BLOCKLEN, blocklen);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_read_single_block(uint32_t address)
 {
 mmcsd_send_cmd(READ_SINGLE_BLOCK, address);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_write_single_block(uint32_t address)
 {
 mmcsd_send_cmd(WRITE_BLOCK, address);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_sd_send_op_cond(void)
 {
 mmcsd_send_cmd(SD_SEND_OP_COND, 0x40000000);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_app_cmd(void)
 {
 mmcsd_send_cmd(APP_CMD, 0);
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_read_ocr(int r3[])
 {
 mmcsd_send_cmd(READ_OCR, 0);
 
 return mmcsd_get_r3(r3);
 }
 
 MMCSD_err mmcsd_crc_on_off(int1 crc_enabled)
 {
 mmcsd_send_cmd(CRC_ON_OFF, crc_enabled);
 
 g_CRC_enabled = crc_enabled;
 
 return mmcsd_get_r1();
 }
 
 MMCSD_err mmcsd_send_cmd(uint8_t cmd, uint32_t arg)
 {
 uint8_t packet[6]; // the entire command, argument, and crc in one variable
 
 // construct the packet
 // every command on an SD card is or'ed with 0x40
 packet[0] = cmd | 0x40;
 packet[1] = make8(arg, 3);
 packet[2] = make8(arg, 2);
 packet[3] = make8(arg, 1);
 packet[4] = make8(arg, 0);
 
 // calculate the crc if needed
 if(g_CRC_enabled)
 packet[5] = mmcsd_crc7(packet, 5);
 else
 packet[5] = 0xFF;
 
 // transfer the command and argument, with an extra 0xFF hacked in there
 MMCSD_SPI_XFER(packet[0]);
 MMCSD_SPI_XFER(packet[1]);
 MMCSD_SPI_XFER(packet[2]);
 MMCSD_SPI_XFER(packet[3]);
 MMCSD_SPI_XFER(packet[4]);
 MMCSD_SPI_XFER(packet[5]);
 //!   spi_write2(packet[0]);
 //!   spi_write2(packet[1]);
 //!   spi_write2(packet[2]);
 //!   spi_write2(packet[3]);
 //!   spi_write2(packet[4]);
 //!   spi_write2(packet[5]);
 
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_get_r1(void)
 {
 uint8_t
 response = 0,  // place to hold the response coming back from the SPI line
 timeout = 0xFF; // maximum amount loops to wait for idle before getting impatient and leaving the function with an error code
 
 // loop until timeout == 0
 while(timeout)
 {
 // read what's on the SPI line
 //  the SD/MMC requires that you leave the line high when you're waiting for data from it
 response = MMCSD_SPI_XFER(0xFF);
 //response = MMCSD_SPI_XFER(0x00);//leave the line idle
 
 // check to see if we got a response
 if(response != 0xFF)
 {
 // fill in the response that we got and leave the function
 return response;
 }
 
 // wait for a little bit longer
 timeout--;
 }
 
 // for some reason, we didn't get a response back from the card
 //  return the proper error codes
 return RESP_TIMEOUT;
 }
 
 MMCSD_err mmcsd_get_r2(uint8_t r2[])
 {
 r2[1] = mmcsd_get_r1();
 
 r2[0] = MMCSD_SPI_XFER(0xFF);
 
 return 0;
 }
 
 MMCSD_err mmcsd_get_r3(uint8_t r3[])
 {
 return mmcsd_get_r7(r3);
 }
 
 MMCSD_err mmcsd_get_r7(uint8_t r7[])
 {
 uint8_t i;   // counter for loop
 
 // the top byte of r7 is r1
 r7[4]=mmcsd_get_r1();
 
 // fill in the other 4 bytes
 for(i = 0; i < 4; i++)
 r7[3 - i] = MMCSD_SPI_XFER(0xFF);
 
 return r7[4];
 }
 
 MMCSD_err mmcsd_wait_for_token(uint8_t token)
 {
 MMCSD_err r1;
 
 // get a token
 r1 = mmcsd_get_r1();
 
 // check to see if the token we recieved was the one that we were looking for
 if(r1 == token)
 return MMCSD_GOODEC;
 
 // if that wasn't right, return the error
 return r1;
 }
 
 unsigned int8 mmcsd_crc7(char *data,uint8_t length)
 {
 uint8_t i, ibit, c, crc;
 
 crc = 0x00;                                                                // Set initial value
 
 for (i = 0; i < length; i++, data++)
 {
 c = *data;
 
 for (ibit = 0; ibit < 8; ibit++)
 {
 crc = crc << 1;
 if ((c ^ crc) & 0x80) crc = crc ^ 0x09;                              // ^ is XOR
 c = c << 1;
 }
 
 crc = crc & 0x7F;
 }
 
 shift_left(&crc, 1, 1);                                                    // MMC card stores the result in the top 7 bits so shift them left 1
 // Should shift in a 1 not a 0 as one of the cards I have won't work otherwise
 return crc;
 }
 
 /* Not needed function (CRC is OFF)
 uint16_t mmcsd_crc16(char *data, uint8_t length)
 {
 uint8_t i, ibit, c;
 
 uint16_t crc;
 
 crc = 0x0000;                                                                // Set initial value
 
 for (i = 0; i < length; i++, data++)
 {
 c = *data;
 
 for (ibit = 0; ibit < 8; ibit++)
 {
 crc = crc << 1;
 if ((c ^ crc) & 0x8000) crc = crc ^ 0x1021;                              // ^ is XOR
 c = c << 1;
 }
 
 crc = crc & 0x7FFF;
 }
 
 shift_left(&crc, 2, 1);                                                    // MMC card stores the result in the top 7 bits so shift them left 1
 // Should shift in a 1 not a 0 as one of the cards I have won't work otherwise
 return crc;
 }
 */
 
 void mmcsd_select()
 {
 output_low(MMCSD_PIN_SELECT);
 }
 
 void mmcsd_deselect()
 {
 //MMCSD_SPI_XFER(0xFF);
 output_high(MMCSD_PIN_SELECT);
 }
 
 MMCSD_err mmcsd_load_buffer(void)
 {
 g_MMCSDBufferChanged = FALSE;
 return(mmcsd_read_block(g_mmcsdBufferAddress, MMCSD_MAX_BLOCK_SIZE, g_mmcsd_buffer));
 }
 
 MMCSD_err mmcsd_flush_buffer(void)
 {
 if (g_MMCSDBufferChanged)
 {
 g_MMCSDBufferChanged = FALSE;
 return(mmcsd_write_block(g_mmcsdBufferAddress, MMCSD_MAX_BLOCK_SIZE, g_mmcsd_buffer));
 }
 return(0);  //ok
 }
 
 MMCSD_err mmcsd_move_buffer(uint32_t new_addr)
 {
 MMCSD_err ec = MMCSD_GOODEC;
 uint32_t
 //cur_block,
 new_block;
 
 // make sure we're still on the same block
 //cur_block = g_mmcsdBufferAddress - (g_mmcsdBufferAddress % MMCSD_MAX_BLOCK_SIZE);
 if(g_card_type == SDHC)
 new_block = new_addr / MMCSD_MAX_BLOCK_SIZE;
 else
 new_block = new_addr - (new_addr % MMCSD_MAX_BLOCK_SIZE);
 
 //if(cur_block != new_block)
 if(g_mmcsdBufferAddress != new_block)
 {
 // dump the old buffer
 if (g_MMCSDBufferChanged)
 {
 ec = mmcsd_flush_buffer();
 if(ec != MMCSD_GOODEC)
 return ec;
 g_MMCSDBufferChanged = FALSE;
 }
 
 // figure out the best place for a block
 g_mmcsdBufferAddress = new_block;
 
 // load up a new buffer
 ec = mmcsd_load_buffer();
 }
 
 return ec;
 }
 
 MMCSD_err mmcsd_read_byte(uint32_t addr, char* data)
 {
 MMCSD_err ec;
 
 ec = mmcsd_move_buffer(addr);
 if(ec != MMCSD_GOODEC)
 {
 return ec;
 }
 
 *data = g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE];
 
 return MMCSD_GOODEC;
 }
 
 MMCSD_err mmcsd_write_byte(uint32_t addr, char data)
 {
 MMCSD_err ec;
 ec = mmcsd_move_buffer(addr);
 if(ec != MMCSD_GOODEC)
 return ec;
 
 g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE] = data;
 
 g_MMCSDBufferChanged = TRUE;
 
 return MMCSD_GOODEC;
 }
 
 #endif
 
 | 
 
 
 This is my driver how can I modify it in order to NOT consume extra current?
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jul 31, 2020 11:29 am |   |  
				| 
 |  
				| An additional information: When the PIC goes to deep sleep, the MicroSD supply provided by a 3.3V LDO voltage regulator is switched off. So I think that MicroSD consumes 2mA through SCK, it is the ONLY MicroSD pin high (3.3V), I checked with a multimeter....
 Otherwise how might MicroSD consume this current ?
 
 Is my deduction correct? If yes, how can I set spi in order to have SCK pin low?
 
 Is it sufficient to change MODE parameter in #use spi setting ?
 
 Thank you,
 
 Marco
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jul 31, 2020 12:59 pm |   |  
				| 
 |  
				| OK. Powering off the SD is a different kettle of fish.
 In this case, the trick is to take advantage of pin_select (the 'in code'
 version of this operation), to deselect the pin.
 
 So:
 
  	  | Code: |  	  | pin_select(NULL,PIN_D4);
 output_low(PIN_D2);  //MOSI
 output_low(PIN_D3);  //MISO
 output_low(PIN_D4);  //SCK
 output_low(PIN_D0);  //CS
 
 //Then when you wake up, re-select the pin:
 pin_select(SCLK2,PIN_D4); //before using the SPI
 
 | 
 
 Remember your fuses must be set to allow the selections to be changed
 more than once.
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 03, 2020 7:34 am |   |  
				| 
 |  
				| Thank you Ttelmah, 
 This directive belongs to a library included by main at each wake-up:
 
 #PIN_SELECT SCK2=PIN_D4
 
 Is it sufficient or Have I to add in code pin_select(SCLK2, PIN_D4);  ??
 
 These are my current fuses:
 
 
  	  | Code: |  	  | #FUSES RTCOSC_INT                                                               // Real Time Clock-Calendar   enabled and uses internal clock
 #FUSES WDT,WDT1024                                                              // Watch Dog Timer            enabled and uses internal clock with 1:1024     Postscale (4.1 sec)
 #FUSES DSWDT,DSWDTOSC_INT                                                       // Deep Sleep Watch Dog Timer enabled and uses internal clock with 1:33554432 Postscale*(9.6 hours)
 #FUSES DSWDT_=12                                                                // *DSWDT_9HRS (compiler 5.090 has an issue with this fuse, so adopt this work-around)
 #FUSES NOPROTECT                                                                // Allow a Programmer device (eg. Pickit) to read Microcontroller firmware
 
 | 
 
 
 Do they allow the selections to be changed more than once?
 If not, how can I change them ?
 
 Regards
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Aug 03, 2020 7:52 am |   |  
				| 
 |  
				| You need to add the fuse NOIOL1WAY 
 Then the point is that the existing code sets the pin up, but in your sleep
 and wake up code you need to add the 'in code' version of pin_select as I
 show. What happens is the the standard #PIN_SELECT sets the pin to be
 controlled by the SPI peripheral. These lines allow this control to be turned
 'off' by instead setting the pin to the 'NULL' device. Then when the chip
 wakes the connection back to the SPI has to be re-made.
 
 This line:
 pin_select(NULL,PIN_D4);
 
 Disconnects D4, from the SPI peripheral, then this line:
 pin_select(SCLK2,PIN_D4);
 
 Connects it back to the peripheral.
 
 Between these, the normal 'output_low' instruction can work.
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Sep 21, 2020 6:52 am |   |  
				| 
 |  
				| Hi everyone, 
 I'm facing a weird problem using a MicroSD and the library posted in this topic.
 Sometimes (5% of all cases) when I try to read data stored in the MicroSD it seems that the RAM buffer does not correctly load data from the card.
 
 The function mmcsd_read_data(a, n, p) returns 0 with success but the data read are the last data previously written during the data acquisition process and buffer content does not change its content.
 
 Any suggestion regarding issue cause ?
 I think it could be a bug of mmcsd.c driver, I need help to fix it.
 
 Regards
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Sep 21, 2020 7:03 am |   |  
				| 
 |  
				| Are you sure you are updating the address required correctly?. The read_data function will not perform a transfer and will return 0, if the
 address requested is the same as the last one used. It assumes in this
 case that since you just wrote the data, what is in the buffer is the data
 required.
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Sep 21, 2020 7:33 am |   |  
				| 
 |  
				| yes I'm sure 
 
  	  | Code: |  	  | void Send_IMG_bytes_from_MicroSD(int32 size,int32 Address,int8 portion)
 {
 fail_safe_wd=0;
 int8 data,res;
 
 
 int32 memAddress=Address;
 int32 counter=0;
 
 while(counter<size)
 {
 res=mmcsd_read_data(memAddress, 1, &data);
 if(res==0)
 {
 counter++;
 memAddress++;
 if((debug)&&(counter<1024)) usb_cdc_putc(data);
 
 }
 }
 }
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Sep 21, 2020 8:05 am |   |  
				| 
 |  
				| Er. It won't load any new data. The read_byte routine, loads a block of data into g_mmcsd_buffer. It then
 returns the data from the requested index in this buffer.
 
 *data = g_mmcsd_buffer[addr % MMCSD_MAX_BLOCK_SIZE];
 
 So a read to change the data will only occur every
 MMCSD_MAX_BLOCK_SIZE bytes,
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Sep 22, 2020 1:18 am |   |  
				| 
 |  
				| I got this point. The problem is : while loop cycles over thousands of sequential data, but I always  read the same 512 bytes.
 When the buffer overflows no new buffer is loaded, it is a weird issue because happens in 5-10% of cases.
 In a lot of other tests MicroSD is correctly read and nothing changes in hardware or firmware...
 I really need to overcome this problem but I have no idea on what is causing it.
 
 Regards
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Sep 22, 2020 1:43 am |   |  
				| 
 |  
				| Test if it is actually calling the mmcsd_load_buffer routine?. This is what actually loads new data into the buffer. The value of g_mmcsdBufferAddress
 when this is called, is the 'block number' to be loaded. This (obviously)
 should be changing to match the new sector to load. If this is not being called
 than an error is occurring, but the question is whey it is not being flagged
 as such. If it is being called, and the sector number is changing, then instead
 we need to work out why this is not actually working....
 |  |  
		|  |  
		| Marco27293 
 
 
 Joined: 09 May 2020
 Posts: 136
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Sep 22, 2020 7:20 am |   |  
				| 
 |  
				| mmcsd_load_buffer routine is correctly called. g_mmcsdBufferAddress is correctly updated.
 
 The bug persists...
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Sep 22, 2020 8:05 am |   |  
				| 
 |  
				| OK. What has to be happening is that when it calls 'wait_for_token', it is retrieving a value of zero.
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |