Commit 697602d1 authored by Dimitris Lampridis's avatar Dimitris Lampridis

[sw/tools] Update svec-flasher to work with new Flash memory.

The Flash memory chip used on the SVEC is obsolete. The new one has a different ID
and sector size. Update the svec-flasher tool to work with both type of memories.

Also update documentation accordingly.

See also:
https://www.ohwr.org/project/svec/issues/19
https://forums.ohwr.org/t/wrtd-installation-instructions/848300/11Signed-off-by: Dimitris Lampridis's avatarDimitris Lampridis <dimitris.lampridis@cern.ch>
parent 935ebe1a
......@@ -12,6 +12,7 @@ Fixed
-----
- [hdl] DDR constraints
- [hdl] DDR controller generic values are now properly capitalised
- [sw] Update svec-flasher to work with new type of flash memory used in newer SVEC boards
[1.4.6] 2019-12-16
==================
......
......@@ -35,6 +35,11 @@
@setchapternewpage off
@tex
\global\def\linkcolor{0.5 0.09 0.12}
\global\def\urlcolor{0.5 0.09 0.12}
@end tex
@set update-month November 2014
@include git_revision.in
......@@ -52,7 +57,6 @@
@end iftex
@c ##########################################################################
@node Top
@chapter Introduction
This document describes the default bitstreams that come preloaded with every SVEC card. As there are two FPGAs on the SVEC, there are two default bitstreams:
......@@ -114,14 +118,14 @@ Programming the Application FPGA directly via VME involves the following steps:
@item Exit bootloader mode by writing 1 to @code{CSR.EXIT} bit.
@end itemize
A code example is available in the repository (@pxref{repo_link,,2}). Successful gateware download to the Application FPGA is indicated by turning on the ``AFPGA DONE'' LED in the middle of the PCB.
A code example is available in the repository (@pxref{repo_link,,3}). Successful gateware download to the Application FPGA is indicated by turning on the ``AFPGA DONE'' LED in the middle of the PCB.
@section Programming the Flash
The SFPGA also allows raw access to the Flash memory (M25P128) via the @code{FAR} register. The code below shows how to execute a single SPI transaction (command + N data bytes).
The SFPGA also allows raw access to the Flash memory (M25P128 or MT25QL128 in newer SVEC cards) via the @code{FAR} register. The code below shows how to execute a single SPI transaction (command + N data bytes).
Low-level details about programming M25Pxxx series Flash memories can be found in their datasheets (@pxref{m25p_datasheet,,1}). A simple VME flasher is provided in @code{software/vme-flasher} directory.
Low-level details about programming the Flash memories can be found in their datasheets (@pxref{m25p_datasheet,,1} and @pxref{mt25_datasheet,,2}). A simple VME flasher is provided in @code{software/vme-flasher} directory.
@b{Note 1:} It is advised to protect the region of the flash containing the system FPGA bitstream from being accidentally overwritten, as this will result in rendering the card unusable and will require re-programming the flash via JTAG. Details on memory protection can be found in the M25P series datasheet.
@b{Note 1:} It is advised to protect the region of the flash containing the system FPGA bitstream from being accidentally overwritten, as this will result in rendering the card unusable and will require re-programming the flash via JTAG. Details on memory protection can be found in the Flash memory datasheet.
@b{Note 2:} The freshly-programmed bitstreams will be loaded into the FPGAs after power-cycling the card. In order to avoid the power cycle, one can boot the Application FPGA directly using the same bitstream.
......@@ -134,7 +138,7 @@ The flash memory of the SVEC contains 16 Megabytes of data, that is 65536 pages
@item @code{0x601000 - 0xffffff}: Free space, foreseen for the AFPGA's private data storage.
@end itemize
An example script for building the default flash filesystem (containg the bootloader and golden bitstreams) is located in the @code{software/sdb-flash} subdirectory in the SVEC project's repository(@pxref{repo_link,,2}). Presence of the SDB descriptor table at @code{0x600000} is checked by the bootloader to prevent booting up from a corrupted or unprogrammed flash.
An example script for building the default flash filesystem (containg the bootloader and golden bitstreams) is located in the @code{software/sdb-flash} subdirectory in the SVEC project's repository(@pxref{repo_link,,3}). Presence of the SDB descriptor table at @code{0x600000} is checked by the bootloader to prevent booting up from a corrupted or unprogrammed flash.
@b{Note:} Both bitstreams must be in raw (@code{.bin} file extension) format. @code{.bit}, @code{.mcs}, @code{.xsvf} and other formats will not work.
......@@ -240,7 +244,7 @@ Certain older SVEC cards have been shipped with the first version of the bootloa
@item Open the right-click menu in the main work area and select ``Initialize chain'' or press Ctrl+I.
@item Right click on the ``SPI/BPI ?'' box above the ``xc6slx9'' FPGA and select ``Add SPI/BPI Flash''.
@item Pick the @code{svec-bootloader-[latest release].mcs} file.
@item Select flash type: SPI PROM, M25P128, data width: 1.
@item Select flash type: SPI PROM, M25P128 (or N25P128 if you have a newer SVEC with a MT25QL128 Flash memory chip), data width: 1.
@item Right click on the ``FLASH'' chip above the ``xc6slx9'' and select ``Program''. Select the ``Verify'' option and click OK.
@item If everything went fine, ``Programming succeeded'' message will appear.
@item Reboot the VME crate to use the new bootloader.
......@@ -307,6 +311,8 @@ NET "flash_miso_i" IOSTANDARD = "LVCMOS33";
@enumerate
@anchor{m25p_datasheet}
@item @uref{http://www.micron.com/parts/nor-flash/serial-nor-flash/m25p128-vme6gb} - M25P series SPI Flash memory datasheet
@anchor{mt25_datasheet}
@item @uref{https://www.micron.com/-/media/client/global/documents/products/data-sheet/nor-flash/serial-nor/mt25q/die-rev-a/mt25q_qlhs_l_128_aba_0.pdf} - MT25QL128ABA series SPI Flash memory datasheet
@anchor{repo_link}
@item @uref{http://www.ohwr.org/projects/svec/repository/} - Git repository containing this document's sources and revision history (@code{doc} subdirectory) and bootloading code examples (@code{software/sveclib} subdirectory).
@end enumerate
......
......@@ -14,6 +14,7 @@
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <libvmebus.h>
//#include <libsdbfs.h>
......@@ -26,9 +27,11 @@
#define BOOTLOADER_SDB_BASE 0x600000
#define ID_M25P128 0x202018
#define ID_MT25QL128 0x20BA18
#define FLASH_PAGE_SIZE 256
#define FLASH_SECTOR_SIZE 0x40000
#define FLASH_SECTOR_SIZE_M25P128 0x40000
#define FLASH_SECTOR_SIZE_MT25QL128 0x10000
#define FLASH_SIZE 0x1000000
/* M25Pxxx SPI flash commands */
......@@ -228,16 +231,32 @@ void flash_program_page(uint32_t addr, const uint8_t * data, int size)
flash_wait_completion();
}
void flash_program(uint32_t addr, const uint8_t * data, int size)
int flash_program(uint32_t addr, const uint8_t * data, int size, uint32_t flash_id)
{
int n = 0;
int sector_map[FLASH_SIZE / FLASH_SECTOR_SIZE];
int ret = 0;
int sector_size;
int *sector_map;
if (flash_id == ID_M25P128)
sector_size = FLASH_SECTOR_SIZE_M25P128;
else if (flash_id == ID_MT25QL128)
sector_size = FLASH_SECTOR_SIZE_MT25QL128;
else
return -ENODEV;
sector_map = (int *)malloc(sizeof(int) * FLASH_SIZE / sector_size);
if (sector_map == NULL)
return -ENOMEM;
memset(sector_map, 0, sizeof(sector_map));
const uint8_t *p = data;
while (n < size) {
int plen = (size > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE : size);
int sector = ((addr + n) / FLASH_SECTOR_SIZE);
int sector = ((addr + n) / sector_size);
if (!sector_map[sector]) {
flash_write_enable();
......@@ -270,17 +289,20 @@ void flash_program(uint32_t addr, const uint8_t * data, int size)
fprintf(stderr,
"Verification failed at offset 0x%06x (is: 0x%02x, should be: 0x%02x)\n.",
addr + n, d, *p);
spi_cs(0);
exit(-1);
ret = -EINVAL;
goto flash_program_exit;
}
}
flash_program_exit:
spi_cs(0);
free(sector_map);
return ret;
}
int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
{
int ret = 0;
printf("Programming the Application FPGA flash with bitstream %s.\n",
name);
......@@ -291,11 +313,14 @@ int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
return -1;
}
if (flash_read_id() != ID_M25P128) {
fprintf(stderr,
"Flash memory ID invalid. You are probably be running an old version\nof the bootloader that doesn't support flash programming via VME.\n");
return -1;
uint32_t flash_id = flash_read_id();
if ((flash_id != ID_M25P128) && (flash_id != ID_MT25QL128)) {
fprintf(stderr, "Flash memory ID invalid (0x%.8x). ", flash_id);
fprintf(stderr, "You are probably running an old version of the bootloader\n");
fprintf(stderr, "that doesn't support flash programming via VME.\n");
return -ENODEV;
}
printf("Flash ID: 0x%.7x, OK\n", flash_id);
if(program_boot)
{
......@@ -310,14 +335,19 @@ int program_flash(char *name, uint8_t *buf, size_t size, int program_boot)
printf("Bootloader update aborted.\n");
return -1;
}
flash_program(0, buf, size);
ret = flash_program(0, buf, size, flash_id);
} else {
flash_program(BOOTLOADER_SDB_BASE, sdb_header, sizeof(sdb_header));
flash_program(BOOTLOADER_BITSTREAM_BASE, buf, size);
printf("Programming OK.\n");
ret = flash_program(BOOTLOADER_SDB_BASE, sdb_header, sizeof(sdb_header), flash_id);
if (ret == 0)
ret = flash_program(BOOTLOADER_BITSTREAM_BASE, buf, size, flash_id);
}
return 0;
if (ret == 0)
printf("Programming OK.\n");
else
printf("Flash programming failed with error %s\n", strerror(ret));
return ret;
}
int program_afpga(char *name, uint8_t *buf, size_t size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment