?? hvprog.c
字號:
/* * Name: hvprog.c * Project: AVR-Doper * Author: Christian Starkjohann <cs@obdev.at> * Creation Date: 2006-07-07 * Tabsize: 4 * Copyright: (c) 2006 by Christian Starkjohann, all rights reserved. * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt) * Revision: $Id: hvprog.c 566 2008-04-26 14:21:47Z cs $ */#include "hardware.h"#if ENABLE_HVPROG#include <avr/io.h>#include <avr/wdt.h>#include "timer.h"#include "utils.h"#include "hvprog.h"/* This module can handle high voltage serial and parallel programming. Serial * programming can be understood as a serial interface to parallel programming: * SDI represents programming data and SII a serial input for the control * input lines /OE, /WR, BS1, XA0, XA1, PAGEL, and BS2. * In order to handle both with similar code, we define the function * hvSetControlAndData() which takes care of the underlying mechanism. *//* control lines for high voltage serial (and parallel) programming *//* 7 6 5 4 | 3 2 1 0 n/a XA1 XA0 BS1 | /WR /OE BS2 PAGEL*/#define HVCTL_PAGEL (1 << 0)#define HVCTL_BS2 (1 << 1)#define HVCTL_nOE (1 << 2)#define HVCTL_nWR (1 << 3)#define HVCTL_BS1 (1 << 4)#define HVCTL_XA0 (1 << 5)#define HVCTL_XA1 (1 << 6)/* actions: */#define HV_ADDR 0#define HV_DATA HVCTL_XA0#define HV_CMD HVCTL_XA1#define HV_NONE (HVCTL_XA1 | HVCTL_XA0)#define HV_PAGEL (HVCTL_XA1 | HVCTL_XA0 | HVCTL_PAGEL)/* bytes: */#define HV_LOW 0#define HV_HIGH HVCTL_BS1#define HV_EXT HVCTL_BS2#define HV_EXT2 (HVCTL_BS1 | HVCTL_BS2)/* modes: */#define HV_READ HVCTL_nWR#define HV_WRITE HVCTL_nOE#define HV_NORW (HVCTL_nWR | HVCTL_nOE)#define HVCTL(action, byte, mode) ((action) | (byte) | (mode))/* high voltage parallel and serial programming commands */#define HVCMD_CHIP_ERASE 0x80#define HVCMD_WRITE_FUSE 0x40#define HVCMD_WRITE_LOCK 0x20#define HVCMD_WRITE_FLASH 0x10#define HVCMD_WRITE_EEPROM 0x11#define HVCMD_READ_SIGCAL 0x08#define HVCMD_READ_FUSELCK 0x04#define HVCMD_READ_FLASH 0x02#define HVCMD_READ_EEPROM 0x03#define HVCMD_NOP 0x00/* ------------------------------------------------------------------------- */static uchar progModeIsPp; /* use parallel programming primitives */static uchar hvPollTimeout;/*Implementing High Voltage Parallel Programming:4 functions have to be implemented for HVPP:ppEnterProgmode() This function brings the port lines into the state required for programming.ppLeaveProgmode() This function turns off all signals to the target device.ppExecute() This function reads data, sets data and sets control lines according to the parameters passed to the function.ppPoll() This function polls for "programming ready".You may have to add global variables to communicate additional parameterssuch as e.g. write pulse width. See the hvsp* function implementation formore information.*//* ------------------------------------------------------------------------- */static uchar hvspExecute(uchar ctlLines, uchar data){uchar cnt, r = 0, port; port = PORT_OUT(HWPIN_HVSP_SII) & ~((1<<PORT_BIT(HWPIN_HVSP_SII)) | (1<<PORT_BIT(HWPIN_HVSP_SDI))); PORT_OUT(HWPIN_HVSP_SII) = port; PORT_PIN_SET(HWPIN_HVSP_SCI); cnt = 8; PORT_PIN_CLR(HWPIN_HVSP_SCI); do{ r <<= 1; if(PORT_PIN_VALUE(HWPIN_HVSP_SDO)) r |= 1; if(data & 0x80) port |= 1 << PORT_BIT(HWPIN_HVSP_SDI); if(ctlLines & 0x80) port |= 1 << PORT_BIT(HWPIN_HVSP_SII); PORT_OUT(HWPIN_HVSP_SII) = port; PORT_PIN_SET(HWPIN_HVSP_SCI); port &= ~((1<<PORT_BIT(HWPIN_HVSP_SII)) | (1<<PORT_BIT(HWPIN_HVSP_SDI))); ctlLines <<= 1; data <<= 1; PORT_PIN_CLR(HWPIN_HVSP_SCI); }while(--cnt); PORT_OUT(HWPIN_HVSP_SII) = port; /* clock out two zeros */ PORT_PIN_SET(HWPIN_HVSP_SCI); PORT_PIN_CLR(HWPIN_HVSP_SCI); PORT_PIN_SET(HWPIN_HVSP_SCI); PORT_PIN_CLR(HWPIN_HVSP_SCI); return r;}/* This function applies 'data' to the data lines, 'ctlLines' to the control * lines and returns the status of the data lines BEFORE any control lines * were changed. These somewhat strange semantics are required for * compatibility with HV serial programming. */static uchar hvSetControlAndData(uchar ctlLines, uchar data){ /* ### insert if(progModeIsPp){}else{} here */ return hvspExecute(ctlLines, data);}/* ------------------------------------------------------------------------- */#if 1void hvspEnterProgmode(stkEnterProgHvsp_t *param){ progModeIsPp = 0; PORT_PIN_SET(HWPIN_LED); TCCR2 &= ~(1 << COM20); /* clear toggle on compare match mode */ PORT_PIN_SET(HWPIN_HVSP_RESET); PORT_PIN_CLR(HWPIN_HVSP_SUPPLY); PORT_DDR(HWPIN_HVSP_SDO) |= (1 << PORT_BIT(HWPIN_HVSP_SDO)); TIMER_US_DELAY(40); PORT_PIN_CLR(HWPIN_HVSP_RESET); PORT_DDR_CLR(HWPIN_HVSP_HVRESET); /* use internal pull-up to source current */ PORT_PIN_SET(HWPIN_HVSP_HVRESET); TIMER_US_DELAY(15); PORT_DDR(HWPIN_HVSP_SDO) &= ~(1 << PORT_BIT(HWPIN_HVSP_SDO)); /* prevent contention */ TIMER_US_DELAY(300);}#else/* This is the new mechanism to enter prog mode which is closer to the method * described in the ATTiny45 data sheet, but it seems to fail on some of the * ATTiny45. We therefore stick with the old method, but leave this code * for reference. */void hvspEnterProgmode(stkEnterProgHvsp_t *param){uchar i; progModeIsPp = 0; PORT_PIN_SET(HWPIN_LED); TCCR2 &= ~(1 << COM20); /* clear toggle on compare match mode */ PORT_PIN_SET(HWPIN_HVSP_RESET); PORT_PIN_CLR(HWPIN_HVSP_SUPPLY); for(i = 0; i < 16; i++){ /* ATTiny[248]4 data sheet says: toggle SCI at least 6 times */ TIMER_US_DELAY(20); PORT_OUT(HWPIN_HVSP_SCI) ^= 1 << PORT_BIT(HWPIN_HVSP_SCI); } PORT_DDR_SET(HWPIN_HVSP_SDO); TIMER_US_DELAY(45); PORT_PIN_CLR(HWPIN_HVSP_RESET); PORT_DDR_CLR(HWPIN_HVSP_HVRESET); /* use internal pull-up to source current */ PORT_PIN_SET(HWPIN_HVSP_HVRESET); TIMER_US_DELAY(20); PORT_DDR_CLR(HWPIN_HVSP_SDO); /* prevent contention */ TIMER_US_DELAY(300);}#endifvoid hvspLeaveProgmode(stkLeaveProgHvsp_t *param){ PORT_PIN_CLR(HWPIN_HVSP_HVRESET); PORT_DDR_SET(HWPIN_HVSP_HVRESET); /* output low level */ PORT_PIN_SET(HWPIN_HVSP_RESET); PORT_OUT(HWPIN_HVSP_SII) &= ~((1<<PORT_BIT(HWPIN_HVSP_SII)) | (1<<PORT_BIT(HWPIN_HVSP_SDI))); PORT_PIN_SET(HWPIN_HVSP_SUPPLY); PORT_PIN_CLR(HWPIN_HVSP_RESET); PORT_PIN_CLR(HWPIN_LED);}/* ------------------------------------------------------------------------- */void ppEnterProgmode(stkEnterProgPp_t *param){ progModeIsPp = 1; /* ### not implemented yet */}void ppLeaveProgmode(stkLeaveProgPp_t *param){ /* ### not implemented yet */}/* ------------------------------------------------------------------------- */static uchar hvspPoll(void){uchar rval = STK_STATUS_CMD_OK; timerSetupTimeout(hvPollTimeout); while(!PORT_PIN_VALUE(HWPIN_HVSP_SDO)){ if(timerTimeoutOccurred()){ rval = STK_STATUS_CMD_TOUT; break; } } return rval;}static uchar hvPoll(void){ /* ### insert if(progModeIsPp){}else{} here */ return hvspPoll();}/* ------------------------------------------------------------------------- */static uchar hvChipErase(uchar eraseTime){uchar rval = STK_STATUS_CMD_OK;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -