Flash memory is critical component to any system, and it’s important to be able to access flash memory efficiently. In this document, we will look at the differences between the two main types of flash used today, NAND flash and NOR flash, how to erase and access flash. Then we will look at the MQX flashx driver, which can be used for both types of flash.
Accessing NOR and NAND Flash
There are two main types of flash memory, the first being nor flash , and the second being nand. For an interface point of view, the main difference is how the data is accessed. Nor flash is a full address and data bus, similar to random devices, and nand devices is using io bus with commands , address and data being multiplexed to share the same bus. It is greatly reduces the number of pins to require connectivity in devices , But for software and data access perspective , there are more significant differences between the two types of memory.
At the core, each bit is storing using different tech knowledge. With nor flash , the memory region is divided by equal size units called blocks. The size of each block in today’s technology ranges from roughly 32k bytes to 128 kbytes, but this is totally dependent on the devices select and over the years this is changed. The internal circuitry of nor flash allows each byte of the device can be individually addressable in the same way that you can address bytes stored in ram, or in an EEPROM and this is why a full bus is used with nor flash. However this only applies for reading a byte or programming an individual byte, the racing skimming must be done at the block level, so unlock a race state requires the entire block to be affected.
Nand flash , however, has being purposely architected differently in order to increase the storage density. It too has a memory region divided in equal size of blocks, but each of these blocks are further broken down into samll regions that are called pages, the page is typically 2k bytes in size and a block often has 64 pages, so 128 kbytes , to the lead data you still be working at the block level, but if you want to read and program part of flash, this is done page by page.
However storing or retrieving data one page at a time is actually an advantage for many applications. Since you are often working with a large files such as a phone, a song or an app. So this is can be more efficient. The main draw back then of not being able to access bytes individually is that nand flash can’t be used to store a program code that you want to be executed in place. Since a CPU needs to read a single instruction, unless your CPU can specifically support this arrangement. There are a couple of downsize that the nand flash you maybe aware of however, the first is in getting bit errors when you reading a page, this is may not be a disater for musical file but obviously not acceptable for a data file or a backup for your image.
To compensate for this , each page of flash has two sections, the first is where your data is stored and the second is a smaller section is where error correction code is stored. There are differenct algorithm used to detect and correct for errors but the ideal is the data stored in ecc is used by the algorithm to detect errors in the data, and in some cases correct an error in the data field. There is a limit to how much corruption can be detected, but minor errors such as a single bit error are dealt with regular basis without the application ever knowing it occurred.
The second issue with nand to be aware of that it is more prone to developing a faulty bit. And this is caused an entire block to be declared as being bad, in fact even a new flash device will have a small percentage of blocks bad and over time some of the active blocks can be come bad. Circuitry in the flash device detects the block’s bad during erase or progam cycle and a bad block manager keeps track of this . Blocks of bad are automatically remapped, and since this happens behind, the interface of software doen’t know the difference.
So to summarize the key differences between nor and nand, we saw you have to access data in pages with nand which is randly access in bytes . and there are differences in access time to erase, write and read from flash. The capacity the flash device contiues to rise for writes that is a steady rate, but currently the largest nand devices have 10 times capacity of largest nor devices. And in terms of issues don’t impact the application code, we saw the nand flash requries bad block management and error correction codes to deal with failure rate that experiences, the pin count is higher in nor given a type of interfaces has, which couple of with different capacity makes it more expencsive. And depending on how you using memory you maybe concered about the expected life cycle of a chosen device .
Before getting into the driver though, the only other thing to cover you may come across when working with the flash has to do with the erase process, you may expect to read back the erased portion of memory has been all zeros but in fact the erased flash memory has all bits set to the high state, so it read back the erased byte as being FF.
When you write data to your address location , the corresponing bits need to be zero are programed as logical zero and efficiently you can rewrite this location with first erase it providing you unwanted any of these bits transition from 0 to 1. You can also write to a different address in the same block without first erasing block, but in most cases you writing a large chunk of data, not a single byte, and typically you don’t want to bother keeping in track of data as being where to written to . And for block should be erased before write or not. This is what the driver does for you, which keeps your application quite simple, however, be aware the overhead associated with the right command won’t always be consistant. As you sometimes you endure an erase and rewrite cycle, and other times you won’t.
Where Flashx Driver Resides
There are two groups of drivers in MQX, the first group contains io drivers, go through the io subsystem. And it includs block mode drivers and byte mode drivers . The second group is a set of low level drivers such as the ADC and the lightweight GPIO driver. Since flash driver supports the writing and reading data of large chunks, it is categorized as blocked mode driver . In the SDK verison of MQX, the io sub system is limited. But the flash driver is still be considered as block mode driver.
Similar to the structure of other drivers we’ve looked at, there is an upper layer and lower layer component in the flash driver. and before you can begin using any dirver, it has to be installed. If you selected flash using a configuation file, MQX will automaticly install the flash driver at boot up. And when you install function is called, the upper level will install function is passed a pointer to the low level configuration information.
The installed function registered it’s called back function to the IO subsystem, once it’s associations are in place , your application code can use a normal a high level calls that access the flash device. So for example, before using the flash driver , you must open it , which will set up internal structures for the flash chip if hasn’t been opened before. And will fetching the addressing for this device . You can then read from flash or write to it as you like using the high level commands.
Before getting further with using the driver though, it will be helpful to see how to access the flash itself. The flash is organized to a series of blocks and you can structure those in different groups. If you are using a kinetis processor, and using the flashx driver to access the internal flash, then as a minimum you need have a room for code base and reserve a saparate area for your data.
You can also set your flash for equal size banks or however you wish to organize your flash, just keeping in mind the boundaries of these regions must be falled into block boundaries in the flash . Each of these regions are effectively a partition of the flash and the flashx driver refer to each partition is a file or see in a monent the region of a flash you use for a file may not be continuously from address point of view , but for application point of view it can be considered to be continuous memory space.
Mqx maitans an index into a file and when you read from the file, the reading starts from an index, similarly, when you write to the file, it starts writing from the index point , and the index commands , as you wirte more data. Your application code can adjust the location index, using the fseek function , you maybe familiar with the fseek function found in a formatted io section of starndard C library , and mqx’s fseek function is used in the same way. It can be used to set the index to provide the offset from the beginning of a file, with an offset from the end of this file , or to an offset in either direction from the current position of the index.
To understand flashx driver how it works , you need to farmilar with some key data structures that it uses. The first one to cover is the block info structure which defines how the flash is organnized. Some flash has different size blocks inside of it or maybe there is gaps between addressing . So this is a way of define a flash infrastructure.
Your device will be represented by an array or a block info structures, one section for each section a flash has continuous addressing and all blocks are in equal size. The terminal is a bit confusing here, within each section of flash there will be a number of blocks, and the data structure refers to is a sector, as mqx considers a sector to be the smallest eraseable units.
The next element of this structure is the starting address of this section which is followed by the size section. The final element is reserved for any special flags and currently not being used.
You can have a number of files in flash, the file block structure is used to define a file, and it cantains a name for the file , the starting address for the file, and an ending address for the file,
And the third data structure called the init structure is used to tie everything together , this contains a pointer to a array of block info structure, and a pointer to a array of file block structures, this also contains the base address of the flash device and some additional elements used to access the total flash address base .
Flash Driver API
So to summarized before we look at the driver code, accessing the flash is very straight forward. You must open the file with the fopen function , and with the flashx driver , flags are not typically used. To read from the file , you speciafy with reading data to be stored , and the number of bytes to read. And to write the flash you should provide a pointer to the data to be written, and the numbe of bytes to transfer. And the last function we used, is the ioctl function, which can be used to retrieve or change the various parameters. When you using the ioctl function, you specify the command you want to use. And a point to where the result will place if you request a value as parameter . So what source code can you make . you can retriev various values, such as the base address, or the number of sectors. You can flush the buffer, or control the buffering feature, erase all or part of flash chip, control the sector caching, or control the write protect.
This document is the 19th Installment of the "Essentials of MQX RTOS Application Development" training course. Please watch the vedio for more details