Skip to content

Instantly share code, notes, and snippets.

@matwey
Last active September 5, 2020 08:21
Show Gist options
  • Select an option

  • Save matwey/d5cc63f85822e35bae49c6d904951141 to your computer and use it in GitHub Desktop.

Select an option

Save matwey/d5cc63f85822e35bae49c6d904951141 to your computer and use it in GitHub Desktop.
Apacer microSD diagnostic readout.
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/mmc/ioctl.h>
#define MMC_BLOCK_MAJOR 179
#define MMC_RSP_PRESENT (1 << 0)
#define MMC_RSP_136 (1 << 1) /* 136 bit response */
#define MMC_RSP_CRC (1 << 2) /* expect valid crc */
#define MMC_RSP_BUSY (1 << 3) /* card may send busy */
#define MMC_RSP_OPCODE (1 << 4) /* response contains opcode */
#define MMC_CMD_AC (0 << 5)
#define MMC_CMD_ADTC (1 << 5)
#define MMC_RSP_SPI_S1 (1 << 7) /* one status byte */
#define MMC_RSP_SPI_BUSY (1 << 10) /* card may send busy */
#define MMC_RSP_SPI_R1 (MMC_RSP_SPI_S1)
#define MMC_RSP_SPI_R1B (MMC_RSP_SPI_S1|MMC_RSP_SPI_BUSY)
#define MMC_RSP_R1 (MMC_RSP_PRESENT|MMC_RSP_CRC|MMC_RSP_OPCODE)
void print_56(int fd, int cmdid) {
struct mmc_ioc_cmd idata;
uint8_t buf[512] = {0};
memset(&idata, 0, sizeof(idata));
idata.write_flag = 1;
idata.opcode = 56;
idata.arg = 0x10;
idata.flags = MMC_RSP_R1;
idata.blksz = 512;
idata.blocks = 1;
mmc_ioc_cmd_set_data(idata, buf);
int ret = ioctl(fd, MMC_IOC_CMD, &idata);
if (ret < 0) {
perror("ioctl");
return;
}
idata.write_flag = 0;
idata.arg = 0x21;
ret = ioctl(fd, MMC_IOC_CMD, &idata);
if (ret < 0) {
perror("ioctl");
return;
}
for(int i=0;i<32;i++) {
printf("%02x ", buf[32+i]);
}
printf("\n");
for(int i=0;i<32;i++) {
printf("%02x ", buf[184+i]);
}
printf("\n");
uint16_t rep = ((uint16_t)buf[16] << 8) | buf[17];
printf("Bad block replace max: %u\n", rep);
uint16_t g = ((uint16_t)buf[64] << 8) | buf[65];
printf("Good block ratio (%): %u\n", g);
uint32_t erase = ((uint32_t)buf[80] << 24) | ((uint32_t)buf[81] << 16) | ((uint32_t)buf[82] << 8) | buf[83];
printf("Erase count: %u\n", erase);
uint16_t e = ((uint16_t)buf[96] << 8) | buf[97];
printf("Endruance (Remain Life) (%): %u\n", e);
uint32_t boot = ((uint32_t)buf[112] << 24) | ((uint32_t)buf[113] << 16) | ((uint32_t)buf[114] << 8) | buf[115];
printf("Powerup count: %u\n", boot);
uint16_t c = ((uint16_t)buf[160] << 8) | buf[161];
printf("Refesh count: %u\n", c);
printf("\n");
}
int main(int argc, char** argv) {
int ret;
int fd = open("/dev/mmcblk0", O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
print_56(fd,0);
close(fd);
return 0;
}
@mavik1
Copy link
Copy Markdown

mavik1 commented Sep 3, 2020

What type of endurance values do you see? I'm seeing values like 11526 and 4400 which seem out of range?

@matwey
Copy link
Copy Markdown
Author

matwey commented Sep 5, 2020

00 0c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Bad block replace max: 47
Good block ratio (%): 9943
Erase count: 4151404
Endruance (Remain Life) (%): 13753
Powerup count: 74
Refesh count: 0

@matwey
Copy link
Copy Markdown
Author

matwey commented Sep 5, 2020

I suppose 13752 has to be interpreted as 137.52%, but I don't know what does it mean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment