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

Subversion Repositories usb_fpga_1_11

[/] [usb_fpga_1_11/] [trunk/] [include/] [ztex-xmega.h] - Diff between revs 3 and 5

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 3 Rev 5
Line 1... Line 1...
/*!
/*!
   ZTEX Firmware Kit for EZ-USB Microcontrollers
   ZTEX Firmware Kit for EZ-USB FX2 Microcontrollers
   Copyright (C) 2009-2010 ZTEX e.K.
   Copyright (C) 2009-2011 ZTEX GmbH.
   http://www.ztex.de
   http://www.ztex.de
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License version 3 as
   it under the terms of the GNU General Public License version 3 as
   published by the Free Software Foundation.
   published by the Free Software Foundation.
Line 24... Line 24...
#define[ZTEX_XMEGA_H]
#define[ZTEX_XMEGA_H]
 
 
#define[@CAPABILITY_XMEGA;]
#define[@CAPABILITY_XMEGA;]
#define[XMEGA_ENABLED][1]
#define[XMEGA_ENABLED][1]
 
 
 
#ifeq[PDI_PORT][E]
 
#define[PDI_bmMODE]
 
#elifeq[PDI_PORT][A]
 
#elifeq[PDI_PORT][B]
 
#elifeq[PDI_PORT][C]
 
#elifneq[PDI_PORT][D]
 
#error[Macro `PDI_PORT' is not defined correctly. Valid values are: `A', `B', `C', `D' and `E'.]
 
#endif
 
 
 
__xdata BYTE xmega_ec;
 
__xdata WORD xmega_flash_pages;   // in pages
 
__xdata WORD xmega_eeprom_pages;  // in pages
 
__xdata BYTE xmega_flash_page_size;   // as power of 2
 
__xdata BYTE xmega_eeprom_page_size;  // as power of 2
 
 
 
__xdata BYTE nvm_page_type;             // current page type (0: none; 1:FLASH; 2:EEPROM)
 
__xdata WORD nvm_current_page;
 
__xdata DWORD nvm_addr;
 
__xdata BYTE nvm_boot_base;     // BOOT_BASE >> 16
 
 
 
#define[XMEGA_FLASH_START][0x800000]
 
#define[XMEGA_EEPROM_START][0x8C0000]
 
#define[XMEGA_FUSE_START][0x8F0020]
 
 
 
#define[XMEGA_EC_NO_ERROR][0]
 
#define[XMEGA_EC_PDI_READ_ERROR][1]
 
#define[XMEGA_EC_NVM_TIMEOUT][2]
 
#define[XMEGA_EC_INVALID_DEVICE][3]
 
#define[XMEGA_EC_ADDRESS_ERROR][4]
 
#define[XMEGA_EC_NVM_BUSY][5]
 
 
 
#define[PDI_IO][IOPDI_PORT]
 
#define[PDI_CLK][IOPDI_PORTPDI_BIT_CLK]
 
#define[PDI_DATA][IOPDI_PORTPDI_BIT_DATA]
 
#define[PDI_bmCLK][(1<<PDI_BIT_CLK)]
 
#define[PDI_bmDATA][(1<<PDI_BIT_DATA)]
 
 
 
#define[NVM_CMD][0xca]
 
#define[NVM_CTRLA][0xcb]
 
#define[NVM_STATUS][0xcf]
 
 
 
/* *********************************************************************
 
   ***** pdi_send ******************************************************
 
   ********************************************************************* */
 
// send one byte to pdi
 
void pdi_send(BYTE b) {
 
    b;                  // this avoids stupid warnings
 
    OEPDI_PORT |= bmBITPDI_BIT_DATA;
 
 
 
__asm
 
#ifdef[PDI_bmMODE]
 
    mov a,dpl
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // start bit
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 0
 
    jnc 0100200$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100200$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 1
 
    jnc 0100201$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100201$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 2
 
    jnc 0100202$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100202$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 3
 
    jnc 0100203$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100203$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 4
 
    jnc 0100204$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100204$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 5
 
    jnc 0100205$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100205$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 6
 
    jnc 0100206$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100206$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // 7
 
    jnc 0100207$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100207$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    rrc a
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmDATA)         // parity bit
 
    jnb _PF,0100208$
 
    orl _PDI_IO, #(PDI_bmDATA)
 
0100208$:
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    orl _PDI_IO, #(PDI_bmDATA)          // stop bit 1
 
    anl _PDI_IO, #(~PDI_bmCLK)  
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)          // stop bit 1
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
#else
 
    mov a,dpl
 
 
 
    clr _PDI_DATA      // start bit
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 0
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 1
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 2
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 3
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 4
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 5
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 6
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov _PDI_DATA,c    // 7
 
    clr _PDI_CLK
 
    rrc a
 
    setb _PDI_CLK
 
 
 
    mov c,_PF
 
    mov _PDI_DATA,c    // parity bit
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
 
 
    setb _PDI_DATA      // stop bit 1
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
 
 
    clr _PDI_CLK        // stop bit 2
 
    setb _PDI_CLK
 
#endif[PDI_PORT][A]
 
__endasm;
 
}
 
 
 
 
 
/* *********************************************************************
 
   ***** pdi_read ******************************************************
 
   ********************************************************************* */
 
// read byte from PDI
 
BYTE pdi_read() {
 
    xmega_ec = XMEGA_EC_NO_ERROR;
 
    OEPDI_PORT &= ~bmBITPDI_BIT_DATA;
 
 
 
__asm
 
#ifdef[PDI_bmMODE]
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov r1,0
 
010020$:                // wait for the start bit
 
    mov a, _PDI_IO      // start bit
 
    anl a, #(PDI_bmDATA)
 
    jz 010021$
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    djnz r1,010020$
 
010021$:
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 0
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 1
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 2
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 3
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 4
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 5
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 6
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // 7
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    rrc a
 
    xrl a,#255
 
    mov r1,a
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // parity bit
 
    anl a, #(PDI_bmDATA)
 
    subb a,#1
 
    mov a,r1
 
    jnc 010022$
 
    jb _PF, 010023$             // parity error
 
    sjmp 010026$
 
010022$:
 
    jnb _PF, 010023$            // parity error
 
010026$:
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // stop bit 1
 
    anl a, #(PDI_bmDATA)
 
    jz 010024$
 
 
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
    mov a, _PDI_IO              // stop bit 2
 
    anl a, #(PDI_bmDATA)
 
    jz 010024$
 
 
 
    mov dpl,r1
 
    ret
 
010023$:
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
010024$:
 
    anl _PDI_IO, #(~PDI_bmCLK)
 
    orl _PDI_IO, #(PDI_bmCLK)   
 
010025$:
 
#else
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov r1,0
 
010020$:                // wait for the start bit
 
    mov c,_PDI_DATA
 
    jnc 010021$ // start bit
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    djnz r1,010020$
 
010021$:
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 0
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 1
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 2
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 3
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 4
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 5
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 6
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // 7
 
    rrc a
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // parity bit
 
    jc 010022$
 
    jb _PF, 010023$     // parity error
 
    sjmp 010026$
 
010022$:
 
    jnb _PF, 010023$    // parity error
 
010026$:
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // stop bit 1
 
    jnc 010024$
 
 
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
    mov c,_PDI_DATA     // stop bit 2
 
    jnc 010025$
 
 
 
    mov dpl,a
 
    ret
 
010023$:
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
010024$:
 
    clr _PDI_CLK
 
    setb _PDI_CLK
 
010025$:
 
#endif
 
__endasm;
 
    xmega_ec = XMEGA_EC_PDI_READ_ERROR;
 
 
 
    return 0;            // never called (just to avoid warnings)
 
}
 
 
 
/* *********************************************************************
 
   ***** pdi_enable ****************************************************
 
   ********************************************************************* */
 
// enable the pdi
 
void pdi_enable() {     // enter PDI mode
 
    BYTE i;
 
    PDI_IO &= ~PDI_bmDATA;
 
    PDI_IO |= PDI_bmCLK;
 
    OEPDI_PORT |= bmBITPDI_BIT_DATA | bmBITPDI_BIT_CLK;
 
 
 
    PDI_IO |= PDI_bmDATA;
 
    NOP;
 
    NOP;
 
    NOP;
 
    NOP;
 
    NOP;
 
    NOP;
 
 
 
    for (i=0; i<16; i++) {
 
        PDI_IO &= ~PDI_bmCLK;
 
        PDI_IO |= PDI_bmCLK;
 
    }
 
 
 
    pdi_send(0xc2);
 
    pdi_send(2);
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_status ****************************************************
 
   ********************************************************************* */
 
// read the NVM_STATUS register
 
BYTE nvm_status () {
 
    pdi_send(0x0c);
 
    pdi_send(NVM_STATUS);
 
    pdi_send(0x01);
 
    pdi_send(0x00);
 
    pdi_send(0x01);
 
    return pdi_read();
 
}
 
 
 
 
 
/* *********************************************************************
 
   ***** nvm_wait_busy *************************************************
 
   ********************************************************************* */
 
// wait up to 40ms if NVM is busy
 
void nvm_wait_busy() {
 
    WORD w;
 
    // wait if nvm controller is busy
 
    for ( w=0; w<40000; w++ ) {
 
        if ( ( (nvm_status() & bmBIT7) == 0) || xmega_ec!=0 )
 
            return;
 
    }
 
    xmega_ec = XMEGA_EC_NVM_BUSY;
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_init ******************************************************
 
   ********************************************************************* */
 
// enable the NVM access via PDI
 
void nvm_init() {       // activate the NVM controller
 
    BYTE b,c,d;
 
    pdi_enable();
 
 
 
    pdi_send(0xc1);     // reset
 
    pdi_send(0x59);
 
 
 
    pdi_send(0xe0);     // send key
 
    pdi_send(0xff);
 
    pdi_send(0x88);
 
    pdi_send(0xd8);
 
    pdi_send(0xcd);
 
    pdi_send(0x45);
 
    pdi_send(0xab);
 
    pdi_send(0x89);
 
    pdi_send(0x12);
 
 
 
    // wait until NVM is available
 
    b = 0; c = 0;
 
    do {
 
        pdi_send(0x80);
 
        c = pdi_read();
 
        d = ((c & bmBIT1) == 0) && (xmega_ec==0);
 
        b+=1;
 
    } while ( (b!=0) && d );
 
    if ( d )
 
        xmega_ec = XMEGA_EC_NVM_TIMEOUT;
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_register_write*********************************************
 
   ********************************************************************* */
 
// write to NVM register
 
void nvm_register_write(BYTE offs, BYTE b) {
 
    pdi_send(0x4c);     // direct write
 
    pdi_send(offs);
 
    pdi_send(0x01);
 
    pdi_send(0x00);
 
    pdi_send(0x01);
 
    pdi_send(b);
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_register_write ********************************************
 
   ********************************************************************* */
 
// enable the NVM access via PDI
 
void nvm_done() {       // deactivate the NVM controller
 
    pdi_send(0xc1);     // disable reset
 
    pdi_send(0);
 
 
 
    nvm_register_write(NVM_CMD,0);       // VNM NOP
 
 
 
    PDI_IO &= ~PDI_bmDATA;
 
    PDI_IO |= PDI_bmCLK;
 
}
 
 
 
void nvm_done2() {      // deactivate the NVM controller
 
    nvm_register_write(NVM_CMD,0);       // VNM NOP
 
 
 
    PDI_IO &= ~PDI_bmDATA;
 
    PDI_IO |= PDI_bmCLK;
 
}
 
 
 
 
 
/* *********************************************************************
 
   ***** nvm_read ******************************************************
 
   ********************************************************************* */
 
// read NVM
 
BYTE nvm_read ( __xdata BYTE *buf, DWORD addr, BYTE length ) {
 
    BYTE ol = length;
 
 
 
    if ( length == 0 )
 
        return 0;
 
 
 
    nvm_register_write(NVM_CMD,0x43);    // load NVM read command into NVM CMD register
 
 
 
    pdi_send( 0x6b );            // set ptr
 
    pdi_send( addr & 255 );
 
    pdi_send( (addr>>8) & 255 );
 
    pdi_send( (addr>>16) & 255 );
 
    pdi_send( (addr>>24) & 255 );
 
 
 
    pdi_send( 0xa0 );           // repeat cmd
 
    pdi_send( length-1 );
 
    pdi_send( 0x24 );           // read one byte cmd
 
    while ( (length!=0) && (xmega_ec==0) ) {
 
        *buf = pdi_read(); buf++;
 
        length-= 1;
 
    }
 
 
 
    return ol-length;
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_page_load *************************************************
 
   ********************************************************************* */
 
// write data into NVM page buffer. Flash: cmd=0x23 , EEPROM: cmd=0x33
 
#define[nvm_flash_page_load(][);][nvm_page_load(0x23, $0);]
 
#define[nvm_eeprom_page_load(][);][nvm_page_load(0x33, $0);]
 
 
 
void nvm_page_load ( BYTE cmd, __xdata BYTE *buf, DWORD addr, BYTE length ) {
 
    BYTE ol = length;
 
 
 
    if ( length == 0 )
 
        return;
 
 
 
    nvm_register_write(NVM_CMD,cmd);    // load "Load Page Buffer" command into CMD register NVM CMD register
 
 
 
    pdi_send( 0x6b );            // set ptr
 
    pdi_send( addr & 255 );
 
    pdi_send( (addr>>8) & 255 );
 
    pdi_send( (addr>>16) & 255 );
 
    pdi_send( (addr>>24) & 255 );
 
 
 
    pdi_send( 0xa0 );           // repeat cmd
 
    pdi_send( length-1 );
 
    pdi_send( 0x64 );           // write one byte cmd
 
    while ( length!=0 ) {
 
        pdi_send(*buf); buf++;
 
        length-= 1;
 
    }
 
}
 
 
 
 
 
/* *********************************************************************
 
   ***** nvm_page_write ************************************************
 
   ********************************************************************* */
 
// erase and write nvm page 
 
#define[nvm_flash_page_write(][);][nvm_page_write(((BYTE)((($0)>>16) & 255)) < nvm_boot_base ? 0x25 : 0x2d, $0);]
 
#define[nvm_eeprom_page_write(][);][nvm_page_write(0x35, $0);]
 
void nvm_page_write (BYTE cmd, DWORD addr ) {
 
    nvm_register_write(NVM_CMD, cmd);   // load "erase and write page" command into NVM CMD register
 
 
 
    pdi_send( 0x4c   );                 // direct write
 
    pdi_send( addr & 255 );
 
    pdi_send( (addr>>8) & 255 );
 
    pdi_send( (addr>>16) & 255 );
 
    pdi_send( (addr>>24) & 255 );
 
    pdi_send( 0 );
 
 
 
    nvm_wait_busy();
 
}
 
 
 
/* *********************************************************************
 
   ***** nvm_fuse_write ************************************************
 
   ********************************************************************* */
 
// write fuse
 
void nvm_fuse_write (BYTE idx, BYTE val) {
 
    nvm_register_write(NVM_CMD, 0x4c);   // load "write fuse" command into NVM CMD register
 
 
 
    pdi_send( 0x4c   );                 // direct write
 
    pdi_send( 0x20 | idx );
 
    pdi_send( 0 );
 
    pdi_send( 0x8f );
 
    pdi_send( 0 );
 
    pdi_send( val );
 
 
 
  nvm_wait_busy();
 
}
 
 
 
/* *********************************************************************
 
   ***** xmega_reset ***************************************************
 
   ********************************************************************* */
 
// reset the xmega
 
void xmega_reset () {
 
    OEPDI_PORT |= bmBITPDI_BIT_CLK;
 
    uwait(20);                  // disable
 
    PDI_IO &= ~PDI_bmCLK;       // enable reset
 
 
 
    uwait(5);
 
    PDI_IO |= PDI_bmCLK;
 
}
 
 
 
/* *********************************************************************
 
   ***** xmega_init ****************************************************
 
   ********************************************************************* */
 
void xmega_init() {
 
    __xdata BYTE xmega_id[3];
 
 
 
    nvm_page_type = 0;
 
    xmega_flash_pages = 0;
 
    xmega_eeprom_pages = 64;
 
    xmega_eeprom_page_size = 5;
 
    xmega_flash_page_size = 9;
 
 
 
 
 
    nvm_init();
 
    if ( xmega_ec != 0 )
 
        return;
 
    nvm_read(xmega_id, 0x01000090, 3);
 
    if ( xmega_ec != 0 )
 
        return;
 
    nvm_done();
 
 
 
    if ( xmega_id[0] != 0x1e ) {
 
        xmega_ec = XMEGA_EC_INVALID_DEVICE;
 
        return;
 
    }
 
 
 
/*  if (  xmega_id[1] == 0x96 && xmega_id[2] == 0x4e ) {        // 64A1 currently not supported
 
        mega_flash_pages = 272;
 
        mega_flash_page_size = 8;
 
        nvm_boot_base = 0x81;
 
    } */
 
    if (  xmega_id[1] == 0x97 && xmega_id[2] == 0x4c ) {        // 128A1
 
        xmega_flash_pages = 272;
 
        nvm_boot_base = 0x82;
 
    }
 
    else if (  xmega_id[1] == 0x97 && xmega_id[2] == 0x4e ) {   // 192A1
 
        xmega_flash_pages = 400;
 
        nvm_boot_base = 0x83;
 
    }
 
    else if (  xmega_id[1] == 0x98 && xmega_id[2] == 0x46 ) {   // 256A1
 
        xmega_flash_pages = 528;
 
        xmega_eeprom_pages = 128;
 
        nvm_boot_base = 0x84;
 
    }
 
    else {
 
        xmega_ec = XMEGA_EC_INVALID_DEVICE;
 
    }
 
}
 
 
 
 
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor request 0x48 ***************************************
 
   ********************************************************************* */
 
// send xmega error and status information to the host
 
ADD_EP0_VENDOR_REQUEST((0x48,,
 
    MEM_COPY1(xmega_ec,EP0BUF,7);
 
    EP0BCH = 0;
 
    EP0BCL = 7;
 
,,
 
    NOP;
 
));;
 
 
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor request 0x49 ***************************************
 
   ********************************************************************* */
 
// reset xmega   
 
ADD_EP0_VENDOR_COMMAND((0x49,,
 
    xmega_reset();
 
,,
 
    NOP;
 
));;
 
 
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor requests 0x4A, 0x4B, 0x4C,0x4D *********************
 
   ********************************************************************* */
 
// read from nvm using: pdi address space (0x4a), flash base (0x4b), EEPROM base (0x4c), FUSE base (0x4d) 
 
BYTE nvm_read_ep0 () {
 
    BYTE i, b;
 
    b = ep0_payload_transfer;
 
    if ( b == 0 )
 
        return 0;
 
 
 
    nvm_init();
 
    i = xmega_ec==0 ? nvm_read(EP0BUF, nvm_addr, b) : 0;
 
    nvm_done();
 
 
 
    nvm_addr += b;
 
    return i;
 
}
 
 
 
ADD_EP0_VENDOR_REQUEST((0x4a: case 0x4b: case 0x4c: case 0x4d,,                 // read from NVM
 
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
 
    if ( bRequest == 0x4b ) {                                                   // read from Flash
 
        nvm_addr += XMEGA_FLASH_START;
 
    }
 
    else if ( bRequest == 0x4c ) {                                              // read from EEPROM
 
        nvm_addr += XMEGA_EEPROM_START;
 
    }
 
    else if ( bRequest == 0x4d ) {                                              // read FUSES
 
        nvm_addr += XMEGA_FUSE_START;
 
    }
 
    EP0BCH = 0;
 
    EP0BCL = nvm_read_ep0();
 
,,
 
    EP0BCH = 0;
 
    EP0BCL = nvm_read_ep0();
 
));;
 
 
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor command 0x4B ***************************************
 
   ********************************************************************* */
 
// write exactly one flash page
 
void nvm_flash_write_ep0 () {
 
    BYTE b;
 
    b = ep0_payload_transfer;
 
 
 
    nvm_init();
 
    if ( xmega_ec != 0 )
 
        return;
 
 
 
    nvm_flash_page_load(EP0BUF, nvm_addr, b);
 
 
 
    if ( ep0_payload_remaining == 0 ) {
 
        nvm_flash_page_write( nvm_addr );
 
        nvm_done();
 
    }
 
    else {
 
        nvm_done2();
 
    }
 
 
 
    nvm_addr += b;
 
}
 
 
 
ADD_EP0_VENDOR_COMMAND((0x4B,,
 
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
 
    nvm_addr += XMEGA_FLASH_START;
 
    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
 
    {
 
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
 
        EP0_STALL;
 
    }
 
,,
 
    if ( ep0_payload_transfer != 0 ) {
 
        xmega_ec = 0;
 
        nvm_flash_write_ep0();
 
        if ( xmega_ec != 0 ) {
 
            EP0_STALL;
 
        }
 
    }
 
));;
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor command 0x4C ***************************************
 
   ********************************************************************* */
 
// write exactly one EEPROM page
 
ADD_EP0_VENDOR_COMMAND((0x4C,,
 
    nvm_addr = *(DWORD*)(&SETUPDAT[2]);
 
    nvm_addr += XMEGA_EEPROM_START;
 
    if ( ( SETUPDAT[2] & 31 ) != 0 || SETUPDAT[7]!=0 || SETUPDAT[6]!=32 || (*(WORD*)(&SETUPDAT[2])>>5)>=xmega_eeprom_pages )  // only 32 byte pages supported
 
    {
 
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
 
        EP0_STALL;
 
    }
 
 
 
    nvm_init();
 
    if ( xmega_ec != 0 )
 
        return;
 
 
 
    nvm_eeprom_page_load(EP0BUF, nvm_addr, 32);
 
    nvm_eeprom_page_write( nvm_addr );
 
    nvm_done();
 
,,
 
));;
 
 
 
/* *********************************************************************
 
   ***** EP0 vendor command 0x4D ***************************************
 
   ********************************************************************* */
 
// write one fuse
 
ADD_EP0_VENDOR_COMMAND((0x4D,,
 
    if ( SETUPDAT[6]!=0 || SETUPDAT[7]!=0 || SETUPDAT[5]!=0 || SETUPDAT[4]>7 )
 
    {
 
        xmega_ec = XMEGA_EC_ADDRESS_ERROR;
 
        EP0_STALL;
 
    }
 
 
 
    nvm_init();
 
    nvm_fuse_write(SETUPDAT[4], SETUPDAT[2]);
 
    nvm_done();
 
,,
 
    NOP;
 
));;
 
 
 
 
#endif  /*ZTEX_XMEGA_H*/
#endif  /*ZTEX_XMEGA_H*/
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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