/* This file is part of JOP, the Java Optimized Processor (http://www.jopdesign.com/) Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ /** * Flash programming via TFTP. * * For new jopcore board with 512 KB flash. * * three file types: * * .ttf ACEX config start at 0x60000 * Cyclone config start at 0x40000 * .bin Java files start at 0x10000 (history of BB project) * .html start at 0x00000 * .class start at 0x30000 (for Applet Tal.class) * * Flash overview (in 64 KB sectors): * * 0x00000 : Java program * 0x10000 : HTML or longer Java program * 0x20000 : user data, Streckendaten in oebb BG263 * 0x30000 : Applet for TAL, bgid in oebb * 0x40000 : CYC config * 0x50000 : CYC config * 0x60000 : ACX, CYC config * 0x70000 : ACX, CYC config * * Changelog: * 2008-05-22 ACEX configuration disabled as we use a compressed bitstream for * the Cyclone and size detection does not work. */ package udp; import java.io.*; import java.util.*; public class Flash extends FlashConst { protected static final int FLASH_SIZE = 0x80000; protected static final int SECTOR_SIZE = 0x10000; protected static final int SECTOR_MASKx = 0xf0000; protected static final int SECTOR_SHIFT = 16; protected static final int MAX_ACEX = 32768*3; // 96kB (acex 1k50) protected static final int MAX_MEM = 65536*4; // 256kB (Cyclone) protected static final int MAX_JAVA = 16384*4*2; // max. 128KB protected static final int MAX_HTML = 1024; // max. 1KB protected static final int START_JAVA = 0x00000; protected static final int START_HTML = 0x10000; protected static final int START_DATA = 0x20000; protected static final int START_CONFIG = 0x30000; protected static final int START_ACX_TTF = 0x60000; protected static final int START_CYC_TTF = 0x40000; protected int start; protected String fname; protected byte[] mem; protected int len; private Tftp tftp; public Flash(Tftp t, String fname) { tftp = t; this.fname = fname; mem = new byte[MAX_MEM]; for (int i=0; i<MAX_MEM; ++i) mem[i] = (byte) 0xff; } public void read() { String line; StringTokenizer st; int pos; boolean isTtf = false; boolean isJava = false; boolean isHtml = false; boolean isAppl = false; int byteCnt = 0; len = 0; try { File f = new File(fname); String s = f.getName(); pos = s.indexOf('.'); if (pos==-1) { System.out.println("wrong filename"); System.exit(-1); } s = s.substring(pos); if (s.equals(".jop") || s.equals(".bin")) { isJava = true; start= START_JAVA; } else if (s.equals(".html")) { isHtml = true; start= START_HTML; } else if (s.equals(".class")) { isAppl = true; start= START_CONFIG; } else if (s.equals(".ttf")) { isTtf = true; // TODO: should be changed to an option // start= START_ACX_TTF; // assume a file for Jopcore (ACEX) start = START_CYC_TTF; } else { System.out.println("wrong file type: '"+s+"'"); System.exit(-1); } if (isJava || isTtf) { BufferedReader in = new BufferedReader(new FileReader(f)); while ((line = in.readLine()) != null) { if ((pos = line.indexOf('/'))!=-1) { st = new StringTokenizer(line.substring(0, pos), " \t\n\r\f,"); } else { st = new StringTokenizer(line, " \t\n\r\f,"); } while (st.hasMoreTokens()) { int val = Integer.parseInt(st.nextToken()); if (isJava) { mem[len++] = (byte) (val>>>24); mem[len++] = (byte) (val>>>16); mem[len++] = (byte) (val>>>8); mem[len++] = (byte) val; } else { mem[len++] = (byte) val; } if (len==MAX_MEM) { System.out.println("too many words"); System.exit(-1); } if (isJava && len==MAX_JAVA) { System.out.println("too many words for this Flash"); System.exit(-1); } } } in.close(); // if (len>MAX_ACEX) { // file is big, so it must be for Cyclone // start= START_CYC_TTF; // change start address // } } else { // 'binary' file InputStream in = new FileInputStream(f); len = in.read(mem); if (in.available()!=0) { System.out.println("file to long"); System.exit(-1); } if (isHtml) { mem[len] = 0; // end character for html files ++len; } else if (isAppl) { // length of class file in first two bytes for (int i=len-1; i>=0; --i) { mem[i+2] = mem[i]; } mem[0] = (byte) (len>>>8); mem[1] = (byte) len; len += 2; } } } catch (IOException e) { System.out.println(e.getMessage()); System.exit(-1); } System.out.println(len+" bytes to program"); } public void program() { int i, j; byte[] buf = new byte[SECTOR_SIZE]; byte[] inbuf = new byte[SECTOR_SIZE]; for (i=0; i<len; i+=SECTOR_SIZE) { int slen = SECTOR_SIZE; if (len-i<slen) slen = len-i; System.out.println("programming"); for (j=0; j<slen ; ++j) { buf[j] = mem[i+j]; } byte s = (byte) ('0'+((i+start)>>SECTOR_SHIFT)); System.out.println("sector "+(s-'0')); try { if (!tftp.write((byte) 'f', (byte) s, buf, slen)) { System.out.println(); System.out.println("programming error"); System.exit(-1); } System.out.println(); System.out.println("compare"); if (tftp.read((byte) 'f', s, inbuf)!=SECTOR_SIZE) { System.out.println(); System.out.println("read error"); System.exit(-1); } } catch (Exception e) { System.out.println(e); System.exit(-1); } for (j=0; j<slen; ++j) { if (buf[j] != inbuf[j]) { System.out.println("wrong data: "+(i+j)+" "+buf[j]+" "+inbuf[j]); System.exit(-1); } } } System.out.println("programming ok"); } public static void main (String[] args) { if (args.length < 2) { System.out.println("usage: java Flash file host"); System.exit(-1); } Flash fl = new Flash(new Tftp(args[1]), args[0]); fl.read(); fl.program(); } }