OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [sw/] [host/] [zipload.cpp] - Blame information for rev 51

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 31 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    zipload.cpp
4
//
5
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
6
//
7
// Purpose:     To load a program for the ZipCPU into memory, whether flash
8
//              or SDRAM.  This requires a working/running configuration
9
//      in order to successfully load.
10
//
11
//
12
// Creator:     Dan Gisselquist, Ph.D.
13
//              Gisselquist Technology, LLC
14
//
15
////////////////////////////////////////////////////////////////////////////////
16
//
17 51 dgisselq
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
18 31 dgisselq
//
19
// This program is free software (firmware): you can redistribute it and/or
20
// modify it under the terms of  the GNU General Public License as published
21
// by the Free Software Foundation, either version 3 of the License, or (at
22
// your option) any later version.
23
//
24
// This program is distributed in the hope that it will be useful, but WITHOUT
25
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
26
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
27
// for more details.
28
//
29
// You should have received a copy of the GNU General Public License along
30 51 dgisselq
// with this program.  (It's in the $(ROOT)/doc directory.  Run make with no
31 31 dgisselq
// target there if the PDF file isn't present.)  If not, see
32
// <http://www.gnu.org/licenses/> for a copy.
33
//
34
// License:     GPL, v3, as defined and found on www.gnu.org,
35
//              http://www.gnu.org/licenses/gpl.html
36
//
37
//
38
////////////////////////////////////////////////////////////////////////////////
39
//
40
//
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <sys/types.h>
44
#include <sys/stat.h>
45
#include <fcntl.h>
46
#include <unistd.h>
47
#include <strings.h>
48
#include <ctype.h>
49
#include <string.h>
50
#include <signal.h>
51
#include <assert.h>
52
 
53
#include "port.h"
54
#include "llcomms.h"
55
#include "regdefs.h"
56
#include "flashdrvr.h"
57 51 dgisselq
#include "zipelf.h"
58
#include "byteswap.h"
59 31 dgisselq
 
60
FPGA    *m_fpga;
61
 
62
void    usage(void) {
63
        printf("USAGE: zipload [-hr] <zip-program-file>\n");
64
        printf("\n"
65 51 dgisselq
"\t-h\tDisplay this usage statement\n"
66 31 dgisselq
"\t-r\tStart the ZipCPU running from the address in the program file\n");
67
}
68
 
69
int main(int argc, char **argv) {
70
        int             skp=0;
71 38 dgisselq
        bool            start_when_finished = false, verbose = false;
72 31 dgisselq
        unsigned        entry = 0;
73
        FLASHDRVR       *flash = NULL;
74 51 dgisselq
        const char      *bitfile = NULL, *altbitfile = NULL, *execfile = NULL;
75 31 dgisselq
 
76
        if (argc < 2) {
77
                usage();
78
                exit(EXIT_SUCCESS);
79
        }
80
 
81
        skp=1;
82
        for(int argn=0; argn<argc-skp; argn++) {
83
                if (argv[argn+skp][0] == '-') {
84
                        switch(argv[argn+skp][1]) {
85
                        case 'h':
86
                                usage();
87
                                exit(EXIT_SUCCESS);
88
                                break;
89
                        case 'r':
90
                                start_when_finished = true;
91
                                break;
92 38 dgisselq
                        case 'v':
93
                                verbose = true;
94
                                break;
95 31 dgisselq
                        default:
96
                                fprintf(stderr, "Unknown option, -%c\n\n",
97
                                        argv[argn+skp][0]);
98
                                usage();
99
                                exit(EXIT_FAILURE);
100
                                break;
101
                        } skp++; argn--;
102
                } else {
103 51 dgisselq
                        // Anything here must be either the program to load,
104
                        // or a bit file to load
105 31 dgisselq
                        argv[argn] = argv[argn+skp];
106
                }
107
        } argc -= skp;
108
 
109
 
110 51 dgisselq
        for(int argn=0; argn<argc; argn++) {
111
                if (iself(argv[argn])) {
112
                        if (execfile) {
113
                                printf("Too many executable files given, %s and %s\n", execfile, argv[argn]);
114
                                usage();
115
                                exit(EXIT_FAILURE);
116
                        } execfile = argv[argn];
117
                } else { // if (isbitfile(argv[argn]))
118
                        if (!bitfile)
119
                                bitfile = argv[argn];
120
                        else if (!altbitfile)
121
                                altbitfile = argv[argn];
122
                        else {
123
                                printf("Unknown file name or too many files, %s\n", argv[argn]);
124
                                usage();
125
                                exit(EXIT_FAILURE);
126
                        }
127
                }
128
        }
129
 
130
        if ((execfile == NULL)&&(bitfile == NULL)) {
131
                printf("No executable or bit file(s) given!\n\n");
132 31 dgisselq
                usage();
133
                exit(EXIT_FAILURE);
134 51 dgisselq
        }
135
 
136
        if ((bitfile)&&(access(bitfile,R_OK)!=0)) {
137 31 dgisselq
                // If there's no code file, or the code file cannot be opened
138 51 dgisselq
                fprintf(stderr, "Cannot open bitfile, %s\n", bitfile);
139 31 dgisselq
                exit(EXIT_FAILURE);
140
        }
141
 
142 51 dgisselq
        if ((altbitfile)&&(access(altbitfile,R_OK)!=0)) {
143
                // If there's no code file, or the code file cannot be opened
144
                fprintf(stderr, "Cannot open alternate bitfile, %s\n", altbitfile);
145
                exit(EXIT_FAILURE);
146
        }
147
 
148
        if ((execfile)&&(access(execfile,R_OK)!=0)) {
149
                // If there's no code file, or the code file cannot be opened
150
                fprintf(stderr, "Cannot open executable, %s\n", execfile);
151
                exit(EXIT_FAILURE);
152
        }
153
 
154 31 dgisselq
        const char *codef = (argc>0)?argv[0]:NULL;
155 51 dgisselq
        char    *fbuf = new char[FLASHLEN];
156 31 dgisselq
 
157
        // Set the flash buffer to all ones
158 51 dgisselq
        memset(fbuf, -1, FLASHLEN);
159 31 dgisselq
 
160 51 dgisselq
        FPGAOPEN(m_fpga);
161 31 dgisselq
 
162
        // Make certain we can talk to the FPGA
163
        try {
164
                unsigned v  = m_fpga->readio(R_VERSION);
165 51 dgisselq
                if (v < 0x20170000) {
166 31 dgisselq
                        fprintf(stderr, "Could not communicate with board (invalid version)\n");
167
                        exit(EXIT_FAILURE);
168
                }
169
        } catch(BUSERR b) {
170
                fprintf(stderr, "Could not communicate with board (BUSERR when reading VERSION)\n");
171
                exit(EXIT_FAILURE);
172
        }
173
 
174
        // Halt the CPU
175
        try {
176
                printf("Halting the CPU\n");
177
                m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_RESET);
178
        } catch(BUSERR b) {
179
                fprintf(stderr, "Could not halt the CPU (BUSERR)\n");
180
                exit(EXIT_FAILURE);
181
        }
182
 
183
        flash = new FLASHDRVR(m_fpga);
184
 
185
        if (codef) try {
186 51 dgisselq
                ELFSECTION      **secpp = NULL, *secp;
187 31 dgisselq
 
188
                if(iself(codef)) {
189
                        // zip-readelf will help with both of these ...
190
                        elfread(codef, entry, secpp);
191
                } else {
192
                        fprintf(stderr, "ERR: %s is not in ELF format\n", codef);
193
                        exit(EXIT_FAILURE);
194
                }
195
 
196
                printf("Loading: %s\n", codef);
197
                // assert(secpp[1]->m_len = 0);
198
                for(int i=0; secpp[i]->m_len; i++) {
199
                        bool    valid = false;
200
                        secp=  secpp[i];
201
 
202
                        // Make sure our section is either within block RAM
203
                        if ((secp->m_start >= MEMBASE)
204
                                &&(secp->m_start+secp->m_len
205 51 dgisselq
                                                <= MEMBASE+MEMLEN))
206 31 dgisselq
                                valid = true;
207
 
208
                        // Flash
209
                        if ((secp->m_start >= RESET_ADDRESS)
210
                                &&(secp->m_start+secp->m_len
211 51 dgisselq
                                                <= EQSPIFLASH+FLASHLEN))
212 31 dgisselq
                                valid = true;
213
 
214
                        // Or SDRAM
215
                        if ((secp->m_start >= RAMBASE)
216
                                &&(secp->m_start+secp->m_len
217 51 dgisselq
                                                <= RAMBASE+RAMLEN))
218 31 dgisselq
                                valid = true;
219
                        if (!valid) {
220
                                fprintf(stderr, "No such memory on board: 0x%08x - %08x\n",
221
                                        secp->m_start, secp->m_start+secp->m_len);
222
                                exit(EXIT_FAILURE);
223
                        }
224
                }
225
 
226
                unsigned        startaddr = RESET_ADDRESS, codelen = 0;
227
                for(int i=0; secpp[i]->m_len; i++) {
228
                        secp = secpp[i];
229
                        if ( ((secp->m_start >= RAMBASE)
230
                                &&(secp->m_start+secp->m_len
231 51 dgisselq
                                                <= RAMBASE+RAMLEN))
232 31 dgisselq
                                ||((secp->m_start >= MEMBASE)
233
                                  &&(secp->m_start+secp->m_len
234 51 dgisselq
                                                <= MEMBASE+MEMLEN)) ) {
235 38 dgisselq
                                if (verbose)
236
                                        printf("Writing to MEM: %08x-%08x\n",
237
                                                secp->m_start,
238
                                                secp->m_start+secp->m_len);
239 51 dgisselq
                                unsigned ln = (secp->m_len+3)&-4;
240
                                uint32_t        *bswapd = new uint32_t[ln>>2];
241
                                if (ln != (secp->m_len&-4))
242
                                        memset(bswapd, 0, ln);
243
                                memcpy(bswapd, secp->m_data,  ln);
244
                                byteswapbuf(ln>>2, bswapd);
245
                                m_fpga->writei(secp->m_start, ln>>2, bswapd);
246 31 dgisselq
                        } else {
247 51 dgisselq
                                // Otherwise writing to flash
248 31 dgisselq
                                if (secp->m_start < startaddr) {
249 51 dgisselq
                                        // Keep track of the first address in
250
                                        // flash, as well as the last address
251
                                        // that we will write
252 31 dgisselq
                                        codelen += (startaddr-secp->m_start);
253
                                        startaddr = secp->m_start;
254
                                } if (secp->m_start+secp->m_len > startaddr+codelen) {
255
                                        codelen = secp->m_start+secp->m_len-startaddr;
256 38 dgisselq
                                } if (verbose)
257
                                        printf("Sending to flash: %08x-%08x\n",
258
                                                secp->m_start,
259
                                                secp->m_start+secp->m_len);
260 51 dgisselq
 
261
                                // Copy this data into our copy of what we want
262
                                // the flash to look like.
263 38 dgisselq
                                memcpy(&fbuf[secp->m_start-EQSPIFLASH],
264 51 dgisselq
                                        secp->m_data, secp->m_len);
265 31 dgisselq
                        }
266
                }
267 38 dgisselq
 
268
                if ((flash)&&(codelen>0)&&(!flash->write(startaddr, codelen, &fbuf[startaddr-EQSPIFLASH], true))) {
269 31 dgisselq
                        fprintf(stderr, "ERR: Could not write program to flash\n");
270
                        exit(EXIT_FAILURE);
271 38 dgisselq
                } else if ((!flash)&&(codelen > 0)) {
272
                        fprintf(stderr, "ERR: Cannot write to flash: Driver didn\'t load\n");
273
                        // fprintf(stderr, "flash->write(%08x, %d, ... );\n", startaddr,
274
                        //      codelen);
275
                }
276 31 dgisselq
                if (m_fpga) m_fpga->readio(R_VERSION); // Check for bus errors
277
 
278
                // Now ... how shall we start this CPU?
279
                if (start_when_finished) {
280
                        printf("Clearing the CPUs registers\n");
281
                        for(int i=0; i<32; i++) {
282
                                m_fpga->writeio(R_ZIPCTRL, CPU_HALT|i);
283 38 dgisselq
                                m_fpga->writeio(R_ZIPDATA, 0);
284 31 dgisselq
                        }
285
 
286 38 dgisselq
                        m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_CLRCACHE);
287
                        printf("Setting PC to %08x\n", entry);
288
                        m_fpga->writeio(R_ZIPCTRL, CPU_HALT|CPU_sPC);
289
                        m_fpga->writeio(R_ZIPDATA, entry);
290
 
291 31 dgisselq
                        printf("Starting the CPU\n");
292
                        m_fpga->writeio(R_ZIPCTRL, CPU_GO|CPU_sPC);
293
                } else {
294
                        printf("The CPU should be fully loaded, you may now\n");
295
                        printf("start it (from reset/reboot) with:\n");
296
                        printf("> wbregs cpu 0x40\n");
297
                        printf("\n");
298
                }
299
        } catch(BUSERR a) {
300
                fprintf(stderr, "ARTY-BUS error: %08x\n", a.addr);
301
                exit(-2);
302
        }
303
 
304
        printf("CPU Status is: %08x\n", m_fpga->readio(R_ZIPCTRL));
305
        if (m_fpga) delete      m_fpga;
306
 
307
        return EXIT_SUCCESS;
308
}
309
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.