Half a megabyte is an awkward number. It is large enough that a product can carry a graphical interface and a communication stack, and small enough that the whole array still fits inside the first bank of the flash controller. The GD32F303CE sits exactly on that line: 512 KB of code space, 64 KB of SRAM, 120 MHz Cortex-M4, and the same 48-pin LQFP body as its quarter-megabyte sibling. For anyone who has to open one, the interesting part is not the size but the fact that the second bank never appears.
GigaDevice splits the array into two banks only when the density demands it. Bank zero covers the first 512 KB in pages of two kilobytes; bank one takes whatever remains in pages of four kilobytes. A CE therefore uses bank zero and nothing else, and the controller presents 256 uniform pages with no seam, no second control register and no second unlock sequence. That is a meaningful simplification. Every page in the device can be addressed with the same arithmetic, every erase takes the same path, and a script written for one region works unchanged on the other.
Memory begins at 0x08000000 and ends at 0x0807FFFF, with the last page starting at 0x0807F800. The information block sits above it at 0x1FFFF000, holding the two-kilobyte loader that only the factory can write, the sixteen-byte option block at 0x1FFFF800, and the signature area at 0x1FFFF7E0 where the flash and SRAM densities are recorded as plain kilobyte values. Reading those two halfwords is the cheapest way to confirm that a board really carries a CE rather than a smaller part with the same pinout. The the STM32F100C6 memory case case shows the same check on a sibling device, and it has saved more than one wrong order.
Because the array is single-bank, the mass erase command has exactly one target. In a two-bank device the operator has to decide whether to clear bank zero, bank one or both, and a mistake there leaves half an image behind. Here the controller’s mass erase bit in the control register clears the entire main array in a single operation, and there is no way to clear part of it except page by page. That is convenient for recovery and unforgiving for accidents: a stray erase on a single-bank part cannot be limited after the fact.
The protection model is unchanged from the rest of the family. A security byte of 0xA5 at 0x1FFFF800 leaves the array open; anything else closes it, and the first four kilobytes become erase-and-program protected at the same time. Under protection a debugger read faults, a write sets the error flag, and the only permitted action is to rewrite that byte, which triggers a full erase before the array becomes usable again. The option block stays reachable in every boot mode precisely so that this exit exists, and it is also why a protected part with a damaged option block is effectively scrap.
Dumping 256 pages at two kilobytes each is a quarter of a million words, and the transfer is paced by the debug interface rather than by the array. A practical arrangement reads in blocks, computes a rolling checksum per block, and writes the raw bytes to disk as it goes, so that a dropped connection costs one block rather than the session. Two passes separated by a power cycle catch the marginal cases: a page that reads differently on the second pass is usually a page at the end of its endurance, and it should be flagged in the report rather than silently averaged.
Interpreting the image is the part customers underestimate. Cortex-M4 code built for this part usually starts with a stack pointer in SRAM and a reset vector just past the vector table, and the first branch target tells you at once whether the image is complete. Where the vector table is present but the reset handler is blank, the product probably used a bootloader that lives in the upper pages, and the entry point will be found near the top of the array instead of the bottom. A comparable exercise on STM32F103C6 unlocking ran into exactly that layout, and a shorter one on STM32F102C6 firmware cloning did not.
The deliverable is a binary, a page map, the raw option block, and a short note on what the reset vector implies about the original build. Where the customer intends to resume production, the option block is as important as the code, since the write-protect mask and the reset behaviour bits travel with it. Two independent reads with matching hashes are the minimum standard before anything is described as complete, and that standard is what reverse engineering a chip is built around. Earlier work on an STM32F101C8 data clone and on STM32F102C4 embedded memory followed the identical checklist on the same controller.
The honest summary for a CE is that the die is easy to work with and hard to surprise. One bank, one page size, one erase bit, one security byte. What makes each job different is the board around it: how much of the debug port is exposed, whether the loader pins are pulled to a usable level, and whether the product resets itself faster than a fixture can hold it.