Dispo Adventures, Episode 1: Reverse-engineering and “running Windows 95” on a disposable vape with a colour LCD screen

As seen on Hackaday!

TL;DR: Disposable vapes can have LCD screens…?! At least they’re moddable now – check out my GitHub for docs, tools, and links to similar projects if you want to try this on a Kraze HD7K or Raz TN9000 (maybe some others too).

Disposable vaping devices have become distressingly common in recent years, and an increasing ecological burden given how many (perfectly reusable!) lithium-ion batteries are discarded into landfills and roadsides alike. Even worse, some of them include flashy colour LCD screens! I’ve been collecting and harvesting disposable vapes from my friends for a few years now, but only recently have I had a chance to take some of these LCD-equipped models apart; while doing so, I figured I could pioneer some reverse-engineering efforts while adding custom theme/skin support along the way. (For the record, I don’t vape or smoke but plenty of my friends do. I’m just in it for the batteries and electronics.)

A modified Kraze HD7K disposable vape, with my custom Windows 95 theme applied.

A modified Kraze HD7K disposable vape, with my custom Windows 95 theme applied.

The vape in question is found in my area of Canada as the Kraze HD7K, but it seems to go by other names like the Raz TN9000. Internally, they are the same minus some firmware and logo differences.

Disclaimer & Safety Information

Harvesting disposable vapes is not without its own risks, and I will not accept any responsibility if something goes wrong if you try it yourself. This should only be attempted if you are familiar with handling lithium-ion batteries and the safety implications that they pose.

Nicotine can enter your bloodstream simply by getting vape juice on your skin (so wear gloves!), and can be messy if it gets on your clothes and workspace.  The enclosed lithium-ion battery can also cause burns or property damage if short-circuited, and are usually not equipped with protection circuits; the fact that these cells can push several amps in such a small package is the precise reason they’re (wastefully) used in this application. Rechargeable disposable vapes pose a slightly higher risk if the cell is near or at full charge when disassembled, whereas pure disposables are almost always fully discharged. Discharged cells inherently hold less energy and this reduces the fire risk should a catastrophic failure occur during disassembly, but they still need to be treated with respect. Overdischarged cells below 2 volts may not necessarily recover, but if you decide to attempt a recovery, you must bring them back up to 3 volts at a very low current (on the order of tens of milliamps), after which it is possible to charge them normally.

Vapes harvested from the roadside should only be picked up when it is safe to do so, and should be inspected for damage as soon as possible. These “street lithium” vapes could be water-damaged and also physically damaged from getting run over by vehicles. Any cells with a punctured or torn pouch/casing are unsalvageable and must be recycled. My own experimental data finds that the majority of run-over cells survive, but I would not recommend using them without being absolutely sure that there is no further internal damage (after charging the cell with supervision, it should have at least 90% of its rated capacity and no appreciable self-discharge after a few weeks of rest. Otherwise, put it in the recycle bin where it belongs). Even then, only use them in applications where their failure will not cause collateral damage, like in an outdoor solar-powered lamp that is kept away from anything flammable. If you’re not comfortable with these conditions, just recycle the vape at an appropriate facility in accordance with local regulations (some vape shops will have recycling bins, and hardware stores often will accept rechargeable batteries for recycling too).

Teardown

Without any screw holes, I needed to find another way to (non-destructively) open the vape. I noticed a seam in the bottom end cap, and found that sliding a slotted screwdriver into that seam and some gentle prying action was able to dislodge the internal clips. Once that cap was free, a sliding airflow “switch” fell out as well. Removing the core of the vape was pretty straightforward, but it did require some pliers to pull it out due to its friction-fit construction.

With the core exposed, I could see that the vape uses a 13450-size lithium-ion pouch cell (13mm diameter, 45mm length) and a generously-sized vape juice reservoir, with a sponge to absorb the juice and prevent it from leaking. I also noticed a small 9-pin right angle header that connected a black “logic board” that held a microcontroller and LCD screen, and a green “power board” that had the inhalation sensor, heating coil connector, USB-C connector and solder pads for the battery.

Reverse-Engineering

The three main components of the vape’s logic board are the microcontroller, an SPI NOR Flash chip, and the LCD screen.

The microcontroller is a Nations Tech N32G031K8Q7-1, containing a 48MHz Arm Cortex-M0 CPU, 64k of internal Flash and 8k of SRAM; the SPI Flash is a 1MB Giantech GT25Q80A-UZLI; and the LCD is of an unknown maker but has a part number of FXD096QQ08B-F, with a resolution of 80×160 pixels.

Given that the LCD is what makes this vape particularly special, I decided to look into what controller and pinout it uses. I had a hunch that it would use a common interface and controller (to keep costs low), and searched for a 0.96″ LCD with 13-pin FPC (flexible printed circuit) connector. This led me to the Smart Prototyping #102106, which used a 13-pin connector and seemed to have a compatible pinout. The aforementioned LCD uses a common ST7735S controller, and is controlled through a 4-wire SPI interface (clock, data, command/data select, chip select). (Additionally, I looked on Alibaba for a similar LCD, and found one source that sells them for about $1.25 each in large quantities; this suggests that the displays themselves add significant cost to the vape, but are still cheap enough to be utilized in a throwaway device.)

I searched other websites for LCDs with the same dimensions and connector, and they all used this pinout:

Pin Name Function
1 TP0/NC Unused (may be used for some touch sensor?)
2 TP1/NC Unused (may be used for some touch sensor?)
3 SDIN SPI data to LCD
4 SCLK SPI clock
5 RS Logic low = command, high = data
6 /RST Reset (active-low)
7 /CS Chip select (active-low)
8 GND Power supply/signal ground
9 NC Not connected
10 VDD Power supply (3.3V)
11 LEDK LED backlight cathode
12 LEDA LED backlight anode
13 GND Power supply/signal ground

To ensure that the pinout I was looking at really matched up with what was in the vape, I connected the data, clock and other control lines to my DSLogic Plus logic analyzer and sniffed the traffic as the vape initializes the display. A glance at the logic analyzer data confirmed the pinout.

To further confirm that I had an ST7735S-based display, I resoldered the LCD onto a TSSOP-to-DIP breakout board (which was annoying, as the pin pitch was slightly different and alignment needed much precision), and used the Adafruit Graphics Library and ST7735S driver on a Teensy 3.0 microcontroller, and it worked! Well, mostly. While black-and-white text worked perfectly, the red and blue channels seem to be swapped around when using the tft.initR(INITR_MINI160x80) routine, and it seems that I wasn’t the only one with this issue.

I decided I was finished with the idea of reusing the display alone, and began looking into how the vape itself works, and how it displays images. The first step was to look into the memory contents of the 1MB SPI Flash, as that is a pretty large amount of memory for such a simple device. I desoldered the chip and mounted it on a SSOP-to-DIP adapter, and dumped its contents to a file using my MiniPro TL866CS universal programmer.

My suspicions were confirmed when I analyzed the image data being sent to the LCD matching what was in the beginning of the SPI Flash. The data also looked like it was in a raw “RGB565” format, which is a method of packing a 16-bit pixel into two bytes of data; the term “565” refers to 5, 6, and 5 bit values belonging to the red, blue and green channels respectively. Since the image on the screen used blue in the top-left of the image, this supported my findings since the data similarly had only set bits belonging to the blue channel, and also further describes the data as being “big-endian” assuming that the red bits are read out before the green and blue.

The data seemed to be transferred in 4096-byte blocks, which I speculated to be performed using DMA (direct memory access); the data transfers seemed too fast and regular to be done in software alone. This later proved to be true when I had a chance to analyze the RAM of a working vape.

(Flash) Map-Making

With the 1MB SPI Flash chip dumped, it was time to take that apart too… but digitally! Armed with a spreadsheet, a hex editor, ImageMagick and an online RGB565 renderer by Rinky-Dink Electronics, it was time to begin the (grueling) process of unpacking the entire SPI Flash’s contents.

My first step was to try extracting the first image frame, which I calculated to be 25,600 bytes in size (80 x 160 x 2 bytes per pixel). The next step was to use ImageMagick to convert the raw RGB565 data into a PNG for viewing on a computer:

magick convert -size 80x160 rgb565:<file>.bin <file>.png

The result looked like an image, but the colours were all incorrect! I then tried the Rinky-Dink online RGB565 renderer, which didn’t have this issue. Most of my attempts were performed with ImageMagick since it was easy for me to carve and test different image sizes. (Later on, I decided to pipe in an RGB test image and it seems that ImageMagick interprets what should be RGB data as BRG…)

Attempting to convert the rest of the images felt like I was staring into The Matrix, trying to make sense of scrambled image data that looked like an autostereogram (the ones where you need to cross your eyes to form an image). Since the data on the Flash was raw and undocumented, I had no idea where each image began and ended, and what their resolutions were. It took a lot, and I mean a LOT, of trial and error to figure out the mappings.

This slideshow requires JavaScript.

One by one, I catalogued each image and added it to my spreadsheet, documenting its address, length, resolution, what category it belonged to, and if it was in a sequence of images (an animation, essentially).

This slideshow requires JavaScript.

This continued up until I was over 95% through the entire 1MB address space, and I even found unused animations (or at least unused for the version customized for my area). There was a bit of blank space, which I ignored for a while… but as it turned out, there was some other hidden data stored further down (it was the counter that the vape used to determine how many “bars” of juice to display). I won’t show the whole table since it’s over 100 rows long, but here’s an excerpt (you can find the whole table on my GitHub if you’re interested):

Index (#)

Offset (Hex)

Length (Hex)

Frame H (px)

Frame V (px)

Category

Seq (#)

0 0 6400 80 160 Background 0
1 6400 2880 72 72 Battery Icon 0
2 8C80 2880 72 72 Battery Icon 1
19 33D00 6400 80 160 Vaping Animation 0
20 3A100 6400 80 160 Vaping Animation 1
72 D53E2 6400 80 160 Plugin Background 3 0
73 DB7E2 E9A 21 89 Charger Logo Wipe 0
74 DC67C E9A 21 89 Charger Logo Wipe 1
104 F8000 4 N/A N/A Total Vape Time x0.01s (LSB->MSB) N/A
105 F8004 1 N/A N/A Vape In Use Flag (0xBB) N/A

Toolcrafting

With the whole SPI Flash mapped out, I was able to, with much help from ChatGPT, make a couple custom tools: a Flash image splitter and repacker. I also used the Rinky-Dink UTFT library‘s conversion tools to enable replacement of the image data (i.e. custom theme support). Imagine that – custom theme/skin support on a vape, now a reality! With no help from the manufacturer!

Rationale

You might be asking: why anyone would do this? Honestly… I’m not sure; I just was fascinated by a colourful disposable vape and just had to thoroughly take it apart and learn everything I could about how it worked. Maybe this could give a reason for people to attempt to refill (and therefore reuse) their disposable vapes, and a reused vape is a vape that doesn’t end up in the landfill or roadside – and frankly, that’s good enough reason for me.

With the tooling set up, it was time for me to prove that these vapes can be rethemed, and I thought of a great retro aesthetic that is completely different from the original theme, yet easy for me to make with simple image editing tools: Windows 95.

It runs Windows 95?!

Okay, not really… but I wanted a cohesive but entirely different theme to apply to the user interface, and I’m not nearly artistic enough to go about making a Doom theme (I tried, but couldn’t think of much that would work within the limitations of the original firmware). Using little more than a copy of Windows NT 4.0 (essentially the enterprise/professional version of Windows 95), some virtual machines, screenshot and recorder tools, and Microsoft Paint, I was able to create a UI that faithfully recreates the nostalgic Windows 95 user interface in a tiny 80×160 space.

Tip: if you need to frequently reprogram a device that uses an external (serial) memory chip, consider adding or making a socket for it. Additionally, vapes that use a 2-pin microphone element for inhalation sensing can be activated by shorting the pins to ground with a pushbutton, or even capacitively with your finger. If the vape requires a load to be present, a small halogen bulb will do the trick.

Main Screen

The main screen features the classic teal background, with two “windows” to represent the battery charge and vape juice levels. In keeping with Windows UI mechanics, the juice level is rendered as if it were an inactive window.

Battery Level

The battery icon, while looking trivial to implement, required a lot of manual work to create the icons. From Windows 95 through XP, the default Windows UI’s battery icons were very limited in granularity: full, half, near empty, and empty. I had to employ “tweening” techniques by copying rows of pixels and aligning them to the desired levels, then manually painting in pixels where required. I also used a slightly more-detailed icon set from Windows XP which added a bit more of a highlight on the left side of the icon, rather than a flat blue colour. While it does somewhat detract from the “purity” of the icon set, the improved appearance was worth the tradeoff.

Vape Juice Level

The juice level representation was a lot more challenging to conceive. I thought of using the Recycle Bin icon, but figured that making icons between empty and full wouldn’t produce a very unambiguous representation. I also thought about the magenta/blue pie chart used to represent disk usage, but that option was ruled out for similar ambiguity issues (I know that magenta is free space, and blue is used space, but this might not be intuitive enough without some sort of legend).

I finally figured that I had just enough room to make the world’s tiniest Explorer window, with just enough space for six 16×16 small icons. I picked a selection of icons that one would see in the C:\ root directory: folder, batch file, system file, application, .ini settings file, and unknown file (the one with a small Windows logo on it). As the vape juice is depleted, an icon is removed from the window. Once the juice is deemed by the microcontroller to be completely depleted, the blinking folder icon almost becomes homage to a similar phenomenon on Mac computers if it cannot find an operating system to boot.

Charging Animation

This one was another challenge, mainly due to the limited animation size of thirty 21×89 frames in an off-centre position atop a static background; not only that, the firmware dwells on the last animation for about a second, so any animation loop will need to stop cleanly at the last frame. The lack of animatable screen space meant that a file copy dialog was a non-starter, and the Windows 95 boot screen was also infeasible. I eventually settled on a small “Charging…” dialog box, with the animated hourglass cursor in the middle. One concession that I had to make was doubling each cursor animation frame, as well as losing one corner and edge of the hourglass during the initial animation sequence, as the hourglass is 22 pixels wide for the first few frames. Thankfully, this happens quickly enough that it isn’t particularly noticeable. I had pondered overlaying this dialog box atop the main UI’s “windows” but found the result to be too crowded in appearance, so a single dialog on the teal background was chosen instead.

Vaping Animation

This one was arguably the most fun yet the most frustrating to actually implement. I knew I wanted to use a screensaver for the vaping animation, but which one? I needed a screensaver that was both iconic, but also looped cleanly. Flying Windows was a contender, but proved to scale down poorly and, due to its random nature, looped poorly as well. 3D Flower Box was skipped for the same reason (and wouldn’t have looked good looping once per second anyway). 3D Maze, 3D Text, and the simple graphic screensavers like Marquee, Mystify and Beziers were out too… so what’s left? Only one screensaver was left in the pipeline… a 3D pipeline – heh, get it? 😉 (sorry. I’ll see myself out for that joke.)

3D Pipes is one of the most famous Windows 95-era screensavers, and despite its randomly-generated nature, had relatively clean transitions which make looping animations easier. It also scaled well both in terms of resolution and in time, but was an absolute pain to record. I eventually settled by running the Windows 95 version in a Windows XP virtual machine, with a custom screen size as close to a 1:2 aspect ratio as possible. After taking a screen recording, I had to then choose the sequence that looked the best, extract 16 frames from the video, scale those down to 80×160, and only then did I get my looped screensaver animation, but the result was well worth the effort. The particular run that I captured even had a flame-like shape to it!

Other Discoveries

With my main goal of extracting and replacing images on the vape accomplished, I decided to look further into its inner workings and learned a few things along the way.

A Secret Port

During my initial teardown, I noticed that the microcontroller’s SWD (Serial Wire Debug) programming lines were brought out to the USB-C port, but in an unusual way. The CC1/CC2 lines were not only used as regular 5.1k pulldowns to enable USB-C chargers to recognize the vape, but also as a programming connector. I had to build a custom cable to interface with it, but was able to use my Segger J-Link to communicate with the microcontroller in situ. As a bonus, the firmware is fully readable, without any encryption or readout prevention enabled!

It’s Not About The Puffs

For a device marketed with a capacity of several thousands “puffs”, one would think that this would be tracked as a means to provide a vape juice gauge to the user. However, this turned out to not be the case, in more than one way.

Vape Usage Counter

The vape usage/time counter at exactly 10 seconds of usage. 0x3E8 = 1000, or 10.00 seconds.

Unlike many other disposable vape implementations, the juice meter’s data was stored in a non-volatile memory location, since neither a reset nor power cycle would reset the meter back to full. I was initially unsure where the microcontroller was holding this variable, and scanning the internal Flash memory and the extra few “option bytes” available above the usual firmware region showed no changes. It wasn’t until I decided to run a difference on the external SPI Flash between “puffs”, where I noticed bytes changing near location 0xF8000, in a sea of empty/0xFF bytes. Erasing the bytes from locations 0xF8000-0xF8004 resulted in the vape juice meter resetting back to full! Since vape inhalation sensors typically include a 10 second timeout, I decided to trigger a 10-second “puff” and noticed the memory location had updated to 0x3E8, which corresponds to 1000 in decimal. It was then easy to determine that the microcontroller was counting vape time with 0.01-second granularity.

A Beeline to the Buffer

Since I had access to the microcontroller’s memories in near-real time, I decided to experimentally determine where the data from the SPI Flash was getting copied into RAM. Since I already knew the microcontroller was using DMA to stream image data from the SPI Flash, I figured that I could fill its entire contents with human-readable text (in my case, I chose consecutive copies of the “Bee Movie” script) and observe the RAM’s contents changing in Segger J-Mem. This technique worked immediately, and it was obvious where the DMA buffer was held in RAM!

Blinking Power, Hidden Version (Screen)

Out of boredom and wanting to repeatedly test the charging animation during development, I was rapidly connecting and disconnecting power to the charging port. After several consecutive fast insertions and removals, I saw a black screen with red text pop up. It read “GV-K23 0904V1” and trying to capture it was difficult until I had the idea to use J-Link Commander to halt the CPU as soon as I triggered it. Given that the version screen had text, yet I saw no text strings in the firmware dump, I figured it had to be a bitmap image, and it was! It was stored near the very end of the firmware. While identifying where it was inside the dump was simple, trying to reconstruct it from the dump was not. The extra padding of 0x00 bytes (basically black when interpreted as RGB565) that didn’t align with 60 pixel/120-byte rows, it took a lot of experimentation with image sizes and offsets until I got a legible picture. Even now I’m still not entirely sure if I’ve captured the entire bitmap.

Further Efforts

In the time between me starting this reverse-engineering/modding project and my publication of this blog post, I released my documentation and rudimentary tools on my GitHub profile in the hopes of drumming up more support from the community. Within days, another GitHub user by the name of “xbenkozx” was able to apply and extend my research into the external Flash memory mapping and debugging facilities. He created his own Flash dumping and modding tools, and even built custom reflashing firmware that only needed access to a SWD debugging/programming dongle and a custom cable – no surface-mount soldering required (i.e. programming that is beyond my current skillset 🙂 ). He also made more detailed analyses of various board revisions, and some important incompatibilities that could have resulted in damage due to overheating of the vape’s heating coil. Check it out!

Hopefully this reverse-engineering and reuse campaign can branch even further. Perhaps development environments (maybe an Arduino board profile?) or alternative firmwares can be developed to allow these boards to be reused in other applications, given that these vapes already provide easy access to a bright LCD screen, a decently powerful Arm microcontroller, Li-ion battery charging, and a megabyte of SPI Flash storage plus some extra LED indicators. Some board versions even have Rx/Tx pads for a UART serial port, which could make communication between different devices a possibility.

In terms of just theme creation, I made an editable template on my GitHub repository, with example bar graphs and animation frames denoting positioning and frame count. Maybe someone out there with more graphics/artistic/programming talent than me could figure out a way to “run Doom” on these vapes! 😀

Conclusion

Disposable vapes are almost everywhere, and their wastefulness goes beyond just some rechargeable batteries and circuit boards – some have bright LCD screens… and yet somehow these are considered throwaway devices!

If you have some of these LCD-equipped disposable vapes like the Kraze HD7K or RAZ TN9000, perhaps try playing around with them a bit. I’ve spearheaded a community campaign on GitHub to reverse-engineer these vapes, which allows them to be reused or repurposed more easily. If you want to take the path of reuse, I and some others have made customization and reflashing tools available. There is also potential in reusing just the microcontroller board since the vape features a pretty powerful microcontroller and a lot of storage space for images.

Unboxing and review of SanDisk 64GB microSDXC High Endurance Card

UPDATE (July 19, 2020): I’ve analyzed a 128GB version of the High Endurance card, and it appears that SanDisk is using 3D TLC Flash.

Dashcams: they can be a crucial tool when reconstructing events in a vehicular incident, or a source of entertainment when watching compilations on YouTube. Like any modern device, they generally use SD or microSD cards as their storage medium. However, not all cards are created equal.

Cheaper cards, like SanDisk’s Ultra lineup, use cheaper TLC (triple-level cell) NAND Flash that is ill-suited to the harsh working conditions of a dashcam. Not only does the card have to endure temperature extremes, the constant writes can burn through the Flash’s write cycles in short order. In fact, SanDisk specifically denounces this line of cards for use in continuous-recording applications.

The solution: high-endurance memory cards! These cards (at least in theory) use more durable MLC or even SLC NAND Flash, which can take many more write cycles. I purchased the 64-gigabyte model, the SDSQQNR-064G-G46A.

Unboxing

The card’s packaging isn’t much different than SanDisk’s typical microSD card offerings. The paper-and-plastic package includes a small blister pack that holds the microSD card itself and the full-size SD card adapter, without a carrying case (granted, the memory card is expected to stay inside the dashcam for most of its working life).

The packaging also includes a license key for a 1-year subscription to the RescuePRO data recovery software (although in all honesty, you’d be better off using the free PhotoRec software instead).

Endurance Rating

SanDisk’s lineup of high-endurance memory cards are designed for use in very write-intensive workloads, such as constant video recording.

Unfortunately, the endurance specifications for these cards are (probably intentionally) vague, only providing a set number of hours of video recording. However, we can infer a rating with a little bit of math.

SanDisk’s card packaging defines Full HD video to be 26 Mbps, which is equivalent to 3.25 (binary) megabytes per second. This equates to 11,700 megabytes per hour, or 11.426 gigabytes per hour. With a rating of 5,000 hours at this data rate, we get a specified endurance of 57,128.91 gigabytes written, or 55.79 terabytes written (TBW).

Memory cards, like other block-based storage media, often define capacities with decimal prefixes, whereas computers usually binary. A “64-gigabyte” card is really 59.605 binary gigabytes (“gibibytes“) in capacity, but in this blog post I’m using the Windows notation of gigabytes; that is, calculating in binary but displaying as decimal. 😛

Therefore, we get a final calculated P/E (program-erase) cycle count of… 936 cycles. This is more in line with traditional 2D TLC NAND Flash, so I suspect that this rating is either based on different bitrates, or SanDisk is being really, really conservative in their estimates – or heck, maybe this really is just TLC NAND Flash that’s being configured and/or warrantied differently by SanDisk. As much as I am tempted to remove the epoxy coating that covers the manufacturing test pads in order to get a NAND Flash signature directly, I like having a warranty for at least a few years. Maybe I’ll buy another card to try this on…

UPDATE (July 19, 2020): I got my paws on another card (the 128GB variant), and did some reverse-engineering work on it to determine what Flash SanDisk used. It turns out they used 3D TLC NAND, which is still quite durable and reliable due to the use of larger process geometries. The Flash should easily withstand thousands of write cycles without much issue.

Card Information

Using an older laptop with a true SD-compliant slot (most newer ones are just USB card readers internally), I was able to grab the card’s metadata from Linux. These information files are found in /sys/block/mmcblkX/device, where X is usually 0 depending on your host machine. Android used to be able to do this as well, but nowadays it’s not possible without a rooted operating system.

Item Value
CID (Card ID) 035744534836344780ed1bbb9e013100
CSD (Card Specific Data) 400e0032db790001dbd37f800a404000
Manufacturer ID 0x03 (SanDisk)
Manufacture Date January 2019
Device Name SH64G
Firmware Version 0x0
Hardware Revision 0x8

Initial Formatting

The card is formatted as exFAT, with a 16 MB offset (that is, the first 16 MB of the card is unallocated), with an allocation unit size of 128 kilobytes. It uses a very basic MBR (Master Boot Record) partition structure, with the first sector being the bare minimum to be recognized as a valid structure.

Performance

Now that I’ve probably irked some of my readers with my usage of decimal and binary prefixes, it’s time to see how fast this card can go. SanDisk’s own ratings for the card are very brief, citing a sequential read/write speed of 100 and 40 MB/s respectively. It is rated for the V30 Video speed classification, which guarantees a minimum of 30 MB/s sequential writes continuously.

All the tests below were performed on my desktop computer using a FCR-HS4 USB 3.0 reader from Kingston, which is based on the Realtek RTS5321 chipset.

CrystalDiskMark

CrystalDiskMark is the de-facto standard for storage benchmarks. I’m using the 64-bit edition of CDM, version 5.2.0.

I/O Type Read Write
Sequential QD32 91.80 MB/s 60.56 MB/s
Sequential 93.33 MB/s 61.66 MB/s
4K Random QD32 8.319 MB/s
2129.7 IOPS
4.004 MB/s
1025.0 IOPS
4K Random 8.121 MB/s
2079.0 IOPS
3.971 MB/s
1016.6 IOPS

The sequential I/O speeds are on par with a modern microSDXC card, and the IOPS aren’t too shabby either; they exceed the IOPS requirements for the A1 performance class which requires R/W IOPS of 1500 and 500 respectively. This could make this type of card a viable option for other write-heavy environments – this includes single-board computers (SBCs) like the Raspberry Pi, where memory card failures due to excessive writes are common.

ATTO Disk Benchmark

The card’s read/write performance levels off at around the 64-kilobyte mark during testing, showing that operations smaller than this incur a significant performance penalty. This may also be indicative of the internal page and block sizes of the NAND Flash itself.

Hard Disk Sentinel

Hard Disk Sentinel comes with a bunch of disk benchmarking tools, including some to test the entire “surface” of a drive. I used the software’s Surface Test tool to measure the card’s performance before and after filling the drive with data – first with random data, then with all zeroes.

Random Seek Test

The Random Seek Test measures the card’s latency when performing random “seeks”, although more accurately it reads a single sector from a random location.

State Average Latency Minimum Latency Maximum Latency
Empty/Initial (0x00) 360 µs 350 µs 420 µs
Random Fill 600 µs 590 µs 670 µs
Zero Fill 600 µs 590 µs 690 µs

The card initially had about 420 microseconds of latency, but after filling the card with random data, this increased to 670 microseconds. Filling the card with all zeroes again did not improve performance, and his isn’t helped by the fact that SD cards generally lack the ability to “TRIM” unused sectors like SSDs or eMMC chips.

Full Surface Read (or at least an attempt)

This is where things get a bit… interesting. It was around this time that I noticed some performance inconsistencies that didn’t show up on other benchmarks. Although the I/O speeds largely matched what my other benchmarks revealed, I noticed frequent dips below normal, often down to the mid-20 MB/s range! I wasn’t sure that this was necessarily the card’s fault (pauses in read/writes could result in performance degradation on a device if it can’t buffer the writes well enough), or if my card reader/operating system/etc. was responsible.

I decided to hold off on publishing the sequential write test until I get this issue figured out – perhaps it’s worthy of a blog post all on its own…

eMMC Adventures, Episode 1: Building my own 64GB memory card with a $6 eMMC chip

As seen on Hackaday!

There’s always some electronics topic that I end up focusing all my efforts on (at least for a certain time), and that topic is now eMMC NAND Flash memory.

Overview

eMMC (sometimes shown as e.MMC or e-MMC) stands for Embedded MultiMediaCard; some manufacturers create their own name like SanDisk’s iNAND or Hynix’s e-NAND. It’s a very common form of Flash storage in smartphones and tablets, even lower-end laptops. The newer versions of the eMMC standard (4.5, 5.0 and 5.1) have placed greater emphasis on random small-block I/O (IOPS, or Input/Output operations per second; eMMC devices can now provide SSD-like performance (>10 MB/s 4KB read/write) without the higher cost and power consumption of a full SATA- or PCIe-based SSD.

MMC and eMMC storage is closely related to the SD card standard everyone knows today. In fact, SD hosts will often be able to use MMC devices without modification (electrically, they are the same, but software-wise SD has a slightly different feature set; for example SD cards have CPRM copy protection but lack the MMC’s TRIM and Secure Erase commands. The “e” in eMMC refers to the fact that the memory is a BGA chip directly soldered (embedded) to the motherboard (this also prevents it from being easily upgraded without the proper tools and know-how.

When browsing online for some eMMC chips to test out, I found a seller that had was selling 64 GB eMMC modules for $6 Canadian per pop; this comes out to a very nice 9.375 cents per gigabyte (that’s HDD-level pricing right there!). With that in mind, I decided to buy a couple modules and see what I could do with them. A few days later, they arrived in the mail (and the seller was nice enough to send three modules instead of just two; the third module’s solder balls were flattened for some reason).

Toshiba eMMC Module

Toshiba THGBM4G9D8GBAII eMMC 4.41 modules

Toshiba THGBM4G9D8GBAII eMMC 4.41 modules

The Flash memory I used is a Toshiba THGBM4G9D8GBAII. According to a Toshiba NAND part number decoder:

  • TH: Toshiba NAND
  • G: Packaged as IC
  • B: Vcc (Flash power supply) = 3.3 V, VccQ (controller/interface power supply) = 1.8 or 3.3 V
  • M: eMMC device
  • 4: Controller revision 4
  • G9: 64 GB
  • D: MLC NAND Flash
  • 8: Eight stacked dice (eight 8 GB chips)
  • G: 24nm A-type Flash (appears to indicate Toggle Mode interface NAND)
  • BA: Lead-free and halogen-free
  • I: Industrial temperature grade (-40 to 85 degrees Celsius)
  • I: 14 x 18 x 1.2 mm BGA package with OSP (Organic Solderability Preservatives)

Given the low, low price of the eMMC chip, I had to make sure that I wasn’t given counterfeit Flash memory (often fake flash would have only 4 or 8 actual GB usable, with most of the address space looping over itself, causing data loss with extended usage). This involved find a way to temporarily connect the eMMC to my computer. I had a USB 2.0 SD/MMC reader on hand as well as a laptop with a native SD host interface, so now all I needed to do was break out the eMMC signals on the BGA package so that I can connect it to the reader.

eMMC Pinout… or is it Ball-Out?

There are plenty of pinouts for eMMC on the Internet, but they all show the pinout for a top view. Since I’m not soldering the eMMC to a PCB, I need to get a bottom view. I took a pinout diagram from a SMART Modular Technologies eMMC datasheet, rotated it to a landscape view, flipped it vertically, then flipped each row’s text in order to make it readable again. I then copy-pasted this into PowerPoint and traced out the package and ball pinouts. This allowed me to colour-code the different signal and power lines I’ll need to implement, including the data, clock, command and power lines. Curiously enough, one of the ground pins (VssQ, or controller/MMC I/O ground) was not a ground pin like the standard required; because of this, I decided to leave that pin open-circuit. Additionally, there were several pins that were not open-circuit, but did not have a known purpose either (these are probably used as test pads for the internal NAND Flash interface – perhaps they could be reused as raw NAND with the right controller, but the exact purpose of these pads will need to be reverse engineered).

Toshiba THGBM4G9D8GBAII eMMC pinout (solder balls facing up)

Toshiba THGBM4G9D8GBAII eMMC pinout (solder balls facing up)

eMMC Reader: Take 1 (Failed!)

For the first reader, I cut open a microSD-to-SD adapter, exposing the eight pins inside. I soldered a cut-up UDMA IDE cable and glued them in place. Despite my careful work, I still melted a hole through the thin plastic shell of the adapter; thankfully this did not affect the adapter’s ability to be plugged in.

I used double-sided foam adhesive tape and a piece of perfboard to create a small “test bed” for the eMMC module. Using some flux, solder wick, and a larger soldering iron tip, I removed all the (lead-free) solder balls on the center of the IC and replaced them with leaded solder bumps to make soldering the tiny 40-gauge magnet wire easier.

After bringing out the minimum wires required (VCC/VCCQ, GND, CLK, CMD, and DAT0 for 1-bit operation), I soldered the wires of my quick SD adapter, and plugged it into the SD card slot of a (very old) Dell Inspiron 9300.

Calling this board’s operation flaky doesn’t do it justice. It would fail to enumerate 9 out of 10 times, and if I even tried to do anything more than read the device capacity, the reader would hang or the eMMC would drop off the SD/MMC bus and show an empty drive in Windows. It was clear I had to do a full memory card “build” before I could verify the usability of the eMMC Flash memory.

eMMC in an SD Card’s Body: Take 1 (Success… half of the time)

I had a 16 MB (yes, megabyte) SD card lying around somewhere, but as usual, I couldn’t find it among all the clutter around my desk and workspace. Instead, I found an old, slow Kingston 2 GB SD card that I felt would be a worthy “sacrifice” since it was an older type that still had a thin PCB inside (most SD cards nowadays are monolithic, which means it’s one solid chunk with a few pads exposed). After opening up the case carefully with an Exacto knife, I wiggled out the old PCB. I desoldered the orignal 2 GB NAND Flash, and began work on breaking the SD card controller from the PCB as it was a chip-on-board design. It took a while, but I was able to ensure that none of the old SD card hardware would interfere with my rebuild.

I removed the eMMC from the board I made previously, and tested the thickness of it to ensure that it would fit inside the SD card case. It did, although the 0402 surface-mount decoupling capacitors I intended to install would cause a few bumps to be visible through the thin plastic SD card casing.

With my eMMC and SD card pinouts on hand, I used a small bead of epoxy to affix the eMMC to the PCB, balls-side up. I used magnet wire to connect the data lines (4 wires for 4-bit operation which is the maximum that the SD standard supports), and used the unused pads on the eMMC as a kind of prototyping space where I could install ceramic capacitors as close to the module as possible. I used a 0.1 µF 0402 size ceramic capacitor across the VDDi (eMMC internal regulator) and a neighouring GND pad. The rest of the power pads were wired in parallel with a few extra 0.1 µF capacitors added. I made use of the existing three 1 µF capacitors on the PCB as both extra decoupling and connection points for VCC and VCCQ. To prevent shorting of the inner CMD and CLK pins, I only removed the enamel coating from the magnet wire at the very end so I could solder them but avoid the issue of shorting those pins against the other signal and power lines. I then soldered these wires to the terminals on the other side of the PCB.

After spending about ten minutes wriggling the PCB into the SD card casing without damaging the wires, I used a multimeter to ensure all the pins were connected (use a multimeter in diode mode, with the positive lead connected to ground – any valid pins should read ~0.5 volts), and also ensured that there were no polarity reversals or shorts on the power pins.

Now… the moment of truth. At this point my USB 2.0 card reader still wasn’t cooperating with me, so I tried the only other ‘fast’ reader I had at the time – an SD to CompactFlash adapter.

To my relief, I finally got a (mostly) usable card. It appears this particular model has been pre-formatted with FAT32. Viewing the MBR in Hard Disk Sentinel shows nothing notable, apart from the fact that it’s pretty blank and is indicative that it wasn’t formatted for use as a PC boot medium.

Things began to fall apart after I tried running speed tests, as the card would hang if it experienced a lot of write activity at once. I suspected this was a power supply-related issue, so I modified my layout to add more capacitance. For good measure, I added 56 ohm termination resistance for the DAT0-4 data lines, using a small resistor network harvested from an old dead MacBook motherboard.

After these modifications, performance was much, much better. Now that the card was usable, I could finally run some speed tests.

eMMC in an SD Card’s Body – This time, with more feeling decoupling!

After adding several 100 nF and 1uF 0402-size ceramic capacitors on the eMMC package, I was able to get a stable card that could be read by (most) SD card readers. As I was rather anxious to get a decent benchmark from the eMMC, I decided to forego the cheaper Amazon Prime route, and go to my local PC parts store to buy a USB 3.0 card reader – the Kingston FCR-HS4.

After placing the eMMC and SD card PCB back into its plastic casing, I was relieved to see that Windows immediately recognized its presence. All I had to do then was open CrystalDiskMark and run the benchmark. Drum roll please…

Toshiba THGBM4G9D8GBAII/064G4A benchmark in CrystalDiskMark

Toshiba THGBM4G9D8GBAII/064G4A benchmark in CrystalDiskMark

Although I was happy to get a usable benchmark score, my belief that all eMMC devices inherently had better 4K random I/O speeds than their SD counterparts was immediately busted. My guess is that random I/O wasn’t considered to be a priority until eMMC 4.5 or 5.0, and my eMMC modules are only version 4.41.

eMMC module listed as version 4.41

eMMC module listed as version 4.41

After the speed test, I ran the card through the popular Flash memory testing tool h2testw to make sure that I was not given a counterfeit device.

H2testw showing flash memory is good

H2testw showing flash memory is good

Excellent – it’s a genuine device. Despite the slower performance than expected, I’m happy that the memory capacity is as it should be.

“eMMC identification and CSD data, please”

As is the case with any USB memory card reader, I cannot access any of the eMMC device information (that is, the CID/Card Information Data and CSD/Card Specific Data registers). I took a spare SSD from my collection and got a quick Windows 10 installation running on one of my laptops that had a native SD host interface.

eMMC identified as Toshiba 064G4A MMC

eMMC identified as Toshiba 064G4A MMC

Interesting. The eMMC identifies itself as a Toshiba 064G4A MMC card. Googling that information brought up literally zero information, so it appears I’m the only one to have found (or published) any information about it. Although eMMCs support some degree of S.M.A.R.T. health reporting like mainstream SSDs and HDDs, no (easily-available) software (for Windows at least) is available to read it.

Linux has the ability to report the CID and CSD data as long as the native SD host interface is used, as opposed to a USB card reader.

CID: 11010030363447344100151344014e00
CSD: d00e00320f5903ffffffffef96400000
date: 04/2011
enhanced_area_offset: 18446744073709551594
erase_size: 8388608
fwrev: 0x0
hwrev: 0x0
manfid: 0x000011
oemid: 0x0100
preferred_erase_size: 8388608
prv: 0x0
raw_rpmb_size_mult: 0x2
rel_sectors: 0x10
serial: 0x15134401

With the help of Gough Lui’s CID and CSD decoders, I was able to gain some more information about the eMMC device, but not too much as the information I was originally interested in was already collected by this point.

Out of the Reader and Back Into the (CF) Adapter

Now that I know what the eMMC is capable of, I decided to try putting it back into my SD-to-CF adapter and doing another benchmark.

eMMC in FC-1307A SD-to-CF adapter. Note the limited performance of this chipset.

eMMC in FC-1307A SD-to-CF adapter. Note the limited performance of this chipset.

This test highlights one of the biggest limitations of the FC1306T/FC1307A chipset that so many adapters use: their performance is limited to a maximum of 25 MB/s per channel. Good thing I purchased that USB 3.0 reader…

Conclusion

This was quite the learning experience. I not only learned that eMMC flash memory does not necessarily have the near-SSD performance that the latest devices offer, but I learned how to “exploit” the unused pads of a BGA device as a sort of “prototype area” for soldering small components onto.

Did I save any money by rolling my own Flash storage device? Absolutely not – given how much time I spent on this, if I paid myself minimum wage ($12 per hour where I live), I could have bought at least three higher-performance 64GB SDXC cards with none of the frustration of trying to adapt an embedded memory device as a removable memory card. But where’s the fun in that? 🙂

Teardown/review of Silicon Power 8GB 200x CompactFlash memory card

Hooray for nice hand-me-down SLR cameras! I finally have a better camera than the one built into my (now ancient) Samsung Galaxy S II that I use for pictures on this blog. The camera, a Canon EOS 50D, had an 8GB CompactFlash card that I was preparing to erase and reuse, and had problems trying to read out the card’s contents; a few stubborn files would refuse to copy and Explorer would simply hang until I restarted the program or unplugged the card. Additionally, when using my Hard Disk Sentinel program to do a surface scan, it too would freeze when reading a certain sector on the card.

Instead of using a USB-to-CompactFlash adapter (I could not find my card reader and have not seen it for over a year now, come to think of it) I used a CompactFlash-to-PATA adapter, then a PATA-to-SATA adapter so I could directly hook up the card to my computer. In addition to having greater theoretical throughput, it allows me to view the S.M.A.R.T. diagnostic data that the card provides.

Memory card issues and performance

The diagnostic information doesn’t really provide any insight into the health of the card; none of the S.M.A.R.T. attributes are listed as critical, and many of them are listed as vendor-specific. Oh well, at least it gave me some sort of information…

After finding a copy of the card’s contents on my home server (I seem to have previously backed up the card before the corruption occurred but didn’t recall doing so until I had raked through some of my archives), I decided I’d do a full card erase and see if it would cause the card to be usable again. I called up the Surface Test in Hard Disk Sentinel and used its surface-write tool to erase the user-accessible area of the card. A few blocks seemed to write dramatically slower than the rest and repeated write tests did not resolve their sluggishness; I call shenanigans with the memory card’s controller and its reluctance in reallocating problematic sectors…

The card itself isn’t very fast. The sequential I/O of the card is good enough for casual photography, but I would definitely not use this card in an embedded system that uses a CompactFlash as a sort of mini-SSD; even though it shows up in my system as a hard drive (non-removable), its random I/O is quite sluggish and its random write speed is worse than that of a standard hard disk drive.

Teardown

The card itself is a sandwich of aluminum plates, a plastic case and the PCB assembly that holds the controller, Flash memory and the CompactFlash connector. A hobby knife run under the aluminum plate was able to separate the plate from the plastic body; some glue and a couple clips were the only things holding the card together.

The card’s controller is a Phison PS3006, which sports a PCMCIA (and therefore CompactFlash) interface with True IDE (or plain PATA) support. It contains an 8051 microcontroller core with a few components to assist with interfacing with the Flash memory, such as a hardware ECC (error correction code) engine and a small amount of SRAM for a buffer.

The datasheet for the PS3006 doesn’t provide information on the S.M.A.R.T. attributes, nor does it indicate what type of Flash wear-leveling is provided. Given the controller’s limited computing capabilities, I’m thinking it uses a less-complex but less-reliable form of wear leveling, known as dynamic wear leveling (see Micron’s application note for more information). It’s less capable of dealing with memory wearout, but doesn’t require the computing overhead of static wear leveling (which proper SSD controllers use to keep performance up).

The memory is an Intel 29F32G08AAMD2 device, which is an asynchronous MLC NAND Flash memory chip. There are two installed on this card with another two footprints on the PCB being unpopulated, suggesting that the 16GB version of this card has all four footprints populated.

Conclusion

Given the simplicity of the card, I don’t really have much else to add about this card. Either way, it’s lost my trust with regards to holding my photos. I bought a NOS Disk 16GB CF card from Amazon as well as a SanDisk Extreme 32GB, and plan to use the latter to hold my photos, with the former mainly being a simple curiosity of the construction of a card from a lesser-known manufacturer. Hopefully those will also provide S.M.A.R.T. data, as I prefer Flash-based storage devices with some sort of S.M.A.R.T. data capability. (Is it an insatiable thirst for knowledge? A means of doing regular ‘check-ups’ on my storage device? Probably the latter, but maaayyyybe the former as well. 🙂 )