/* 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 = 0, 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));
    while(len--){   /* len may be 0 */
        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);    /* <-- data clocked by device */
            shift <<= 1;
            port &= ~(1 << PORT_BIT(HWPIN_ISP_MOSI));
#if METABOARD_HARDWARE
            if(PORT_PIN_VALUE(HWPIN_ISP_MISO))  /* no driver in this hardware */
                shift |= 1;
#else /* METABOARD_HARDWARE */
            if(!PORT_PIN_VALUE(HWPIN_ISP_MISO)) /* driver is inverting */
                shift |= 1;
#endif /* METABOARD_HARDWARE */
            sei();
            timerTicksDelay(delay);
            cli();
            PORT_PIN_CLR(HWPIN_ISP_SCK);    /* <-- device changes data */
        }while(--cnt);
    }
    sei();
/*    DBG2(0x41, &shift, 1); */
    return shift;
}
Example #2
0
static void ispAttachToDevice(_u8 stk500Delay, _u8 stabDelay)
{

    if(stk500Delay == 0){ /* 1.8 MHz nominal */
        ispClockDelay = 0;
    }else if(stk500Delay == 1){ /* 460 kHz nominal */
        ispClockDelay = 0;
    }else if(stk500Delay == 2){ /* 115 kHz nominal */
        ispClockDelay = 1;
    }else if(stk500Delay == 3){ /* 58 kHz nominal */
        ispClockDelay = 2;
    }else{
        /* from STK500v2 spec: stk500Delay = 1/(24 * SCK / 7.37 MHz) - 10/12
         * definition of ispClockDelay = 1 + 1/(SCK/MHz * 2 * TIMER_TICK_US)
         * ispClockDelay = 1 + (stk500Delay + 10/12) * 12 / (TIMER_TICK_US * 7.37)
         */
#if F_CPU > 14000000L    /* ~ 16 MHz */
        ispClockDelay = (stk500Delay + 1)/2 - (stk500Delay + 1)/8 + (stk500Delay + 1)/32;
#else   /* must be 12 MHz */
        ispClockDelay = (stk500Delay + 1)/4 + (stk500Delay + 1)/16;
#endif
    }

    LED_TX_ON();
    /* turn on power for programming sockets: */
    PIN_MODE(ISP_SCK, OUTPUT);
    PIN_MODE(ISP_MOSI,OUTPUT);

//    delay(200);   /* allow device to power up */
    PIN_MODE(ISP_RST,OUTPUT);

    delay(stabDelay);
    
    timerTicksDelay(ispClockDelay); /* stabDelay may have been 0 */
    DIGITAL_WRITE(ISP_RST, HIGH);   /* give positive RESET pulse */
    timerTicksDelay(ispClockDelay);
    DIGITAL_WRITE(ISP_RST, LOW);   /* bring RESET back low */
}
Example #3
0
_u8   ispEnterProgmode(stkEnterProgIsp_t *param)
{
    _u8   i, rval;
    ispAttachToDevice(stkParam.s.sckDuration, param->stabDelay);
    delay(param->cmdExeDelay);
    /* we want for(i = param->synchLoops; i--;), but avrdude sends synchLoops == 0 */
    for(i = 32; 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: */
        DIGITAL_WRITE(ISP_SCK, HIGH);
        timerTicksDelay(ispClockDelay);
        DIGITAL_WRITE(ISP_SCK, LOW);
        timerTicksDelay(ispClockDelay);
    }
    ispDetachFromDevice();
    return STK_STATUS_CMD_FAILED;   /* failure */
}
Example #4
0
/* We disable interrupts while transfer a byte. This ensures that we execute
 * at nominal speed, in spite of aggressive USB polling.
 */
static _u8 ispBlockTransfer(_u8 *block, _u8 len)
{
    _u8   cnt, shift = 0, port, delay = ispClockDelay;

    /* minimum clock pulse width:
     * 5 + 4 * delay clock cycles           -> Tmin = 750 ns
     * total clock period: 12 + 8 * delay   -> fmax = 600 kHz
     */
    cli();
    while(len--){   /* len may be 0 */
        cnt = 8;
        shift = *block++;
        do{
            if(shift & 0x80){
                DIGITAL_WRITE(ISP_MOSI, HIGH);
            }else
            {
                DIGITAL_WRITE(ISP_MOSI, LOW);
            }
            sei();
            timerTicksDelay(delay);
            cli(); 
            DIGITAL_WRITE(ISP_SCK, HIGH);  /* <-- data clocked by device */
            shift <<= 1;

            if(DIGITAL_READ(ISP_MISO))  /* no driver in this hardware */
                shift |= 1;
            sei();
            timerTicksDelay(delay);
            cli();
            DIGITAL_WRITE(ISP_SCK, LOW);    /* <-- device changes data */
        }while(--cnt);
    }
    sei();
    return shift;
}
static void ispAttachToDevice(uchar stk500Delay, uchar stabDelay)
{
#if !METABOARD_HARDWARE /* on metaboard, we use the jumper to select CDC vs. HID mode */
    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
#endif
    if(stk500Delay == 0){ /* 1.8 MHz nominal */
        ispClockDelay = 0;
    }else if(stk500Delay == 1){ /* 460 kHz nominal */
        ispClockDelay = 0;
    }else if(stk500Delay == 2){ /* 115 kHz nominal */
        ispClockDelay = 1;
    }else if(stk500Delay == 3){ /* 58 kHz nominal */
        ispClockDelay = 2;
    }else{
        /* from STK500v2 spec: stk500Delay = 1/(24 * SCK / 7.37 MHz) - 10/12
         * definition of ispClockDelay = 1 + 1/(SCK/MHz * 2 * TIMER_TICK_US)
         * ispClockDelay = 1 + (stk500Delay + 10/12) * 12 / (TIMER_TICK_US * 7.37)
         */
#if F_CPU > 14000000L    /* ~ 16 MHz */
        ispClockDelay = (stk500Delay + 1)/2 - (stk500Delay + 1)/8 + (stk500Delay + 1)/32;
#else   /* must be 12 MHz */
        ispClockDelay = (stk500Delay + 1)/4 + (stk500Delay + 1)/16;
#endif
    }
#if METABOARD_HARDWARE
    PORT_PIN_CLR(HWPIN_LED);        /* turn on LED */
    /* turn on power for programming sockets: */
    PORT_OUT(HWPIN_ISP_SUPPLY1) |= _BV(PORT_BIT(HWPIN_ISP_SUPPLY1)) | _BV(PORT_BIT(HWPIN_ISP_SUPPLY2));
#ifdef HWPIN_ISP_CLK
    PORT_DDR_SET(HWPIN_ISP_CLK);    /* turn on optional clock for programming socket */
#endif
    PORT_DDR_SET(HWPIN_ISP_SCK);    /* enable programming I/O pins */
    PORT_DDR_SET(HWPIN_ISP_MOSI);
    timerMsDelay(200);              /* allow device to power up */
    PORT_DDR_SET(HWPIN_ISP_RESET);
    timerMsDelay(stabDelay);
    timerTicksDelay(ispClockDelay); /* stabDelay may have been 0 */
    PORT_PIN_SET(HWPIN_ISP_RESET);  /* give positive RESET pulse */
    timerTicksDelay(ispClockDelay);
    PORT_PIN_CLR(HWPIN_ISP_RESET);  /* bring RESET back low */
#else /* METABOARD_HARDWARE */
    PORT_PIN_SET(HWPIN_LED);
    /* 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);
#endif /* METABOARD_HARDWARE */
}