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/] [fx2/] [ztex-xmega.h] - 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 FX2 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
/*
27
    AVR XMEGA support
28
*/
29
 
30
#ifndef[ZTEX_XMEGA_H]
31
#define[ZTEX_XMEGA_H]
32
 
33
#define[@CAPABILITY_XMEGA;]
34
#define[XMEGA_ENABLED][1]
35
 
36
#ifeq[PDI_PORT][E]
37
#define[PDI_bmMODE]
38
#elifeq[PDI_PORT][A]
39
#elifeq[PDI_PORT][B]
40
#elifeq[PDI_PORT][C]
41
#elifneq[PDI_PORT][D]
42
#error[Macro `PDI_PORT' is not defined correctly. Valid values are: `A', `B', `C', `D' and `E'.]
43
#endif
44
 
45
__xdata BYTE xmega_ec;
46
__xdata WORD xmega_flash_pages;   // in pages
47
__xdata WORD xmega_eeprom_pages;  // in pages
48
__xdata BYTE xmega_flash_page_size;   // as power of 2
49
__xdata BYTE xmega_eeprom_page_size;  // as power of 2
50
 
51
__xdata BYTE nvm_page_type;             // current page type (0: none; 1:FLASH; 2:EEPROM)
52
__xdata WORD nvm_current_page;
53
__xdata DWORD nvm_addr;
54
__xdata BYTE nvm_boot_base;     // BOOT_BASE >> 16
55
 
56
#define[XMEGA_FLASH_START][0x800000]
57
#define[XMEGA_EEPROM_START][0x8C0000]
58
#define[XMEGA_FUSE_START][0x8F0020]
59
 
60
#define[XMEGA_EC_NO_ERROR][0]
61
#define[XMEGA_EC_PDI_READ_ERROR][1]
62
#define[XMEGA_EC_NVM_TIMEOUT][2]
63
#define[XMEGA_EC_INVALID_DEVICE][3]
64
#define[XMEGA_EC_ADDRESS_ERROR][4]
65
#define[XMEGA_EC_NVM_BUSY][5]
66
 
67
#define[PDI_IO][IOPDI_PORT]
68
#define[PDI_CLK][IOPDI_PORTPDI_BIT_CLK]
69
#define[PDI_DATA][IOPDI_PORTPDI_BIT_DATA]
70
#define[PDI_bmCLK][(1<<PDI_BIT_CLK)]
71
#define[PDI_bmDATA][(1<<PDI_BIT_DATA)]
72
 
73
#define[NVM_CMD][0xca]
74
#define[NVM_CTRLA][0xcb]
75
#define[NVM_STATUS][0xcf]
76
 
77
/* *********************************************************************
78
   ***** pdi_send ******************************************************
79
   ********************************************************************* */
80
// send one byte to pdi
81
void pdi_send(BYTE b) {
82
    b;                  // this avoids stupid warnings
83
    OEPDI_PORT |= bmBITPDI_BIT_DATA;
84
 
85
__asm
86
#ifdef[PDI_bmMODE]
87
    mov a,dpl
88
 
89
    anl _PDI_IO, #(~PDI_bmDATA)         // start bit
90
    anl _PDI_IO, #(~PDI_bmCLK)  
91
    rrc a
92
    orl _PDI_IO, #(PDI_bmCLK)   
93
 
94
    anl _PDI_IO, #(~PDI_bmDATA)         // 0
95
    jnc 0100200$
96
    orl _PDI_IO, #(PDI_bmDATA)
97
0100200$:
98
    anl _PDI_IO, #(~PDI_bmCLK)  
99
    rrc a
100
    orl _PDI_IO, #(PDI_bmCLK)   
101
 
102
    anl _PDI_IO, #(~PDI_bmDATA)         // 1
103
    jnc 0100201$
104
    orl _PDI_IO, #(PDI_bmDATA)
105
0100201$:
106
    anl _PDI_IO, #(~PDI_bmCLK)  
107
    rrc a
108
    orl _PDI_IO, #(PDI_bmCLK)   
109
 
110
    anl _PDI_IO, #(~PDI_bmDATA)         // 2
111
    jnc 0100202$
112
    orl _PDI_IO, #(PDI_bmDATA)
113
0100202$:
114
    anl _PDI_IO, #(~PDI_bmCLK)  
115
    rrc a
116
    orl _PDI_IO, #(PDI_bmCLK)   
117
 
118
    anl _PDI_IO, #(~PDI_bmDATA)         // 3
119
    jnc 0100203$
120
    orl _PDI_IO, #(PDI_bmDATA)
121
0100203$:
122
    anl _PDI_IO, #(~PDI_bmCLK)  
123
    rrc a
124
    orl _PDI_IO, #(PDI_bmCLK)   
125
 
126
    anl _PDI_IO, #(~PDI_bmDATA)         // 4
127
    jnc 0100204$
128
    orl _PDI_IO, #(PDI_bmDATA)
129
0100204$:
130
    anl _PDI_IO, #(~PDI_bmCLK)  
131
    rrc a
132
    orl _PDI_IO, #(PDI_bmCLK)   
133
 
134
    anl _PDI_IO, #(~PDI_bmDATA)         // 5
135
    jnc 0100205$
136
    orl _PDI_IO, #(PDI_bmDATA)
137
0100205$:
138
    anl _PDI_IO, #(~PDI_bmCLK)  
139
    rrc a
140
    orl _PDI_IO, #(PDI_bmCLK)   
141
 
142
    anl _PDI_IO, #(~PDI_bmDATA)         // 6
143
    jnc 0100206$
144
    orl _PDI_IO, #(PDI_bmDATA)
145
0100206$:
146
    anl _PDI_IO, #(~PDI_bmCLK)  
147
    rrc a
148
    orl _PDI_IO, #(PDI_bmCLK)   
149
 
150
    anl _PDI_IO, #(~PDI_bmDATA)         // 7
151
    jnc 0100207$
152
    orl _PDI_IO, #(PDI_bmDATA)
153
0100207$:
154
    anl _PDI_IO, #(~PDI_bmCLK)  
155
    rrc a
156
    orl _PDI_IO, #(PDI_bmCLK)   
157
 
158
    anl _PDI_IO, #(~PDI_bmDATA)         // parity bit
159
    jnb _PF,0100208$
160
    orl _PDI_IO, #(PDI_bmDATA)
161
0100208$:
162
    anl _PDI_IO, #(~PDI_bmCLK)  
163
    orl _PDI_IO, #(PDI_bmCLK)   
164
 
165
    orl _PDI_IO, #(PDI_bmDATA)          // stop bit 1
166
    anl _PDI_IO, #(~PDI_bmCLK)  
167
    orl _PDI_IO, #(PDI_bmCLK)   
168
 
169
    anl _PDI_IO, #(~PDI_bmCLK)          // stop bit 1
170
    orl _PDI_IO, #(PDI_bmCLK)   
171
#else
172
    mov a,dpl
173
 
174
    clr _PDI_DATA      // start bit
175
    clr _PDI_CLK
176
    rrc a
177
    setb _PDI_CLK
178
 
179
    mov _PDI_DATA,c    // 0
180
    clr _PDI_CLK
181
    rrc a
182
    setb _PDI_CLK
183
 
184
    mov _PDI_DATA,c    // 1
185
    clr _PDI_CLK
186
    rrc a
187
    setb _PDI_CLK
188
 
189
    mov _PDI_DATA,c    // 2
190
    clr _PDI_CLK
191
    rrc a
192
    setb _PDI_CLK
193
 
194
    mov _PDI_DATA,c    // 3
195
    clr _PDI_CLK
196
    rrc a
197
    setb _PDI_CLK
198
 
199
    mov _PDI_DATA,c    // 4
200
    clr _PDI_CLK
201
    rrc a
202
    setb _PDI_CLK
203
 
204
    mov _PDI_DATA,c    // 5
205
    clr _PDI_CLK
206
    rrc a
207
    setb _PDI_CLK
208
 
209
    mov _PDI_DATA,c    // 6
210
    clr _PDI_CLK
211
    rrc a
212
    setb _PDI_CLK
213
 
214
    mov _PDI_DATA,c    // 7
215
    clr _PDI_CLK
216
    rrc a
217
    setb _PDI_CLK
218
 
219
    mov c,_PF
220
    mov _PDI_DATA,c    // parity bit
221
    clr _PDI_CLK
222
    setb _PDI_CLK
223
 
224
    setb _PDI_DATA      // stop bit 1
225
    clr _PDI_CLK
226
    setb _PDI_CLK
227
 
228
    clr _PDI_CLK        // stop bit 2
229
    setb _PDI_CLK
230
#endif[PDI_PORT][A]
231
__endasm;
232
}
233
 
234
 
235
/* *********************************************************************
236
   ***** pdi_read ******************************************************
237
   ********************************************************************* */
238
// read byte from PDI
239
BYTE pdi_read() {
240
    xmega_ec = XMEGA_EC_NO_ERROR;
241
    OEPDI_PORT &= ~bmBITPDI_BIT_DATA;
242
 
243
__asm
244
#ifdef[PDI_bmMODE]
245
    anl _PDI_IO, #(~PDI_bmCLK)
246
    orl _PDI_IO, #(PDI_bmCLK)   
247
    mov r1,0
248
010020$:                // wait for the start bit
249
    mov a, _PDI_IO      // start bit
250
    anl a, #(PDI_bmDATA)
251
    jz 010021$
252
    anl _PDI_IO, #(~PDI_bmCLK)
253
    orl _PDI_IO, #(PDI_bmCLK)   
254
    djnz r1,010020$
255
010021$:
256
 
257
    anl _PDI_IO, #(~PDI_bmCLK)
258
    orl _PDI_IO, #(PDI_bmCLK)   
259
    mov a, _PDI_IO              // 0
260
    anl a, #(PDI_bmDATA)
261
    subb a,#1
262
    mov a,r1
263
    rrc a
264
    mov r1,a
265
 
266
    anl _PDI_IO, #(~PDI_bmCLK)
267
    orl _PDI_IO, #(PDI_bmCLK)   
268
    mov a, _PDI_IO              // 1
269
    anl a, #(PDI_bmDATA)
270
    subb a,#1
271
    mov a,r1
272
    rrc a
273
    mov r1,a
274
 
275
    anl _PDI_IO, #(~PDI_bmCLK)
276
    orl _PDI_IO, #(PDI_bmCLK)   
277
    mov a, _PDI_IO              // 2
278
    anl a, #(PDI_bmDATA)
279
    subb a,#1
280
    mov a,r1
281
    rrc a
282
    mov r1,a
283
 
284
    anl _PDI_IO, #(~PDI_bmCLK)
285
    orl _PDI_IO, #(PDI_bmCLK)   
286
    mov a, _PDI_IO              // 3
287
    anl a, #(PDI_bmDATA)
288
    subb a,#1
289
    mov a,r1
290
    rrc a
291
    mov r1,a
292
 
293
    anl _PDI_IO, #(~PDI_bmCLK)
294
    orl _PDI_IO, #(PDI_bmCLK)   
295
    mov a, _PDI_IO              // 4
296
    anl a, #(PDI_bmDATA)
297
    subb a,#1
298
    mov a,r1
299
    rrc a
300
    mov r1,a
301
 
302
    anl _PDI_IO, #(~PDI_bmCLK)
303
    orl _PDI_IO, #(PDI_bmCLK)   
304
    mov a, _PDI_IO              // 5
305
    anl a, #(PDI_bmDATA)
306
    subb a,#1
307
    mov a,r1
308
    rrc a
309
    mov r1,a
310
 
311
    anl _PDI_IO, #(~PDI_bmCLK)
312
    orl _PDI_IO, #(PDI_bmCLK)   
313
    mov a, _PDI_IO              // 6
314
    anl a, #(PDI_bmDATA)
315
    subb a,#1
316
    mov a,r1
317
    rrc a
318
    mov r1,a
319
 
320
    anl _PDI_IO, #(~PDI_bmCLK)
321
    orl _PDI_IO, #(PDI_bmCLK)   
322
    mov a, _PDI_IO              // 7
323
    anl a, #(PDI_bmDATA)
324
    subb a,#1
325
    mov a,r1
326
    rrc a
327
    xrl a,#255
328
    mov r1,a
329
 
330
    anl _PDI_IO, #(~PDI_bmCLK)
331
    orl _PDI_IO, #(PDI_bmCLK)   
332
    mov a, _PDI_IO              // parity bit
333
    anl a, #(PDI_bmDATA)
334
    subb a,#1
335
    mov a,r1
336
    jnc 010022$
337
    jb _PF, 010023$             // parity error
338
    sjmp 010026$
339
010022$:
340
    jnb _PF, 010023$            // parity error
341
010026$:
342
 
343
    anl _PDI_IO, #(~PDI_bmCLK)
344
    orl _PDI_IO, #(PDI_bmCLK)   
345
    mov a, _PDI_IO              // stop bit 1
346
    anl a, #(PDI_bmDATA)
347
    jz 010024$
348
 
349
    anl _PDI_IO, #(~PDI_bmCLK)
350
    orl _PDI_IO, #(PDI_bmCLK)   
351
    mov a, _PDI_IO              // stop bit 2
352
    anl a, #(PDI_bmDATA)
353
    jz 010024$
354
 
355
    mov dpl,r1
356
    ret
357
010023$:
358
    anl _PDI_IO, #(~PDI_bmCLK)
359
    orl _PDI_IO, #(PDI_bmCLK)   
360
010024$:
361
    anl _PDI_IO, #(~PDI_bmCLK)
362
    orl _PDI_IO, #(PDI_bmCLK)   
363
010025$:
364
#else
365
    clr _PDI_CLK
366
    setb _PDI_CLK
367
    mov r1,0
368
010020$:                // wait for the start bit
369
    mov c,_PDI_DATA
370
    jnc 010021$ // start bit
371
    clr _PDI_CLK
372
    setb _PDI_CLK
373
    djnz r1,010020$
374
010021$:
375
 
376
    clr _PDI_CLK
377
    setb _PDI_CLK
378
    mov c,_PDI_DATA     // 0
379
    rrc a
380
 
381
    clr _PDI_CLK
382
    setb _PDI_CLK
383
    mov c,_PDI_DATA     // 1
384
    rrc a
385
 
386
    clr _PDI_CLK
387
    setb _PDI_CLK
388
    mov c,_PDI_DATA     // 2
389
    rrc a
390
 
391
    clr _PDI_CLK
392
    setb _PDI_CLK
393
    mov c,_PDI_DATA     // 3
394
    rrc a
395
 
396
    clr _PDI_CLK
397
    setb _PDI_CLK
398
    mov c,_PDI_DATA     // 4
399
    rrc a
400
 
401
    clr _PDI_CLK
402
    setb _PDI_CLK
403
    mov c,_PDI_DATA     // 5
404
    rrc a
405
 
406
    clr _PDI_CLK
407
    setb _PDI_CLK
408
    mov c,_PDI_DATA     // 6
409
    rrc a
410
 
411
    clr _PDI_CLK
412
    setb _PDI_CLK
413
    mov c,_PDI_DATA     // 7
414
    rrc a
415
 
416
    clr _PDI_CLK
417
    setb _PDI_CLK
418
    mov c,_PDI_DATA     // parity bit
419
    jc 010022$
420
    jb _PF, 010023$     // parity error
421
    sjmp 010026$
422
010022$:
423
    jnb _PF, 010023$    // parity error
424
010026$:
425
 
426
    clr _PDI_CLK
427
    setb _PDI_CLK
428
    mov c,_PDI_DATA     // stop bit 1
429
    jnc 010024$
430
 
431
    clr _PDI_CLK
432
    setb _PDI_CLK
433
    mov c,_PDI_DATA     // stop bit 2
434
    jnc 010025$
435
 
436
    mov dpl,a
437
    ret
438
010023$:
439
    clr _PDI_CLK
440
    setb _PDI_CLK
441
010024$:
442
    clr _PDI_CLK
443
    setb _PDI_CLK
444
010025$:
445
#endif
446
__endasm;
447
    xmega_ec = XMEGA_EC_PDI_READ_ERROR;
448
 
449
    return 0;            // never called (just to avoid warnings)
450
}
451
 
452
/* *********************************************************************
453
   ***** pdi_enable ****************************************************
454
   ********************************************************************* */
455
// enable the pdi
456
void pdi_enable() {     // enter PDI mode
457
    BYTE i;
458
    PDI_IO &= ~PDI_bmDATA;
459
    PDI_IO |= PDI_bmCLK;
460
    OEPDI_PORT |= bmBITPDI_BIT_DATA | bmBITPDI_BIT_CLK;
461
 
462
    PDI_IO |= PDI_bmDATA;
463
    NOP;
464
    NOP;
465
    NOP;
466
    NOP;
467
    NOP;
468
    NOP;
469
 
470
    for (i=0; i<16; i++) {
471
        PDI_IO &= ~PDI_bmCLK;
472
        PDI_IO |= PDI_bmCLK;
473
    }
474
 
475
    pdi_send(0xc2);
476
    pdi_send(2);
477
}
478
 
479
/* *********************************************************************
480
   ***** nvm_status ****************************************************
481
   ********************************************************************* */
482
// read the NVM_STATUS register
483
BYTE nvm_status () {
484
    pdi_send(0x0c);
485
    pdi_send(NVM_STATUS);
486
    pdi_send(0x01);
487
    pdi_send(0x00);
488
    pdi_send(0x01);
489
    return pdi_read();
490
}
491
 
492
 
493
/* *********************************************************************
494
   ***** nvm_wait_busy *************************************************
495
   ********************************************************************* */
496
// wait up to 40ms if NVM is busy
497
void nvm_wait_busy() {
498
    WORD w;
499
    // wait if nvm controller is busy
500
    for ( w=0; w<40000; w++ ) {
501
        if ( ( (nvm_status() & bmBIT7) == 0) || xmega_ec!=0 )
502
            return;
503
    }
504
    xmega_ec = XMEGA_EC_NVM_BUSY;
505
}
506
 
507
/* *********************************************************************
508
   ***** nvm_init ******************************************************
509
   ********************************************************************* */
510
// enable the NVM access via PDI
511
void nvm_init() {       // activate the NVM controller
512
    BYTE b,c,d;
513
    pdi_enable();
514
 
515
    pdi_send(0xc1);     // reset
516
    pdi_send(0x59);
517
 
518
    pdi_send(0xe0);     // send key
519
    pdi_send(0xff);
520
    pdi_send(0x88);
521
    pdi_send(0xd8);
522
    pdi_send(0xcd);
523
    pdi_send(0x45);
524
    pdi_send(0xab);
525
    pdi_send(0x89);
526
    pdi_send(0x12);
527
 
528
    // wait until NVM is available
529
    b = 0; c = 0;
530
    do {
531
        pdi_send(0x80);
532
        c = pdi_read();
533
        d = ((c & bmBIT1) == 0) && (xmega_ec==0);
534
        b+=1;
535
    } while ( (b!=0) && d );
536
    if ( d )
537
        xmega_ec = XMEGA_EC_NVM_TIMEOUT;
538
}
539
 
540
/* *********************************************************************
541
   ***** nvm_register_write*********************************************
542
   ********************************************************************* */
543
// write to NVM register
544
void nvm_register_write(BYTE offs, BYTE b) {
545
    pdi_send(0x4c);     // direct write
546
    pdi_send(offs);
547
    pdi_send(0x01);
548
    pdi_send(0x00);
549
    pdi_send(0x01);
550
    pdi_send(b);
551
}
552
 
553
/* *********************************************************************
554
   ***** nvm_register_write ********************************************
555
   ********************************************************************* */
556
// enable the NVM access via PDI
557
void nvm_done() {       // deactivate the NVM controller
558
    pdi_send(0xc1);     // disable reset
559
    pdi_send(0);
560
 
561
    nvm_register_write(NVM_CMD,0);       // VNM NOP
562
 
563
    PDI_IO &= ~PDI_bmDATA;
564
    PDI_IO |= PDI_bmCLK;
565
}
566
 
567
void nvm_done2() {      // deactivate the NVM controller
568
    nvm_register_write(NVM_CMD,0);       // VNM NOP
569
 
570
    PDI_IO &= ~PDI_bmDATA;
571
    PDI_IO |= PDI_bmCLK;
572
}
573
 
574
 
575
/* *********************************************************************
576
   ***** nvm_read ******************************************************
577
   ********************************************************************* */
578
// read NVM
579
BYTE nvm_read ( __xdata BYTE *buf, DWORD addr, BYTE length ) {
580
    BYTE ol = length;
581
 
582
    if ( length == 0 )
583
        return 0;
584
 
585
    nvm_register_write(NVM_CMD,0x43);    // load NVM read command into NVM CMD register
586
 
587
    pdi_send( 0x6b );            // set ptr
588
    pdi_send( addr & 255 );
589
    pdi_send( (addr>>8) & 255 );
590
    pdi_send( (addr>>16) & 255 );
591
    pdi_send( (addr>>24) & 255 );
592
 
593
    pdi_send( 0xa0 );           // repeat cmd
594
    pdi_send( length-1 );
595
    pdi_send( 0x24 );           // read one byte cmd
596
    while ( (length!=0) && (xmega_ec==0) ) {
597
        *buf = pdi_read(); buf++;
598
        length-= 1;
599
    }
600
 
601
    return ol-length;
602
}
603
 
604
/* *********************************************************************
605
   ***** nvm_page_load *************************************************
606
   ********************************************************************* */
607
// write data into NVM page buffer. Flash: cmd=0x23 , EEPROM: cmd=0x33
608
#define[nvm_flash_page_load(][);][nvm_page_load(0x23, $0);]
609
#define[nvm_eeprom_page_load(][);][nvm_page_load(0x33, $0);]
610
 
611
void nvm_page_load ( BYTE cmd, __xdata BYTE *buf, DWORD addr, BYTE length ) {
612
    BYTE ol = length;
613
 
614
    if ( length == 0 )
615
        return;
616
 
617
    nvm_register_write(NVM_CMD,cmd);    // load "Load Page Buffer" command into CMD register NVM CMD register
618
 
619
    pdi_send( 0x6b );            // set ptr
620
    pdi_send( addr & 255 );
621
    pdi_send( (addr>>8) & 255 );
622
    pdi_send( (addr>>16) & 255 );
623
    pdi_send( (addr>>24) & 255 );
624
 
625
    pdi_send( 0xa0 );           // repeat cmd
626
    pdi_send( length-1 );
627
    pdi_send( 0x64 );           // write one byte cmd
628
    while ( length!=0 ) {
629
        pdi_send(*buf); buf++;
630
        length-= 1;
631
    }
632
}
633
 
634
 
635
/* *********************************************************************
636
   ***** nvm_page_write ************************************************
637
   ********************************************************************* */
638
// erase and write nvm page 
639
#define[nvm_flash_page_write(][);][nvm_page_write(((BYTE)((($0)>>16) & 255)) < nvm_boot_base ? 0x25 : 0x2d, $0);]
640
#define[nvm_eeprom_page_write(][);][nvm_page_write(0x35, $0);]
641
void nvm_page_write (BYTE cmd, DWORD addr ) {
642
    nvm_register_write(NVM_CMD, cmd);   // load "erase and write page" command into NVM CMD register
643
 
644
    pdi_send( 0x4c   );                 // direct write
645
    pdi_send( addr & 255 );
646
    pdi_send( (addr>>8) & 255 );
647
    pdi_send( (addr>>16) & 255 );
648
    pdi_send( (addr>>24) & 255 );
649
    pdi_send( 0 );
650
 
651
    nvm_wait_busy();
652
}
653
 
654
/* *********************************************************************
655
   ***** nvm_fuse_write ************************************************
656
   ********************************************************************* */
657
// write fuse
658
void nvm_fuse_write (BYTE idx, BYTE val) {
659
    nvm_register_write(NVM_CMD, 0x4c);   // load "write fuse" command into NVM CMD register
660
 
661
    pdi_send( 0x4c   );                 // direct write
662
    pdi_send( 0x20 | idx );
663
    pdi_send( 0 );
664
    pdi_send( 0x8f );
665
    pdi_send( 0 );
666
    pdi_send( val );
667
 
668
  nvm_wait_busy();
669
}
670
 
671
/* *********************************************************************
672
   ***** xmega_reset ***************************************************
673
   ********************************************************************* */
674
// reset the xmega
675
void xmega_reset () {
676
    OEPDI_PORT |= bmBITPDI_BIT_CLK;
677
    uwait(20);                  // disable
678
    PDI_IO &= ~PDI_bmCLK;       // enable reset
679
 
680
    uwait(5);
681
    PDI_IO |= PDI_bmCLK;
682
}
683
 
684
/* *********************************************************************
685
   ***** xmega_init ****************************************************
686
   ********************************************************************* */
687
void xmega_init() {
688
    __xdata BYTE xmega_id[3];
689
 
690
    nvm_page_type = 0;
691
    xmega_flash_pages = 0;
692
    xmega_eeprom_pages = 64;
693
    xmega_eeprom_page_size = 5;
694
    xmega_flash_page_size = 9;
695
 
696
 
697
    nvm_init();
698
    if ( xmega_ec != 0 )
699
        return;
700
    nvm_read(xmega_id, 0x01000090, 3);
701
    if ( xmega_ec != 0 )
702
        return;
703
    nvm_done();
704
 
705
    if ( xmega_id[0] != 0x1e ) {
706
        xmega_ec = XMEGA_EC_INVALID_DEVICE;
707
        return;
708
    }
709
 
710
/*  if (  xmega_id[1] == 0x96 && xmega_id[2] == 0x4e ) {        // 64A1 currently not supported
711
        mega_flash_pages = 272;
712
        mega_flash_page_size = 8;
713
        nvm_boot_base = 0x81;
714
    } */
715
    if (  xmega_id[1] == 0x97 && xmega_id[2] == 0x4c ) {        // 128A1
716
        xmega_flash_pages = 272;
717
        nvm_boot_base = 0x82;
718
    }
719
    else if (  xmega_id[1] == 0x97 && xmega_id[2] == 0x4e ) {   // 192A1
720
        xmega_flash_pages = 400;
721
        nvm_boot_base = 0x83;
722
    }
723
    else if (  xmega_id[1] == 0x98 && xmega_id[2] == 0x46 ) {   // 256A1
724
        xmega_flash_pages = 528;
725
        xmega_eeprom_pages = 128;
726
        nvm_boot_base = 0x84;
727
    }
728
    else {
729
        xmega_ec = XMEGA_EC_INVALID_DEVICE;
730
    }
731
}
732
 
733
 
734
 
735
/* *********************************************************************
736
   ***** EP0 vendor request 0x48 ***************************************
737
   ********************************************************************* */
738
// send xmega error and status information to the host
739
ADD_EP0_VENDOR_REQUEST((0x48,,
740
    MEM_COPY1(xmega_ec,EP0BUF,7);
741
    EP0BCH = 0;
742
    EP0BCL = 7;
743
,,
744
    NOP;
745
));;
746
 
747
 
748
/* *********************************************************************
749
   ***** EP0 vendor request 0x49 ***************************************
750
   ********************************************************************* */
751
// reset xmega   
752
ADD_EP0_VENDOR_COMMAND((0x49,,
753
    xmega_reset();
754
,,
755
    NOP;
756
));;
757
 
758
 
759
/* *********************************************************************
760
   ***** EP0 vendor requests 0x4A, 0x4B, 0x4C,0x4D *********************
761
   ********************************************************************* */
762
// read from nvm using: pdi address space (0x4a), flash base (0x4b), EEPROM base (0x4c), FUSE base (0x4d) 
763
BYTE nvm_read_ep0 () {
764
    BYTE i, b;
765
    b = ep0_payload_transfer;
766
    if ( b == 0 )
767
        return 0;
768
 
769
    nvm_init();
770
    i = xmega_ec==0 ? nvm_read(EP0BUF, nvm_addr, b) : 0;
771
    nvm_done();
772
 
773
    nvm_addr += b;
774
    return i;
775
}
776
 
777
ADD_EP0_VENDOR_REQUEST((0x4a: case 0x4b: case 0x4c: case 0x4d,,                 // read from NVM
778
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
779
    if ( bRequest == 0x4b ) {                                                   // read from Flash
780
        nvm_addr += XMEGA_FLASH_START;
781
    }
782
    else if ( bRequest == 0x4c ) {                                              // read from EEPROM
783
        nvm_addr += XMEGA_EEPROM_START;
784
    }
785
    else if ( bRequest == 0x4d ) {                                              // read FUSES
786
        nvm_addr += XMEGA_FUSE_START;
787
    }
788
    EP0BCH = 0;
789
    EP0BCL = nvm_read_ep0();
790
,,
791
    EP0BCH = 0;
792
    EP0BCL = nvm_read_ep0();
793
));;
794
 
795
 
796
/* *********************************************************************
797
   ***** EP0 vendor command 0x4B ***************************************
798
   ********************************************************************* */
799
// write exactly one flash page
800
void nvm_flash_write_ep0 () {
801
    BYTE b;
802
    b = ep0_payload_transfer;
803
 
804
    nvm_init();
805
    if ( xmega_ec != 0 )
806
        return;
807
 
808
    nvm_flash_page_load(EP0BUF, nvm_addr, b);
809
 
810
    if ( ep0_payload_remaining == 0 ) {
811
        nvm_flash_page_write( nvm_addr );
812
        nvm_done();
813
    }
814
    else {
815
        nvm_done2();
816
    }
817
 
818
    nvm_addr += b;
819
}
820
 
821
ADD_EP0_VENDOR_COMMAND((0x4B,,
822
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
823
    nvm_addr += XMEGA_FLASH_START;
824
    if ( SETUPDAT[2]!=0 || (SETUPDAT[3] & 1)!=0 || SETUPDAT[7]!=2 || SETUPDAT[6]!=0 || (*(WORD*)(&SETUPDAT[3])>>1)>=xmega_flash_pages )  // only 512 byte pages supported
825
    {
826
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
827
        EP0_STALL;
828
    }
829
,,
830
    if ( ep0_payload_transfer != 0 ) {
831
        xmega_ec = 0;
832
        nvm_flash_write_ep0();
833
        if ( xmega_ec != 0 ) {
834
            EP0_STALL;
835
        }
836
    }
837
));;
838
 
839
/* *********************************************************************
840
   ***** EP0 vendor command 0x4C ***************************************
841
   ********************************************************************* */
842
// write exactly one EEPROM page
843
ADD_EP0_VENDOR_COMMAND((0x4C,,
844
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
845
    nvm_addr += XMEGA_EEPROM_START;
846
    if ( ( SETUPDAT[2] & 31 ) != 0 || SETUPDAT[7]!=0 || SETUPDAT[6]!=32 || (*(WORD*)(&SETUPDAT[2])>>5)>=xmega_eeprom_pages )  // only 32 byte pages supported
847
    {
848
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
849
        EP0_STALL;
850
    }
851
 
852
    nvm_init();
853
    if ( xmega_ec != 0 )
854
        return;
855
 
856
    nvm_eeprom_page_load(EP0BUF, nvm_addr, 32);
857
    nvm_eeprom_page_write( nvm_addr );
858
    nvm_done();
859
,,
860
));;
861
 
862
/* *********************************************************************
863
   ***** EP0 vendor command 0x4D ***************************************
864
   ********************************************************************* */
865
// write one fuse
866
ADD_EP0_VENDOR_COMMAND((0x4D,,
867
    if ( SETUPDAT[6]!=0 || SETUPDAT[7]!=0 || SETUPDAT[5]!=0 || SETUPDAT[4]>7 )
868
    {
869
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
870
        EP0_STALL;
871
    }
872
 
873
    nvm_init();
874
    nvm_fuse_write(SETUPDAT[4], SETUPDAT[2]);
875
    nvm_done();
876
,,
877
    NOP;
878
));;
879
 
880
 
881
#endif  /*ZTEX_XMEGA_H*/

powered by: WebSVN 2.1.0

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