Forums » Software Development »
SPI NOR Flash memory map
Added by Thomas Catalino almost 12 years ago
(posted for a customer)
We are looking at using the SPI flash and/or NOR flash for storing our software on the L138 SOM. We are currently using uBoot and the exisiting boot code on the board so we do not want to overwrite these.
Could you provide a map of your use of NOR and NAND flash as initially occupied on a delivered board?
Also, could you provide the RAM address space used by uBoot? (Approximately).
Replies (6)
RE: SPI NOR Flash memory map - Added by Jonathan Cormier almost 12 years ago
This appears to be what your looking for.
MityDSP-L138_Architecture
Also can be determined by looking at the uboot environment variables. The erase commands give the starting address and the max size expected for each image.
U-Boot > print
...
flashuboot=tftp 0xc0700000 mityomap/u-boot-ubl.bin; sf probe 0; sf erase 0x10000 0x80000; sf write 0xc0700000 0x10000 ${filesize}
flashkernel=tftp 0xc0700000 mityomap/uImage; sf probe 0; sf erase 0x100000 0x280000; sf write 0xc0700000 0x100000 ${filesize}
flashubl=tftp 0xc0700000 mityomap/UBL_SPI_MEM.ais; sf probe 0; sf erase 0 0x10000; sf write 0xc0700000 0 0x10000
flashrootfs=tftp 0xc2000000 mityomap/mityomap-base-mityomapl138.jffs2; nand erase 0 0x08000000; nand write.jffs2 0xc2000000 0 ${filesize}
...
RE: SPI NOR Flash memory map - Added by Mary Frantz almost 12 years ago
This probably doesn't completely answer your question, but may be helpful. There is some "spare" memory on the SPI NOR flash.
On your target try:
root@mityomapl138:~# cat /proc/mtd dev: size erasesize name mtd0: 08000000 00020000 "rootfs" mtd1: 08000000 00020000 "homefs" mtd2: 00010000 00010000 "ubl" mtd3: 00080000 00010000 "u-boot" mtd4: 00010000 00010000 "u-boot-env" mtd5: 00010000 00010000 "periph-config" mtd6: 00050000 00010000 "reserved" mtd7: 00300000 00010000 "kernel" mtd8: 00200000 00010000 "fpga" mtd9: 00200000 00010000 "spare"
The "spare" section is an area you can read/write from linux programmatically. I don't know the starting address though.
Here's how to access from linux code:
#include <stdio.h> #include <error.h> #include <errno.h> void FLASH_read(unsigned long off, void * pDest, unsigned int size) { FILE *fd; fd = fopen("/dev/mtd9", "r"); if (fd == NULL) error(0, errno,"FLASH_read() called fopen():"); else { fseek(fd, off, SEEK_SET ); // move 'off' bytes from start fread(pDest, 1, size, fd ); fclose(fd); } } // end: FLASH_read() void FLASH_write(unsigned long off, void * pSrc, unsigned int size) { FILE *fd; fd = fopen("/dev/mtd9", "r+"); if (fd == NULL) error(0, errno,"FLASH_write() called fopen():"); else { fseek(fd, off, SEEK_SET ); // move 'off' bytes from start fwrite(pSrc, 1, size, fd ); fclose(fd); } } // end: FLASH_read()
RE: SPI NOR Flash memory map - Added by Fred Weiser over 11 years ago
Please allow me to chime in with a similar question... I have "reorganized" the upper part of the spi nor flash on my mityDspL138 module as I have a Linux kernel that is larger than the original allocation. I have modified the uboot environment variables to modify starting offset and size of the kernel and fpga locations, and the result seems to work fine; however, when I boot Linux and issue the "cat /proc/mtd" command shown earlier in this thread, the "kernel" area is still listed as the previous size. It seems I am missing something - how does the Linux kernel know where the spi nor flash partitions are? Is there a tool/procedure I should be using when reorganizing the spi nor flash to be sure everything is in synch? And is there a Linux command like "cat /proc/mtd" that shows starting offsets (or something in /sys/class/mtd perhaps)? --Thanks.
RE: SPI NOR Flash memory map - Added by Michael Williamson over 11 years ago
The SPI partitions are defaulted in the board-mityomapl138.c file in arch/arm/mach-davinci in the spi_flash_partitions[] structure. This is where the kernel is getting these values.
If you want the partitions to show up right in MTD, you'll need to modify this file, or it should be possible to override the default partitions table using the mtdparts kernel command line option if you have command line MTD partitions enabled (should be by default for MityDSP-L138 builds). We do this for the NAND quite often but I believe the NOR should also be supported. Something like:
bootargs mem=96M console=ttyS1,115200n8 ... mtdparts=nor:64k@0(ubl),512K@64k(u-boot), ....
I haven't tested this, if I get some time I will, but this might be enough of a hint?
-Mike
RE: SPI NOR Flash memory map - Added by Michael Williamson over 11 years ago
BTW:
It's not entirely clear to me if the write routine above will work properly. I don't know for sure, off-hand, if the driver is smart enough to do a FLASH erase prior to the write. And if it does, be aware that you will be erasing an entire sector not just the data you are interested in. But... the drivers may be OK there.
The MTD utility library (mtd-utils) might be a good option for managing the SPI interfaces.
-Mike
RE: SPI NOR Flash memory map - Added by Mary Frantz over 11 years ago
You are correct, Mike. The flash does have to be erased before writing. Here is a more fleshed out version of my code. It includes some checking for valid data before reading using a header, which others may not need but you get the idea...
unsigned int FLASH_read(unsigned int sector, void * pDest, unsigned int size) { mtd_info_t mtd_info; int fd; unsigned int n = 0; FLASHINFO fInfo; unsigned char *pTemp; fd = open("/dev/mtd9", O_RDONLY); if (fd < 0) error(0, errno,"FLASH_read() called open():"); else { ioctl(fd, MEMGETINFO, &mtd_info); lseek(fd, mtd_info.erasesize * sector , SEEK_SET ); // move to given sector read(fd, &fInfo, sizeof(fInfo)); // get header if (fInfo.length == 0xFFFF) // erased, don't read n = 0; else { n = (fInfo.length <= size) ? fInfo.length : size; // use valid data up to size of destination buffer lseek(fd, (mtd_info.erasesize * sector) + sizeof(fInfo) , SEEK_SET ); // move past header // read flash // TODO: use permanent buffer rather than malloc? pTemp = (unsigned char *)malloc(n); if (pTemp == NULL) n = 0; else { read(fd, pTemp, n); // read into temporary buffer // Checksum if (fInfo.cs == checksum(pTemp, n)) // verify checksum memcpy(pDest, pTemp, n); // data ok, copy to destination else n = 0; free(pTemp); } // endelse: malloc } // endelse: erased close(fd); } // endelse: fd < 0 return n; } // end: FLASH_read() void FLASH_store(unsigned int sector, void * pSrc, unsigned int size) { mtd_info_t mtd_info; int fd; erase_info_t ei; FLASHINFO fInfo; fd = open("/dev/mtd9", O_RDWR); if (fd < 0) error(0, errno,"FLASH_write() called open():"); else { ioctl(fd, MEMGETINFO, &mtd_info); printf("MTD type: %u\n", mtd_info.type); printf("MTD total size : %u bytes\n", mtd_info.size); printf("MTD erase size : %u bytes\n", mtd_info.erasesize); // Erase sector ei.start = sector * mtd_info.erasesize; ei.length = mtd_info.erasesize; ioctl(fd, MEMUNLOCK, &ei); ioctl(fd, MEMERASE, &ei); // write header fInfo.length = size; fInfo.cs = checksum((unsigned char *)pSrc, size); lseek(fd, ei.start, SEEK_SET); // move to start of sector write(fd, &fInfo, sizeof(fInfo)); // write lseek(fd, ei.start + sizeof(fInfo), SEEK_SET); // move to end of header write(fd, pSrc, size); // close close(fd); } } // end: FLASH_store()
Mary