📄 dapa.c
字号:
// $Id: DAPA.C,v 1.3.4.2 2003/08/18 22:09:46 cssharp Exp $/* * $Id: DAPA.C,v 1.3.4.2 2003/08/18 22:09:46 cssharp Exp $ * **************************************************************************** * * uisp - The Micro In-System Programmer for Atmel AVR microcontrollers. * Copyright (C) 1999, 2000, 2001, 2002, 2003 Sergey Larin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * **************************************************************************** *//* DAPA.C Direct AVR Parallel Access (c) 1999 Originally written by Sergey Larin. Corrected by Denis Chertykov, Uros Platise and Marek Michalkiewicz*/#ifndef NO_DAPA//#define DEBUG//#define DEBUG1#include "config.h"#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <ctype.h>#ifndef NO_DIRECT_IO/* Linux and FreeBSD differ in the order of outb() arguments. XXX any other OS/architectures with PC-style parallel ports? XXX how about the other *BSDs? */#if defined(__linux__) && defined(__i386__)#include <sys/io.h>#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(val, port)#define ioport_enable(port, num) ({ \ int x = ioperm(port, num, 1); usleep(1); x; }) #define ioport_disable(port, num) ({ \ int x = ioperm(port, num, 0); usleep(1); x; })#elif defined(__CYGWIN__)#include "cygwinp.h"#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(val, port)#define ioport_enable(port, num) ioperm(port, num, 1)#define ioport_disable(port, num) ioperm(port, num, 0)#elif defined(__FreeBSD__) && defined(__i386__)#include <sys/fcntl.h>#include <machine/cpufunc.h>#include <machine/sysarch.h>#define ioport_read(port) inb(port)#define ioport_write(port, val) outb(port, val)#define ioport_enable(port, num) i386_set_ioperm(port, num, 1)#define ioport_disable(port, num) i386_set_ioperm(port, num, 0)#else/* Direct I/O port access not supported - ppdev/ppi kernel driver required for parallel port support to work at all. Only likely to work on PC-style parallel ports (all signals implemented) anyway. The only lines believed to be implemented in all parallel ports are: D0-D6 outputs (long long ago I heard of some non-PC machine with D7 hardwired to GND - don't remember what it was) BUSY input So far, only the dt006 interface happens to use a subset of the above. STROBE output might be pulsed by hardware and not be writable ACK input might only trigger an interrupt and not be readable Future designers of these "dongles" might want to keep this in mind. */#define ioport_read(port) (0xFF)#define ioport_write(port, val)#define ioport_enable(port, num) (-1)#define ioport_disable(port, num) (0)#endif#else /* NO_DIRECT_IO */#define ioport_read(port) (0xFF)#define ioport_write(port, val)#define ioport_enable(port, num) (-1)#define ioport_disable(port, num) (0)#endif /* NO_DIRECT_IO */#include <unistd.h>#include <signal.h>#include "timeradd.h"#include <sys/ioctl.h>#include <fcntl.h>#include "parport.h"/* These should work on any architecture, not just i386. */#if defined(__linux__)#include "ppdev.h"#define par_claim(fd) ioctl(fd, PPCLAIM, 0)#define par_read_status(fd, ptr) ioctl(fd, PPRSTATUS, ptr)#define par_write_data(fd, ptr) ioctl(fd, PPWDATA, ptr)#define par_write_ctrl(fd, ptr) ioctl(fd, PPWCONTROL, ptr)#define par_set_dir(fd, ptr) ioctl(fd, PPDATADIR, ptr)#define par_release(fd) ioctl(fd, PPRELEASE, 0)#elif defined(__FreeBSD__)#include </sys/dev/ppbus/ppi.h>#define par_claim(fd) (0)#define par_read_status(fd, ptr) ioctl(fd, PPIGSTATUS, ptr)#define par_write_data(fd, ptr) ioctl(fd, PPISDATA, ptr)#define par_write_ctrl(fd, ptr) ioctl(fd, PPISCTRL, ptr)/* par_set_dir not defined, par_write_ctrl used instead */#define par_release(fd)#else/* Dummy defines if ppdev/ppi not supported by the kernel. */#define par_claim(fd) (-1)#define par_read_status(fd, ptr)#define par_write_data(fd, ptr)#define par_write_ctrl(fd, ptr)#define par_release(fd)#endif#include "Global.h"#include "Error.h"#include "DAPA.h"#include "Avr.h"/* Parallel Port Base Address*/#define IOBASE parport_base#define IOSIZE 3/* FIXME: rewrite using tables to define new interface types. For each of the logical outputs (SCK, MOSI, RESET, ENA1, ENA2, power, XTAL1) there should be two bit masks that define which physical bits (from the parallel port output data or control registers, or serial port DTR/RTS/TXD) are affected, and if they should be inverted. More than one output may be changed. For each of the inputs (MISO, maybe TEST?), define which bit (only one, from parallel port status or CTS/DCD/DSR/RI) should be tested and if it should be inverted. One struct as described above should be initialized for each of the supported hardware interfaces. *//* Alex's Direct Avr Parallel Access */#define DAPA_SCK PARPORT_CONTROL_STROBE /* base + 2 */#define DAPA_RESET PARPORT_CONTROL_INIT /* base + 2 */#define DAPA_DIN PARPORT_STATUS_BUSY /* base + 1 */#define DAPA_DOUT 0x1 /* base *//* STK200 Direct Parallel Access */#define STK2_TEST1 0x01 /* D0 (base) - may be connected to POUT input */#define STK2_TEST2 0x02 /* D1 (base) - may be connected to BUSY input */#define STK2_ENA1 0x04 /* D2 (base) - ENABLE# for RESET#, MISO */#define STK2_ENA2 0x08 /* D3 (base) - ENABLE# for SCK, MOSI, LED# */#define STK2_SCK 0x10 /* D4 (base) - SCK */#define STK2_DOUT 0x20 /* D5 (base) - MOSI */#define STK2_LED 0x40 /* D6 (base) - LED# (optional) */#define STK2_RESET 0x80 /* D7 (base) - RESET# */#define STK2_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* Altera Byte Blaster Port Configuration*/#define ABB_EN PARPORT_CONTROL_AUTOFD /* low active */#define ABB_LPAD 0x80 /* D7: loop back throught enable auto-detect */#define ABB_SCK 0x01 /* D0: TCK (ISP conn. pin 1) */#define ABB_RESET 0x02 /* D1: TMS (ISP conn. pin 5) */#define ABB_DOUT 0x40 /* D6: TDI (ISP conn. pin 9) */#define ABB_DIN PARPORT_STATUS_BUSY /* BUSY: TDO (ISP conn. pin 3) *//* D5 (pin 7) connected to ACK (pin 10) directly *//* D7 (pin 9) connected to POUT (pin 12) via 74HC244 buffer *//* optional modification for AVREAL: D3 (pin 5) = XTAL1 (ISP conn. pin 8) */#define ABB_XTAL1 0x08/* XXX not yet supported, just documented here... Atmel-ISP Download Cable (P/N ATDH1150VPC) (10-pin connector similar to Altera Byte Blaster, but no 3-state outputs) http://www.atmel.com/atmel/acrobat/isp_c_v5.pdf VCC ---- 4 GND ---- 2,10 ---- GND SCK <- TCK(1) <- nSTROBE MISO -> TDO(3) -> nACK RESET <- TMS(5) <- SELECT MOSI <- TDI(9) <- D0 XTAL1 <- AF(8) <- AUTOFD (optional, not yet supported) */#define ATDH_SCK PARPORT_CONTROL_STROBE#define ATDH_DOUT 0x01#define ATDH_RESET PARPORT_CONTROL_SELECT#define ATDH_DIN PARPORT_STATUS_ACK#define ATDH_XTAL1 PARPORT_CONTROL_AUTOFD/* "Atmel AVR ISP" cable (?) */#define AISP_TSTOUT 0x08 /* D3 (base) - dongle test output */#define AISP_SCK 0x10 /* D4 (base) - SCK */#define AISP_DOUT 0x20 /* D5 (base) - MOSI */#define AISP_ENA 0x40 /* D6 (base) - ENABLE# for MISO, MOSI, SCK */#define AISP_RESET 0x80 /* D7 (base) - RESET# */#define AISP_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* BUSY and POUT used as inputs to test for the dongle *//* Yet another AVR ISP cable from http://www.bsdhome.com/avrprog/ */#define BSD_POWER 0x0F /* D0-D3 (base) - power */#define BSD_ENA 0x10 /* D4 (base) - ENABLE# */#define BSD_RESET 0x20 /* D5 (base) - RESET# */#define BSD_SCK 0x40 /* D6 (base) - SCK */#define BSD_DOUT 0x80 /* D7 (base) - MOSI */#define BSD_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* optional status LEDs, active low, not yet supported (base + 2) */#define BSD_LED_ERR PARPORT_CONTROL_STROBE /* error */#define BSD_LED_RDY PARPORT_CONTROL_AUTOFD /* ready */#define BSD_LED_PGM PARPORT_CONTROL_INIT /* programming */#define BSD_LED_VFY PARPORT_CONTROL_SELECT /* verifying *//* FBPRG - http://ln.com.ua/~real/avreal/adapters.html*/#define FBPRG_POW 0x07 /* D0,D1,D2 (base) - power supply (XXX D7 too?) */#define FBPRG_XTAL1 0x08 /* D3 (base) (not supported) */#define FBPRG_RESET 0x10 /* D4 (base) */#define FBPRG_DOUT 0x20 /* D5 (base) */#define FBPRG_SCK 0x40 /* D6 (base) */#define FBPRG_DIN PARPORT_STATUS_ACK /* ACK (base + 1) - MISO *//* DT006/Sample Electronics Parallel Cable http://www.dontronics.com/dt006.html*//* all at base, except for DT006_DIN at base + 1 */#define DT006_SCK 0x08#define DT006_RESET 0x04#define DT006_DIN PARPORT_STATUS_BUSY#define DT006_DOUT 0x01/* ETT-AVR V2.0 Programmer / Futurlec AT90S8535 */ #define ETT_SCK 0x01 /* DB25 Pin 2: D0 (Base + 0) -> SCK */#define ETT_RESET 0x02 /* DB25 Pin 3: D1 (Base + 0) -> RESET */#define ETT_DIN PARPORT_STATUS_ACK /* DB25 Pin 10: ACK (Base + 1) -> MISO */#define ETT_DOUT PARPORT_CONTROL_STROBE /* DB25 Pin 1: STROBE (Base + 2) -> MOSI *//* ABC Maxi - just like DT006 with two pins swapped *//* all at base, except for MAXI_DIN at base + 1 */#define MAXI_SCK 0x02#define MAXI_RESET 0x04#define MAXI_DIN PARPORT_STATUS_ACK#define MAXI_DOUT 0x01/* Xilinx JTAG download cable RESET=TMS, SCK=TCK, MISO=TDO, MOSI=TDI*/#define XIL_DOUT 0x01 /* D0: TDI */#define XIL_SCK 0x02 /* D1: TCK */#define XIL_RESET 0x04 /* D2: TMS */#define XIL_ENA 0x08 /* D3: ENABLE# */#define XIL_DIN PARPORT_STATUS_SELECT /* SLCT: TDO *//* Default value for minimum SCK high/low time in microseconds. */#ifndef SCK_DELAY#define SCK_DELAY 5#endif/* Minimum RESET# high time in microseconds. Should be enough to charge a capacitor between RESET# and GND (it is recommended to use a voltage detector with open collector output, and only something like 100 nF for noise immunity). Default value may be changed with -dt_reset=N microseconds. */#ifndef RESET_HIGH_TIME#define RESET_HIGH_TIME 1000#endif/* Delay from RESET# low to sending program enable command (the datasheet says it must be at least 20 ms). Also wait time for crystal oscillator to start after possible power down mode. */#ifndef RESET_LOW_TIME#define RESET_LOW_TIME 30000#endifvoidTDAPA::SckDelay(){ Delay_usec(t_sck);}#ifndef MIN_SLEEP_USEC#define MIN_SLEEP_USEC 20000#endifvoidTDAPA::Delay_usec(long t){ struct timeval t1, t2;#if defined(__CYGWIN__) if (cygwinp_delay_usec(t)) { return; }#endif if (t <= 0) return; /* very short delay for slow machines */ gettimeofday(&t1, NULL); if (t > MIN_SLEEP_USEC) usleep(t - MIN_SLEEP_USEC); /* loop for the remaining time */ t2.tv_sec = t / 1000000UL; t2.tv_usec = t % 1000000UL; timeradd(&t1, &t2, &t1); do { gettimeofday(&t2, NULL); } while (timercmp(&t2, &t1, <));}voidTDAPA::ParportSetDir(int dir){ if (dir) par_ctrl |= PARPORT_CONTROL_DIRECTION; else par_ctrl &= ~PARPORT_CONTROL_DIRECTION; if (ppdev_fd != -1) {#ifdef par_set_dir par_set_dir(ppdev_fd, &dir);#else par_write_ctrl(ppdev_fd, &par_ctrl);#endif } else ioport_write(IOBASE+2, par_ctrl);}voidTDAPA::ParportWriteCtrl(){ if (ppdev_fd != -1) par_write_ctrl(ppdev_fd, &par_ctrl); else ioport_write(IOBASE+2, par_ctrl);}voidTDAPA::ParportWriteData(){ if (ppdev_fd != -1) par_write_data(ppdev_fd, &par_data); else ioport_write(IOBASE, par_data);}voidTDAPA::ParportReadStatus(){ if (ppdev_fd != -1) par_read_status(ppdev_fd, &par_status); else par_status = ioport_read(IOBASE+1);}voidTDAPA::SerialReadCtrl(){#ifdef TIOCMGET ioctl(ppdev_fd, TIOCMGET, &ser_ctrl);#else ser_ctrl = 0;#endif}voidTDAPA::SerialWriteCtrl(){#ifdef TIOCMGET ioctl(ppdev_fd, TIOCMSET, &ser_ctrl);#endif}voidTDAPA::OutReset(int b) /* FALSE means active Reset at the AVR */ { if (reset_invert) b = !b; switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: if (b) par_ctrl |= DAPA_RESET; else par_ctrl &= ~DAPA_RESET; ParportWriteCtrl(); break; case PAT_STK200: if (b) par_data |= STK2_RESET; else par_data &= ~STK2_RESET; ParportWriteData(); break; case PAT_ABB: if (b) par_data |= ABB_RESET; else par_data &= ~ABB_RESET; ParportWriteData(); break; case PAT_AVRISP: if (b) par_data |= AISP_RESET; else par_data &= ~AISP_RESET; ParportWriteData(); break; case PAT_BSD: if (b) par_data |= BSD_RESET; else par_data &= ~BSD_RESET; ParportWriteData(); break; case PAT_FBPRG: if (b) par_data |= FBPRG_RESET; else par_data &= ~FBPRG_RESET; ParportWriteData(); break; case PAT_DT006: if (b) par_data |= DT006_RESET; else par_data &= ~DT006_RESET; ParportWriteData(); break; case PAT_ETT: if (b) par_data |= ETT_RESET; else par_data &= ~ETT_RESET; ParportWriteData(); break; case PAT_MAXI: if (b) par_data |= MAXI_RESET; else par_data &= ~MAXI_RESET; ParportWriteData(); break; case PAT_XIL: if (b) par_data |= XIL_RESET; else par_data &= ~XIL_RESET; ParportWriteData(); break; case PAT_DASA:#ifdef TIOCMGET SerialReadCtrl(); if (b) ser_ctrl |= TIOCM_RTS; else ser_ctrl &= ~TIOCM_RTS; SerialWriteCtrl();#endif /* TIOCMGET */ break; case PAT_DASA2:#if defined(TIOCMGET) && defined(TIOCCBRK) ioctl(ppdev_fd, b ? TIOCCBRK : TIOCSBRK, 0);#endif /* TIOCMGET */ break; } Delay_usec(b ? reset_high_time : RESET_LOW_TIME );}voidTDAPA::OutSck(int b){ if (sck_invert) b = !b;#ifdef DEBUG1 printf("%c",(b)?'S':'s');#endif switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: if (b) par_ctrl &= ~DAPA_SCK; else par_ctrl |= DAPA_SCK; ParportWriteCtrl(); break; case PAT_STK200: if (b) par_data |= STK2_SCK; else par_data &= ~STK2_SCK; ParportWriteData(); break; case PAT_ABB: if (b) par_data |= ABB_SCK; else par_data &= ~ABB_SCK; ParportWriteData(); break; case PAT_AVRISP: if (b) par_data |= AISP_SCK; else par_data &= ~AISP_SCK; ParportWriteData(); break; case PAT_BSD: if (b) par_data |= BSD_SCK; else par_data &= ~BSD_SCK; ParportWriteData(); break; case PAT_FBPRG: if (b) par_data |= FBPRG_SCK; else par_data &= ~FBPRG_SCK; ParportWriteData(); break; case PAT_DT006: if (b) par_data |= DT006_SCK; else par_data &= ~DT006_SCK; ParportWriteData(); break; case PAT_ETT: if (b) par_data |= ETT_SCK; else par_data &= ~ETT_SCK; ParportWriteData(); break; case PAT_MAXI: if (b) par_data |= MAXI_SCK; else par_data &= ~MAXI_SCK; ParportWriteData(); break; case PAT_XIL: if (b) par_data |= XIL_SCK; else par_data &= ~XIL_SCK; ParportWriteData(); break; case PAT_DASA:#if defined(TIOCMGET) SerialReadCtrl(); if (b) ser_ctrl |= TIOCM_DTR; else ser_ctrl &= ~TIOCM_DTR; SerialWriteCtrl();#endif /* TIOCMGET */ break; case PAT_DASA2:#if defined(TIOCMGET) if (b) ser_ctrl |= TIOCM_RTS; else ser_ctrl &= ~TIOCM_RTS; SerialWriteCtrl();#endif /* TIOCMGET */ break; }}voidTDAPA::OutEnaReset(int b){ bool no_ps2_hack = GetCmdParam("-dno-ps2-hack", false); switch (pa_type) { case PAT_DAPA: case PAT_DAPA_2: case PAT_FBPRG: case PAT_DT006: case PAT_ETT: case PAT_MAXI: if (b) { ParportSetDir(0); } else if (!no_ps2_hack) { /* No special enable line on these interfaces, for PAT_DAPA this only disables the data line (MOSI) and not SCK. */ ParportSetDir(1); } break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -