⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isp.c

📁 ATmega8实现USB接口(采用USB的CDC类
💻 C
字号:
#include "hardware.h"#include <avr/io.h>#include <avr/wdt.h>#include <avr/interrupt.h>#include "utils.h"#include <util/delay.h>#include "isp.h"#include "timer.h"#include "oddebug.h"static uchar    ispClockDelay;static uchar    cmdBuffer[4];/* ------------------------------------------------------------------------- *//* We disable interrupts while transfer a byte. This ensures that we execute * at nominal speed, in spite of aggressive USB polling. */static uchar ispBlockTransfer(uchar *block, uchar len){uchar   cnt, shift, port, delay = ispClockDelay;/* minimum clock pulse width: * 5 + 4 * delay clock cycles           -> Tmin = 750 ns * total clock period: 12 + 8 * delay   -> fmax = 600 kHz *//*    DBG2(0x40, block, len); */    cli();    port = PORT_OUT(HWPIN_ISP_MOSI) & ~(1 << PORT_BIT(HWPIN_ISP_MOSI));    do{        cnt = 8;        shift = *block++;        do{            if(shift & 0x80){                port |= (1 << PORT_BIT(HWPIN_ISP_MOSI));            }            PORT_OUT(HWPIN_ISP_MOSI) = port;            sei();            timerTicksDelay(delay);            cli();            PORT_PIN_SET(HWPIN_ISP_SCK);            shift <<= 1;            port &= ~(1 << PORT_BIT(HWPIN_ISP_MOSI));            if(!PORT_PIN_VALUE(HWPIN_ISP_MISO)) /* driver is inverting */                shift |= 1;            sei();            timerTicksDelay(delay);            cli();            PORT_PIN_CLR(HWPIN_ISP_SCK);        }while(--cnt);    }while(--len);    sei();/*    DBG2(0x41, &shift, 1); */    return shift;}/* ------------------------------------------------------------------------- */static uchar    deviceIsBusy(void){    cmdBuffer[0] = 0xf0;    cmdBuffer[1] = 0;    return ispBlockTransfer(cmdBuffer, 4) & 1;}static uchar    waitUntilReady(uchar msTimeout){    timerSetupTimeout(msTimeout);    while(deviceIsBusy()){        if(timerTimeoutOccurred())            return STK_STATUS_RDY_BSY_TOUT;    }    return STK_STATUS_CMD_OK;}/* ------------------------------------------------------------------------- */static void ispAttachToDevice(uchar stk500Delay, uchar stabDelay){    PORT_PIN_SET(HWPIN_LED);    if(!PORT_PIN_VALUE(HWPIN_JUMPER)){      /* Jumper is set -> request clock below 8 kHz */        ispClockDelay = (uchar)(70/TIMER_TICK_US);   /* 140 us -> 7.14 kHz clock rate */    }else if(stk500Delay == 0){ /* 1.8 MHz nominal */        ispClockDelay = 0;    }else if(stk500Delay == 1){ /* 460 kHz nominal */        ispClockDelay = 1;    }else if(stk500Delay == 2){ /* 115 kHz nominal */        ispClockDelay = 2;    }else if(stk500Delay == 3){ /* 58 kHz nominal */        ispClockDelay = 3;    }else{        ispClockDelay = 1 + stk500Delay/4 + stk500Delay/16;    }    /* setup initial condition: SCK, MOSI = 0 */    PORT_OUT(HWPIN_ISP_SCK) &= ~((1 << PORT_BIT(HWPIN_ISP_SCK)) | (1 << PORT_BIT(HWPIN_ISP_MOSI)));    PORT_PIN_SET(HWPIN_ISP_RESET);  /* set RESET */    PORT_DDR_CLR(HWPIN_ISP_DRIVER); /* make input: use internal pullup to control driver */    PORT_PIN_SET(HWPIN_ISP_DRIVER); /* attach to device: */    TCCR2 |= (1 << COM20);  /* set toggle on compare match mode -> activate clock */    timerMsDelay(stabDelay);    timerTicksDelay(ispClockDelay);    /* stabDelay may have been 0 */    /* We now need to give a positive pulse on RESET since we can't guarantee     * that SCK was low during power up (according to instructions in Atmel's     * data sheets).     */    PORT_PIN_CLR(HWPIN_ISP_RESET);  /* give a positive RESET pulse */    timerTicksDelay(ispClockDelay);    PORT_PIN_SET(HWPIN_ISP_RESET);}static void ispDetachFromDevice(uchar removeResetDelay){    PORT_OUT(HWPIN_ISP_SCK) &= ~((1 << PORT_BIT(HWPIN_ISP_SCK)) | (1 << PORT_BIT(HWPIN_ISP_MOSI)));    PORT_PIN_SET(HWPIN_ISP_RESET);    timerMsDelay(removeResetDelay);    TCCR2 &= ~(1 << COM20);  /* clear toggle on compare match mode */    PORT_PIN_CLR(HWPIN_ISP_DRIVER); /* detach from device */    PORT_DDR_SET(HWPIN_ISP_DRIVER); /* set pin level to low-Z 0 */    PORT_PIN_CLR(HWPIN_ISP_RESET);    PORT_PIN_CLR(HWPIN_LED);}/* ------------------------------------------------------------------------- */uchar   ispEnterProgmode(stkEnterProgIsp_t *param){uchar   i, rval;    ispAttachToDevice(stkParam.s.sckDuration, param->stabDelay);    timerMsDelay(param->cmdExeDelay);    for(i = param->synchLoops; i--;){        wdt_reset();        rval = ispBlockTransfer(param->cmd, param->pollIndex);        if(param->pollIndex < 4)            ispBlockTransfer(param->cmd + param->pollIndex, 4 - param->pollIndex);        if(rval == param->pollValue){   /* success: we are in sync */            return STK_STATUS_CMD_OK;        }        /* insert one clock pulse and try again: */        PORT_PIN_SET(HWPIN_ISP_SCK);        timerTicksDelay(ispClockDelay);        PORT_PIN_CLR(HWPIN_ISP_SCK);        timerTicksDelay(ispClockDelay);    }    ispDetachFromDevice(0);    return STK_STATUS_CMD_FAILED;   /* failure */}void    ispLeaveProgmode(stkLeaveProgIsp_t *param){    ispDetachFromDevice(param->preDelay);    timerMsDelay(param->postDelay);}/* ------------------------------------------------------------------------- */uchar   ispChipErase(stkChipEraseIsp_t *param){uchar   maxDelay = param->eraseDelay;uchar   rval = STK_STATUS_CMD_OK;    ispBlockTransfer(param->cmd, 4);    if(param->pollMethod != 0){        if(maxDelay < 10)   /* allow at least 10 ms */            maxDelay = 10;        rval = waitUntilReady(maxDelay);    }else{        timerMsDelay(maxDelay);    }    return rval;}/* ------------------------------------------------------------------------- */uchar   ispProgramMemory(stkProgramFlashIsp_t *param, uchar isEeprom){utilWord_t  numBytes;uchar       rval = STK_STATUS_CMD_OK;uchar       valuePollingMask, rdyPollingMask;uint        i;    numBytes.bytes[1] = param->numBytes[0];    numBytes.bytes[0] = param->numBytes[1];    if(param->mode & 1){    /* page mode */        valuePollingMask = 0x20;        rdyPollingMask = 0x40;    }else{                  /* word mode */        valuePollingMask = 4;        rdyPollingMask = 8;    }    for(i = 0; rval == STK_STATUS_CMD_OK && i < numBytes.word; i++){        uchar x;        wdt_reset();        cmdBuffer[1] = stkAddress.bytes[1];        cmdBuffer[2] = stkAddress.bytes[0];        cmdBuffer[3] = param->data[i];        x = param->cmd[0];        if(!isEeprom){            if((uchar)i & 1){                x |= 0x08;                stkIncrementAddress();            }else{                x &= ~0x08;            }        }else{            stkIncrementAddress();        }        cmdBuffer[0] = x;//        if(cmdBuffer[3] == 0xff && !(param->mode & 1) && !isEeprom)   /* skip 0xff in word mode *///            continue;        ispBlockTransfer(cmdBuffer, 4);        if(param->mode & 1){            /* is page mode */            if(i < numBytes.word - 1 || !(param->mode & 0x80))                continue;               /* not last byte written */            cmdBuffer[0] = param->cmd[1];     /* write program memory page */            ispBlockTransfer(cmdBuffer, 4);        }        /* poll for ready after each byte (word mode) or page (page mode) */        if(param->mode & valuePollingMask){ /* value polling */            uchar x = param->cmd[2];     /* read flash */            if((uchar)i & 1){                x |= 0x08;            }else{                x &= ~0x08;            }            cmdBuffer[0] = x;            timerSetupTimeout(param->delay);            while(ispBlockTransfer(cmdBuffer, 4) != param->poll[0]){                if(timerTimeoutOccurred()){                    rval = STK_STATUS_CMD_TOUT;                    break;                }            }        }else if(param->mode & rdyPollingMask){ /* rdy/bsy polling */            rval = waitUntilReady(param->delay);        }else{                          /* must be timed delay */            timerMsDelay(param->delay);        }    }    return rval;}/* ------------------------------------------------------------------------- */uint    ispReadMemory(stkReadFlashIsp_t *param, stkReadFlashIspResult_t *result, uchar isEeprom){utilWord_t  numBytes;uchar       *p, cmd0;uint        i;    cmdBuffer[3] = 0;    numBytes.bytes[1] = param->numBytes[0];    numBytes.bytes[0] = param->numBytes[1];    p = result->data;    result->status1 = STK_STATUS_CMD_OK;    cmd0 = param->cmd;    for(i = 0; i < numBytes.word; i++){        wdt_reset();        cmdBuffer[1] = stkAddress.bytes[1];        cmdBuffer[2] = stkAddress.bytes[0];        if(!isEeprom){            if((uchar)i & 1){                cmd0 |= 0x08;                stkIncrementAddress();            }else{                cmd0 &= ~0x08;            }        }else{            stkIncrementAddress();        }        cmdBuffer[0] = cmd0;        *p++ = ispBlockTransfer(cmdBuffer, 4);    }    *p = STK_STATUS_CMD_OK; /* status2 */    return numBytes.word + 2;}/* ------------------------------------------------------------------------- */uchar   ispProgramFuse(stkProgramFuseIsp_t *param){    ispBlockTransfer(param->cmd, 4);    return STK_STATUS_CMD_OK;}/* ------------------------------------------------------------------------- */uchar   ispReadFuse(stkReadFuseIsp_t *param){uchar   rval;    rval = ispBlockTransfer(param->cmd, param->retAddr);    if(param->retAddr < 4)        ispBlockTransfer(param->cmd + param->retAddr, 4 - param->retAddr);    return rval;}/* ------------------------------------------------------------------------- */uint    ispMulti(stkMultiIsp_t *param, stkMultiIspResult_t *result){uchar   cnt1, i, *p;    cnt1 = param->numTx;    if(cnt1 > param->rxStartAddr)        cnt1 = param->rxStartAddr;    ispBlockTransfer(param->txData, cnt1);    p = result->rxData;    for(i = 0; i < param->numTx - cnt1; i++){        uchar b = ispBlockTransfer(&param->txData[cnt1] + i, 1);        if(i < param->numRx)            *p++ = b;        wdt_reset();    }        for(; i < param->numRx; i++){        cmdBuffer[0] = 0;        *p++ = ispBlockTransfer(cmdBuffer, 1);        wdt_reset();    }    *p = result->status1 = STK_STATUS_CMD_OK;    return (uint)param->numRx + 2;}/* ------------------------------------------------------------------------- */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -