This program reads out the health data of some industrial grade SD Cards. Unfortunately there is no standard way of doing this. Sdmon uses CMD56 of the SD card specification and currently does this for:
- Apacer Industrial SD Cards, and some others from branded distributors
- Kingston Industrial SD Cards (SDCIT/32GB and the SDCIT2/32GB where reported to work with the -a option, see Issue #6)
- Kingston High Endurance SD Cards (SDCE, see Issue #30)
- SanDisk Industrial SD Cards (code contributed by William Croft)
- Western Digital WD Purple SD Cards (QD101)
Although some of the above cards have been tested, there is no guarantee that a particular card of the above manufacturers will work.
The output of the program is JSON so that it can be parsed easier in applications using sdmon.
For available versions see releases. Choose the correct archive for your os, i.e. sdmon-arm64.tar.gz for raspberry pi os 64bit or sdmon-armv7.tar.gz raspberry pi os 32bit.
Adjust the path to the desired version by replacing v0.2.0
in the below example with the desired one.
curl -L https://github.com/Ognian/sdmon/releases/download/v0.2.0/sdmon-arm64.tar.gz | tar zxf -
The latest
development release may be also available.
curl -L https://github.com/Ognian/sdmon/releases/download/latest/sdmon-arm64.tar.gz | tar zxf -
The executable is statically linked, therefore it should work without any dependencies.
On a raspberry pi:
sudo ./sdmon /dev/mmcblk0
The -a option was introduced to allow extra time between the 2 CMD56 commands (1 second). Try first without it and if not successful try using the -a option like:
sudo ./sdmon /dev/mmcblk0 -a
This is the output when the card doesn't support health status:
sudo ./sdmon /dev/mmcblk0
{
"version": "v.0.01-dirty (314f9dc)",
"date": "2022-04-07T16:18:24.000Z",
"device":"/dev/mmcblk0",
"idata.response[]":"0x900 0x00 0x00 0x00",
"error1":"1st CMD56 CALL FAILED: Operation timed out",
"error2":"2nd CMD56 CALL FAILED: Operation timed out"
}
Apacer Industrial micro SD card (99.97% healthy):
{
"version": "v0.3.2-dirty (262e866)",
"date": "2022-04-14T11:23:48.000Z",
"device":"/dev/mmcblk0",
"read_via_cmd56_arg_1":"read successful but signature 0xff 0xff"
"idata.response[]":"0x900 0x00 0x00 0x00",
"flashId": ["0x98","0x3c","0x98","0xb3","0x76","0x72","0x08","0x0e","0x00"],
"icVersion": ["0x1f","0xc3"],
"fwVersion": [83,201],
"ceNumber": "0x01",
"spareBlockCount": 46,
"initialBadBlockCount": 72,
"goodBlockRatePercent": 97.56,
"totalEraseCount": 1380,
"enduranceRemainLifePercent": 99.97,
"avgEraseCount": 1,
"minEraseCount": 1,
"maxEraseCount": 5,
"powerUpCount": 55,
"abnormalPowerOffCount": 0,
"totalRefreshCount": 0,
"productMarker": ["0x00","0x00","0x00","0x00","0x00","0x00","0x00","0x00"],
"laterBadBlockCount": 0,
"success":true
}
Sandisk Industrial SD card (99% healthy)
sudo ./sdmon /dev/mmcblk0
{
"version": "v0.3.2-3 (a04b618) arm64",
"date": "2022-04-14T08:27:15.000Z",
"device":"/dev/mmcblk0",
"signature":"0x44 0x53",
"SanDisk":"true",
"manufactureYYMMDD": "211122",
"healthStatusPercentUsed": 1,
"featureRevision": "0x1f",
"generationIdentifier": 5,
"productString": "SanDisk ",
"success":true
}
Western Digital Purple QD101
sudo ./sdmon /dev/mmcblk0
{
"version": "v0.9.0 (4dff9b6) arm64",
"date": "2024-08-04T23:41:55.000",
"device":"/dev/mmcblk0",
"addTime": "false",
"signature":"0x44 0x57",
"SanDisk":"true",
"manufactureYYMMDD": "240403",
"healthStatusPercentUsed": 1,
"featureRevision": "0x1f",
"generationIdentifier": 7,
"productString": "Western Digital ",
"powerOnTimes": 14,
"success":true
}
Kingston Industrial microSD Card SDCIT2
sudo ./sdmon /dev/mmcblk0
{
"version": "v0.8.1-18 (f492365) armv7",
"date": "2025-01-21T17:04:54.000Z",
"device":"/dev/mmcblk0",
"addTime": "false",
"read_via_cmd56_arg_1":"read successful but signature 0xff 0xff",
"idata.response[]":"0x900 0x00 0x00 0x00",
"flashId": ["0x98","0x3c","0x98","0xb3","0xf6","0xe3","0x08","0x1e","0x00"],
"icVersion": ["0x1f","0xc3"],
"fwVersion": [38,240],
"ceNumber": "0x01",
"spareBlockCount": 12,
"initialBadBlockCount": 12,
"goodBlockRatePercent": 99.38,
"totalEraseCount": 1707,
"enduranceRemainLifePercent": 100.00,
"avgEraseCount": 1,
"minEraseCount": 1,
"maxEraseCount": 13,
"powerUpCount": 46,
"abnormalPowerOffCount": 0,
"totalRefreshCount": 0,
"productMarker": ["0x70","0x53","0x4c","0x43","0x00","0x00","0x00","0x00"],
"laterBadBlockCount": 0,
"success":true
}
Although it's impossible to maintain an exhaustive and up-to-date list, here is a list of SD cards that are known NOT to be working at the time they were tested, with the available knowledge at the time.
- Sandisk High Endurance (2025): doesn't answer to CMD56 at all (timeout)
- Sandisk Max Endurance (2025): doesn't answer to CMD56 at all (timeout)
- Samsung Pro Endurance (2025): doesn't answer to CMD56 at all (timeout)
- Transcend High Endurance (2025): answers a 0x00-filled block to known CMD56 arg1 values. Bruteforced all possible arg1 values (with bit0 == 1), none found returning anything else than a zero-filled block, except 0x11111111 returning static-data with 2 useless strings.
Additionally, it is believed that none of the classical (non-"endurance" non-"industrial") widely available consumer-grade models will ever support any type of health query, so they're omitted from this list.
This project uses the json and json-builder libraries, licensed under the BSD-2-Clause License. Their .c and .h source files have simply been added untouched to the source tree, as suggested in their readme file. The headers of these files contain more details about the license.
(c) 2018 - today, OGI-IT, Ognian Tschakalov and contributors, released under GNU GPL v2