‎2020-10-10 12:27 PM
Hi .
Below code has two part :
1- when there is response to CMD8
2- when there is not
And by this response we can determine if it is V1 or V2 but , when it will go for Initializing V2 after sending first ACMD41 then there is an "if" clause ,which will check response to knows if response is "SD_R1_ILLEGAL_COMMAND" then if it is "SD_R1_ILLEGAL_COMMAND" it will send ACMD41 with no argument .
---------------------
So there is two question here for me ?
(Both questions are related to line 947 in attached C file which is :)
if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND)
1- Is second "if clause " for checking ( SDSC ) or ( SDHC and SDXC ) type card ? => what I've got is : It is for initializing V2 - SDSC type card so it will send ACMD41 with no argument (HCS = 0) .(Am I right ?) ( It is what I got from flowchart in "SPI Mode Initilization Flow" part of SD documents ).
2- I read "Physical_Layer_Simplified_Specification" more than ten times but ,I couldn't find description, when it will send "SD_R1_ILLEGAL_COMMAND" in response of ACMD41 (which used in "if clause " after first ACMD41 with argument HCS = 1 ,so by checking response second ACMD41 which is in this "if clause " will send with HCS = 0 because of this ), which page has described this part of ACMD41 in SPI mode ?
response = SD_SendCmd(SD_CMD_SEND_IF_COND, 0x1AA, 0x87, SD_ANSWER_R7_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND)
{
/* initialise card V1 */
do
{
/* initialise card V1 */
/* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_APP_CMD, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
/* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
}
while(response.r1 == SD_R1_IN_IDLE_STATE);
flag_SDHC = 0;
}
else if(response.r1 == SD_R1_IN_IDLE_STATE)
{
/* initialise card V2 */
do {
/* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
/* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x40000000, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
}
while(response.r1 == SD_R1_IN_IDLE_STATE);
//********************************QA**********************************
// below line of code is where I could not find description for it in SD Documentation
//********************************QA**********************************
if((response.r1 & SD_R1_ILLEGAL_COMMAND) == SD_R1_ILLEGAL_COMMAND)
{
do {
/* Send CMD55 (SD_CMD_APP_CMD) before any ACMD command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_APP_CMD, 0, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
if(response.r1 != SD_R1_IN_IDLE_STATE)
{
return BSP_SD_ERROR;
}
/* Send ACMD41 (SD_CMD_SD_APP_OP_COND) to initialize SDHC or SDXC cards: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SD_APP_OP_COND, 0x00000000, 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
}
while(response.r1 == SD_R1_IN_IDLE_STATE);
}
/* Send CMD58 (SD_CMD_READ_OCR) to initialize SDHC or SDXC cards: R3 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_READ_OCR, 0x00000000, 0xFF, SD_ANSWER_R3_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
if(response.r1 != SD_R1_NO_ERROR)
{
return BSP_SD_ERROR;
}
flag_SDHC = (response.r2 & 0x40) >> 6;
‎2020-10-12 09:05 AM
Up.
(Just because community had problem )
:)
‎2020-10-13 02:52 AM
CMD8 performs three functions:
(a) differentiates v1 and v2 SD cards,
(b) notifies the card the host understands the physical spec v2,
(c) checks the card can handle the host's supply voltage.
>1- when there is response to CMD8
>2- when there is not
From SD Specifications Part 1 Physical Layer Simplified Specification Version 6.00 August 29, 2018,
figure 4-2 shows a "no response" to the CMD8. But that is SD-mode. SPI-mode should always respond to CMD8.
page 175 lists how different versions of SD card respond to the CMD8. Cards that don't support CMD8 respond in the R1 part with illegal command status.
page 203, 210 explain CMD8 and ACMD41.
figure 7-2 explains the ACMD41 argument 0x40000000 (HCS bit) for v2 cards.
>below line of code is where I could not find description for it in SD Documentation
No it's not mentioned. But there are many SD cards. We can only guess the developer of this code had a card that would respond without illegal command to the CMD8, and with illegal command to the ACMD41 with the HCS bit set.
Another good resource is http://elm-chan.org/docs/mmc/mmc_e.html.
‎2020-10-14 12:37 AM
Thank you . this part was my question :
-------------------------------------
No it's not mentioned. But there are many SD cards. We can only guess the developer of this code had a card that would respond without illegal command to the CMD8, and with illegal command to the ACMD41 with the HCS bit set.
-------------------------------------
And there is another question about this library :
1- for CMD32 it will check SDHC then will multiply to 1 or BlockSize (in case of sdsc), to overcome block oriented type or byte oriented card type :
/* Send CMD32 (Erase group start) and check if the SD acknowledged the erase command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SD_ERASE_GRP_START, (StartAddr) * (flag_SDHC == 1 ? 1 : BlockSize), 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
2- But for CMD33 EndAddr multiply by 512 by default ,then again will check SDHC and maybe another multiply to 512(BlockSize usually) .I know why second 512(BlockSize usually) is necessary, but why is the first default 512 necessary? ( this one -> (EndAddr*512) )
/* Send CMD33 (Erase group end) and Check if the SD acknowledged the erase command: R1 response (0x00: no errors) */
response = SD_SendCmd(SD_CMD_SD_ERASE_GRP_END, (EndAddr*512) * (flag_SDHC == 1 ? 1 : BlockSize), 0xFF, SD_ANSWER_R1_EXPECTED);
SD_IO_CSState(1);
SD_IO_WriteByte(SD_DUMMY_BYTE);
‎2020-10-14 04:10 AM
flag_SDHC is the variable at the bottom of the code snippet in your first post.
SD Specifications Part 1 Physical Layer Simplified Specification Version 6.00 August 29, 2018, table 7-4, point 10.
It applies all commands with an address argument. The older SDSC are byte-addressed. The newer SDHC and SDXC (and larger) are 512-byte-block-addressed as they'll need the extra address bits and the various file systems are dependent on the 512-byte block size anyway.
‎2020-10-15 07:07 AM
Nop . It was not my question . I knew different between SDSC byte address oriented card and SDHC-SDXC block address .
The problem is with those two function maybe with an example it will be better explanation .
Imagine flag_SDHC = 1 ; -> so the card is block address type .
Now we will call SD_SendCmd function :
1- For start erase address it would be like this :
//The Second parameter will replace with 1 because we want to erase from first or block number one and because "lag_SDHC = 1" so because of ternary operator "?" block number 1 * 1 will be 1 :
SD_SendCmd(SD_CMD_SD_ERASE_GRP_START, 1 , 0xFF, SD_ANSWER_R1_EXPECTED);
which has no problem and everything seems fine .
2- For end erase address it would be like this :
//The Second parameter will replace with 5( as an example we want block number 5 will be our end erase address ) and because of "flag_SDHC = 1" and because of ternary operator "?" resault for second function parameter will be (5 * 512)*(1) which is block 2560 !!! :
SD_SendCmd(SD_CMD_SD_ERASE_GRP_END, (5*512) * (1), 0xFF, SD_ANSWER_R1_EXPECTED);
But here is the problem it will multiply our EndAddress with 512 ! why should we do this ? why like start address it is not just block number (without any multiplication to 512) ?
‎2020-10-15 03:54 PM
Yes, that would be a bug.
The function's called if _USE_TRIM's enabled?
‎2020-10-16 07:38 AM
I don't think it will be a bug ! because it is so obvious .it should be something ( maybe all address for two function should be in byte manner )
USE_TRIM is not in this library .
‎2020-10-16 06:25 PM
>I read "Physical_Layer_Simplified_Specification"
In version 6.00 of the spec, CMD32 and CMD33 for SPI-mode are described on page 221, and see their reference to note 10. For CCS = 0, the address is byte unit. For CCS = 1, the address us 512-bytes unit.
>I don't think it will be a bug !
Only if EndAddr's type is float.
>USE_TRIM is not in this library .
See http://elm-chan.org/fsw/ff/doc/config.html#use_trim.
If _USE_TRIM (FF_USE_TRIM on this page) isn't enabled in your FatFs configuration header file, I suspect this function using CMD32/33 isn't being called.
‎2020-10-19 09:52 AM
Thank you , And I'm not using FatFs ,At this time I just am using this library nothing else .
And in picture below there is an example of "Physical_Layer_Simplified_Specification"
So,Still here have this question not answered :
-----------------------------------------------------------------------
I knew different between SDSC byte address oriented card and SDHC-SDXC block address .
The problem is with those two function maybe with an example it will be better explanation .
Imagine flag_SDHC = 1 ; -> so the card is block address type .
Now we will call SD_SendCmd function :
1- For start erase address it would be like this :
//The Second parameter will replace with 1 because we want to erase from first or block number one and because "lag_SDHC = 1" so because of ternary operator "?" block number 1 * 1 will be 1 :
SD_SendCmd(SD_CMD_SD_ERASE_GRP_START, 1 , 0xFF, SD_ANSWER_R1_EXPECTED);
which has no problem and everything seems fine .
2- For end erase address it would be like this :
//The Second parameter will replace with 5( as an example we want block number 5 will be our end erase address ) and because of "flag_SDHC = 1" and because of ternary operator "?" resault for second function parameter will be (5 * 512)*(1) which is block 2560 !!! :
SD_SendCmd(SD_CMD_SD_ERASE_GRP_END, (5*512) * (1), 0xFF, SD_ANSWER_R1_EXPECTED);
But here is the problem it will multiply our EndAddress with 512 ! why should we do this ? why like start address it is not just block number as in last picture sd specification example said (without any multiplication to 512) ?
For CSD v2 in sector_size it has said it is not related to erase operation and AU size has affect on this ? Isn't it related to this 512 ?