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

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [fx3/] [ztex-flash.c] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
/*%
2
   ZTEX Firmware Kit for EZ-USB FX3 Microcontrollers
3
   Copyright (C) 2009-2017 ZTEX GmbH.
4
   http://www.ztex.de
5
 
6
   This Source Code Form is subject to the terms of the Mozilla Public
7
   License, v. 2.0. If a copy of the MPL was not distributed with this file,
8
   You can obtain one at http://mozilla.org/MPL/2.0/.
9
 
10
   Alternatively, the contents of this file may be used under the terms
11
   of the GNU General Public License Version 3, as described below:
12
 
13
   This program is free software; you can redistribute it and/or modify
14
   it under the terms of the GNU General Public License version 3 as
15
   published by the Free Software Foundation.
16
 
17
   This program is distributed in the hope that it will be useful, but
18
   WITHOUT ANY WARRANTY; without even the implied warranty of
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
   General Public License for more details.
21
 
22
   You should have received a copy of the GNU General Public License
23
   along with this program; if not, see http://www.gnu.org/licenses/.
24
%*/
25
/*
26
    SPI flash support.
27
*/
28
 
29
#include "cyu3system.h"
30
#include "cyu3os.h"
31
#include "cyu3usb.h"
32
#include "cyu3spi.h"
33
#include "cyu3dma.h"
34
#include "cyu3error.h"
35
 
36
#define ZTEX_SPI_DMA
37
#define ZTEX_SPI_PAGE_SIZE 256
38
 
39
#ifdef ZTEX_SPI_DMA
40
CyU3PDmaChannel ztex_spi_wr_handle, ztex_spi_rd_handle;
41
#endif
42
 
43
#define FLASH_EC_TIMEOUT 2
44
#define FLASH_EC_BUSY 3
45
#define FLASH_EC_PENDING 4
46
#define FLASH_EC_NOTSUPPORTED 7
47
#define FLASH_EC_RUNTIME 8
48
 
49
struct __attribute__((__packed__)) ztex_flash_t {
50
    uint8_t enabled;                    // 0    1: enabled, 0:disabled
51
    uint16_t sector_size;               // 1    sector size <sector size> = MSB==0 : flash_sector_size and 0x7fff ? 1<<(flash_sector_size and 0x7fff)
52
    uint32_t sectors;                   // 3    number of sectors
53
    uint8_t ec;                         // 7    error code
54
 
55
    uint8_t vendor;                     // 0
56
    uint8_t device;                     // 1
57
    uint8_t memtype;                    // 2
58
    uint8_t erase_cmd;                  // 3
59
    uint8_t last_cmd;                   // 4
60
    uint8_t buf[4];                     // 5
61
    uint8_t cs;
62
 
63
    uint32_t ep0_read_addr;
64
    uint8_t need_pp;
65
    uint32_t write_addr;
66
};
67
 
68
struct ztex_flash_t ztex_flash;
69
 
70
void ztex_flash_select () {
71
    CyU3PSpiSetSsnLine(CyFalse);
72
    ztex_flash.cs = 1;
73
}
74
 
75
void ztex_flash_deselect () {
76
    CyU3PSpiSetSsnLine(CyTrue);
77
    ztex_flash.cs = 0;
78
}
79
 
80
uint8_t ztex_flash_wait() {
81
    uint16_t i;
82
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
83
 
84
    ztex_flash.ec = ztex_flash.cs ? FLASH_EC_PENDING : ztex_flash.enabled ? 0 : FLASH_EC_NOTSUPPORTED;
85
    if ( ztex_flash.ec ) return ztex_flash.ec;
86
 
87
    ztex_flash.buf[0]=ztex_flash.last_cmd=5;
88
    ztex_flash_select();
89
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 1));
90
    if (status != CY_U3P_SUCCESS) goto errreturn;
91
 
92
    for ( i=0; i<11000; i++) {  // wait up to 11s
93
        ZTEX_REC(status = CyU3PSpiReceiveWords (ztex_flash.buf, 4));
94
        if (status != CY_U3P_SUCCESS) goto errreturn;
95
        if ( !(ztex_flash.buf[0] & 1) ) break;
96
        CyU3PThreadSleep(1);    // 1ms
97
    }
98
    ztex_flash_deselect();
99
    ztex_flash.ec = ztex_flash.buf[0] & 1 ? FLASH_EC_TIMEOUT : 0;
100
    return ztex_flash.ec;
101
 
102
errreturn:
103
    ztex_flash.ec = FLASH_EC_RUNTIME;
104
    ztex_flash_deselect();
105
    return ztex_flash.ec;
106
}
107
 
108
uint8_t ztex_flash_read (uint8_t* buf, uint32_t addr, uint32_t size) {
109
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
110
 
111
    if ( ztex_flash_wait() ) return ztex_flash.ec;
112
 
113
    ztex_flash.buf[0]=ztex_flash.last_cmd=0xb;
114
    ztex_flash.buf[1]=addr>>16;
115
    ztex_flash.buf[2]=addr>>8;
116
    ztex_flash.buf[3]=addr;
117
    ztex_flash_select();
118
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 5));
119
    if (status != CY_U3P_SUCCESS) goto errreturn;
120
 
121
#ifdef ZTEX_SPI_DMA
122
    CyU3PDmaBuffer_t buf_p;
123
    uint32_t s2;
124
 
125
    buf_p.buffer = buf;
126
    buf_p.status = 0;
127
 
128
    while ( size>0 ) {
129
        s2 = size;
130
        if ( s2 > ZTEX_SPI_PAGE_SIZE ) s2 = ZTEX_SPI_PAGE_SIZE;
131
 
132
        buf_p.size  = s2;
133
        buf_p.count = s2;
134
 
135
        CyU3PSpiSetBlockXfer (0, s2);
136
        ZTEX_REC(status = CyU3PDmaChannelSetupRecvBuffer (&ztex_spi_rd_handle, &buf_p));
137
        if (status != CY_U3P_SUCCESS) goto errreturn;
138
 
139
        ZTEX_REC(status = CyU3PDmaChannelWaitForCompletion (&ztex_spi_rd_handle, 500));
140
        if (status != CY_U3P_SUCCESS) {
141
            CyU3PDmaChannelReset (&ztex_spi_rd_handle);
142
            CyU3PSpiDisableBlockXfer (CyFalse, CyTrue);
143
            goto errreturn;
144
        }
145
        CyU3PSpiDisableBlockXfer (CyFalse, CyTrue);
146
 
147
        size-=s2;
148
        buf_p.buffer+=s2;
149
//        CyU3PThreadSleep(1);
150
    }
151
#else
152
    ZTEX_REC(status = CyU3PSpiReceiveWords(buf, size) );
153
    if (status != CY_U3P_SUCCESS) goto errreturn;
154
#endif
155
    ztex_flash_deselect();
156
    return 0;
157
 
158
errreturn:
159
    ztex_flash.ec = FLASH_EC_RUNTIME;
160
    ztex_flash_deselect();
161
    return ztex_flash.ec;
162
}
163
 
164
 
165
// sends pp command
166
uint8_t ztex_flash_pp () {
167
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
168
 
169
    ztex_flash_deselect();                      // finish previous write cmd
170
    ztex_flash.need_pp = 0;
171
    if ( ztex_flash_wait() ) return ztex_flash.ec;
172
 
173
//    ZTEX_LOG("flash_pp: %d",ztex_flash.write_addr);
174
 
175
    ztex_flash.buf[0]=ztex_flash.last_cmd=0x06;
176
    ztex_flash_select();
177
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 1));
178
    if (status != CY_U3P_SUCCESS) goto errreturn;
179
    ztex_flash_deselect();
180
 
181
    ztex_flash.buf[0]=ztex_flash.last_cmd=0x02;
182
    ztex_flash.buf[1]=ztex_flash.write_addr >> 16;
183
    ztex_flash.buf[2]=ztex_flash.write_addr >> 8;
184
    ztex_flash.buf[3]=ztex_flash.write_addr;
185
    ztex_flash_select();
186
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 4));
187
    if (status != CY_U3P_SUCCESS) goto errreturn;
188
 
189
    return 0;
190
 
191
errreturn:
192
    ztex_flash.ec = FLASH_EC_RUNTIME;
193
    ztex_flash_deselect();
194
    return ztex_flash.ec;
195
}
196
 
197
// has to be called at begin of a 64K write sequence
198
uint8_t ztex_flash_write_start (uint16_t sector) {
199
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
200
 
201
    if ( ztex_flash_wait() ) return ztex_flash.ec;
202
 
203
    // write enable command
204
    ztex_flash.buf[0]=ztex_flash.last_cmd=0x06;
205
    ztex_flash_select();
206
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 1));
207
    if (status != CY_U3P_SUCCESS) goto errreturn;
208
    ztex_flash_deselect();
209
 
210
    // erase  command
211
//    ztex_log("flash_erase");
212
    ztex_flash.buf[0]=ztex_flash.last_cmd=ztex_flash.erase_cmd;
213
    ztex_flash.buf[1]=sector;
214
    ztex_flash.buf[2]=0;
215
    ztex_flash.buf[3]=0;
216
    ztex_flash_select();
217
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 4));
218
    if (status != CY_U3P_SUCCESS) goto errreturn;
219
    ztex_flash_deselect();
220
 
221
    ztex_flash.need_pp = 1;
222
    ztex_flash.write_addr = sector << 16;
223
    return 0;
224
 
225
errreturn:
226
    ztex_flash.ec = FLASH_EC_RUNTIME;
227
    ztex_flash_deselect();
228
    return ztex_flash.ec;
229
}
230
 
231
// is called between ztex_write_start and ztex_write_finish
232
uint8_t ztex_flash_write (uint8_t* buf, uint32_t size) {
233
    uint32_t s2;
234
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
235
 
236
    if ( ztex_flash.need_pp && ztex_flash_pp() ) return ztex_flash.ec;
237
 
238
    while (size>0) {
239
        s2 = 256-(ztex_flash.write_addr & 255);
240
        if (s2>size) s2=size;
241
#ifdef ZTEX_SPI_DMA
242
        CyU3PDmaBuffer_t buf_p;
243
 
244
        buf_p.size  = s2;
245
        buf_p.count = s2;
246
        buf_p.buffer = buf;
247
        buf_p.status = 0;
248
 
249
        CyU3PSpiSetBlockXfer (s2, 0);
250
        ZTEX_REC( status = CyU3PDmaChannelSetupSendBuffer (&ztex_spi_wr_handle, &buf_p) );
251
 
252
        ZTEX_REC(status = CyU3PDmaChannelWaitForCompletion (&ztex_spi_wr_handle, 500));
253
        if (status != CY_U3P_SUCCESS) {
254
            CyU3PSpiDisableBlockXfer (CyTrue, CyFalse);
255
            goto errreturn;
256
        }
257
        CyU3PSpiDisableBlockXfer (CyTrue, CyFalse);
258
#else   
259
        ZTEX_REC(status = CyU3PSpiTransmitWords (buf, s2));
260
        if (status != CY_U3P_SUCCESS) goto errreturn;
261
#endif  
262
        size-=s2;
263
        buf+=s2;
264
        ztex_flash.write_addr+=s2;
265
        if ( size==0 ) {
266
            ztex_flash_deselect();      // finish pp
267
            ztex_flash.need_pp = 1;     // do not wait
268
        }
269
        else {
270
            if ( ztex_flash_pp() ) return ztex_flash.ec; // finish pp + wait
271
        }
272
    }
273
 
274
    return 0;
275
 
276
errreturn:
277
    ztex_flash.ec = FLASH_EC_RUNTIME;
278
    ztex_flash_deselect();
279
    return ztex_flash.ec;
280
}
281
 
282
// is called after ztex_flash_write
283
void ztex_flash_write_finish () {
284
    ztex_flash_deselect();
285
}
286
 
287
 
288
// VR 0x40
289
uint8_t vr_flash_info(uint16_t value, uint16_t index, uint16_t length ) {
290
    if ( ztex_flash.ec==0 && ztex_flash.cs ) ztex_flash.ec = FLASH_EC_PENDING;
291
    CyU3PMemCopy( ztex_ep0buf, (uint8_t*)&ztex_flash, 8);
292
    ZTEX_REC_RET( CyU3PUsbSendEP0Data( 8, ztex_ep0buf ) );
293
    return 0;
294
}
295
 
296
// VR 0x41
297
uint8_t vr_flash_read(uint16_t value, uint16_t index, uint16_t length ) {
298
    index = index >> 8;
299
    if ( index==0 ) {
300
//        ZTEX_LOG("FR: %d, %d", index, value);
301
        ztex_flash.ep0_read_addr = value << 16;
302
    }
303
    if ( ztex_flash_read(ztex_ep0buf,ztex_flash.ep0_read_addr,length) ) return 255;
304
    ztex_flash.ep0_read_addr += length;
305
    ZTEX_REC_RET ( CyU3PUsbSendEP0Data( length, ztex_ep0buf ) );
306
    return 0;
307
}
308
 
309
// VC 0x42
310
uint8_t vc_flash_write(uint16_t value, uint16_t index, uint16_t length ) {
311
    index = index >> 8;
312
//    ZTEX_LOG("FW: %d, %d", index, value);
313
    if ( index==0 && ztex_flash_write_start(value) ) return 255;
314
 
315
    ZTEX_REC_RET ( CyU3PUsbGetEP0Data (length, ztex_ep0buf, NULL) );
316
    if ( ztex_flash_write(ztex_ep0buf,length) ) return 255;
317
 
318
    if ( index==3 ) ztex_flash_write_finish();
319
    return 0;
320
}
321
 
322
// VR 0x43
323
uint8_t vr_flash_info2(uint16_t value, uint16_t index, uint16_t length ) {
324
    CyU3PMemCopy( ztex_ep0buf, (uint8_t*)&ztex_flash.ec, 10);
325
    return CyU3PUsbSendEP0Data( 10, ztex_ep0buf );
326
}
327
 
328
void ztex_flash_init () {
329
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
330
    CyU3PSpiConfig_t spiConfig;
331
 
332
    ztex_flash.enabled = 0;
333
    ztex_flash.ec = FLASH_EC_NOTSUPPORTED;
334
    ztex_flash.cs = 0;
335
 
336
    ztex_register_vendor_req(0x40, vr_flash_info);
337
    ztex_register_vendor_req(0x41, vr_flash_read);
338
    ztex_register_vendor_cmd(0x42, vc_flash_write);
339
    ztex_register_vendor_req(0x43, vr_flash_info2);
340
 
341
    // Start the SPI module and configure the master 
342
    ZTEX_REC(status = CyU3PSpiInit());
343
    if (status != CY_U3P_SUCCESS) goto errreturn;
344
 
345
    /* Start the SPI master block. Run the SPI clock at 8MHz
346
       and configure the word length to 8 bits. Also configure
347
       the slave select using FW */
348
    CyU3PMemSet ((uint8_t *)&spiConfig, 0, sizeof(spiConfig));
349
    spiConfig.isLsbFirst = CyFalse;
350
    spiConfig.cpol       = CyTrue;
351
    spiConfig.ssnPol     = CyFalse;
352
    spiConfig.cpha       = CyTrue;
353
    spiConfig.leadTime   = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;
354
    spiConfig.lagTime    = CY_U3P_SPI_SSN_LAG_LEAD_HALF_CLK;
355
    spiConfig.ssnCtrl    = CY_U3P_SPI_SSN_CTRL_FW;
356
    spiConfig.clock      = 33000000;
357
//    spiConfig.clock      = 10000000;
358
    spiConfig.wordLen    = 8;
359
    ZTEX_REC(status =  CyU3PSpiSetConfig (&spiConfig, NULL) );
360
    if (status != CY_U3P_SUCCESS) goto errreturn;
361
 
362
#ifdef ZTEX_SPI_DMA
363
    CyU3PDmaChannelConfig_t dmaConfig;
364
 
365
    // DMA channels for SPI write 
366
    CyU3PMemSet ((uint8_t *)&dmaConfig, 0, sizeof(dmaConfig));
367
    dmaConfig.size           = ZTEX_SPI_PAGE_SIZE;
368
    // No buffers need to be allocated as this channel will be used only in override mode. */
369
    dmaConfig.count          = 0;
370
    dmaConfig.prodAvailCount = 0;
371
    dmaConfig.dmaMode        = CY_U3P_DMA_MODE_BYTE;
372
    dmaConfig.prodHeader     = 0;
373
    dmaConfig.prodFooter     = 0;
374
    dmaConfig.consHeader     = 0;
375
    dmaConfig.notification   = 0;
376
    dmaConfig.cb             = NULL;
377
 
378
    /* Channel to write to SPI flash. */
379
    dmaConfig.prodSckId = CY_U3P_CPU_SOCKET_PROD;
380
    dmaConfig.consSckId = CY_U3P_LPP_SOCKET_SPI_CONS;
381
    ZTEX_REC(status =  CyU3PDmaChannelCreate (&ztex_spi_wr_handle, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaConfig) );
382
    if (status != CY_U3P_SUCCESS) goto errreturn;
383
 
384
    /* Channel to read from SPI flash. */
385
    dmaConfig.prodSckId = CY_U3P_LPP_SOCKET_SPI_PROD;
386
    dmaConfig.consSckId = CY_U3P_CPU_SOCKET_CONS;
387
    ZTEX_REC(status =  CyU3PDmaChannelCreate (&ztex_spi_rd_handle, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaConfig) );
388
    if (status != CY_U3P_SUCCESS) goto errreturn;
389
#endif
390
 
391
    // CMD 0x90 may not be supported by all devices
392
    ztex_flash.buf[0]=0x90;
393
    ztex_flash.buf[1]=0;
394
    ztex_flash.buf[2]=0;
395
    ztex_flash.buf[3]=0;
396
    ztex_flash_select();
397
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 4));
398
    if (status != CY_U3P_SUCCESS) goto errreturn;
399
    ztex_flash.device = CyU3PSpiReceiveWords (ztex_flash.buf, 2) == CY_U3P_SUCCESS ? ztex_flash.buf[1] : 127;
400
    ztex_flash_deselect();
401
 
402
    // CMD 0x9F: JEDEC ID
403
    ztex_flash.buf[0]=ztex_flash.last_cmd=0x9F;
404
    ztex_flash_select();
405
    ZTEX_REC(status = CyU3PSpiTransmitWords (ztex_flash.buf, 1));
406
    if (status != CY_U3P_SUCCESS) goto errreturn;
407
    ZTEX_REC(status = CyU3PSpiReceiveWords (ztex_flash.buf, 3));
408
    if (status != CY_U3P_SUCCESS) goto errreturn;
409
    ztex_flash_deselect();
410
 
411
    if ( ztex_flash.buf[2]<16 || ztex_flash.buf[2]>24 ) {
412
        ztex_log("Error: Invalid Flash size");
413
        return;
414
    }
415
    ztex_flash.vendor = ztex_flash.buf[0];
416
    ztex_flash.memtype = ztex_flash.buf[1];
417
    ztex_flash.sector_size = 0x8010;            // only 64 KByte sectors are supported because erasing 4 KByte is extremely slow
418
    ztex_flash.sectors = 1 << (ztex_flash.buf[2]-16);
419
    ztex_flash.erase_cmd = 0xd8;
420
    ztex_flash.ec = 0;
421
    ztex_flash.enabled = 1;
422
 
423
    ZTEX_LOG("Info: Found %d MBit SPI Flash",ztex_flash.sectors>>1);
424
    return;
425
 
426
errreturn:
427
    ztex_flash.ec = FLASH_EC_RUNTIME;
428
    ztex_flash_deselect();
429
    ztex_log("Error: No SPI Flash found");
430
}
431
 
432
void ztex_usb_stop_flash() {
433
#ifdef ZTEX_SPI_DMA
434
    CyU3PDmaChannelReset (&ztex_spi_wr_handle);
435
    CyU3PDmaChannelReset (&ztex_spi_rd_handle);
436
#endif    
437
}

powered by: WebSVN 2.1.0

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