diff --git a/Makefile.am b/Makefile.am index 895c80c..82068a4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -111,6 +111,8 @@ libavrdude_a_SOURCES = \ lists.c \ lists.h \ my_ddk_hidsdi.h \ + nanonote.c \ + nanonote.h \ par.c \ par.h \ pgm.c \ diff --git a/config_gram.y b/config_gram.y index 99956c0..2837965 100644 --- a/config_gram.y +++ b/config_gram.y @@ -48,6 +48,7 @@ #include "avr.h" #include "jtagmkI.h" #include "jtagmkII.h" +#include "nanonote.h" #if defined(WIN32NATIVE) #define strtok_r( _s, _sep, _lasts ) \ @@ -99,6 +100,7 @@ static int parse_cmdbits(OPCODE * op); %token K_DRAGON_JTAG %token K_DRAGON_PDI %token K_DRAGON_PP +%token K_NANONOTE %token K_STK500_DEVCODE %token K_AVR910_DEVCODE %token K_EEPROM @@ -551,6 +553,12 @@ prog_parm : } } | + K_TYPE TKN_EQUAL K_NANONOTE { + { + nanonote_initpgm(current_prog); + } + } | + K_DESC TKN_EQUAL TKN_STRING { strncpy(current_prog->desc, $3->value.string, PGM_DESCLEN); current_prog->desc[PGM_DESCLEN-1] = 0; diff --git a/lexer.l b/lexer.l index c5ce360..5ffe36a 100644 --- a/lexer.l +++ b/lexer.l @@ -164,6 +164,7 @@ memory { yylval=NULL; return K_MEMORY; } min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; } miso { yylval=NULL; return K_MISO; } mosi { yylval=NULL; return K_MOSI; } +nanonote { yylval=NULL; return K_NANONOTE; } num_banks { yylval=NULL; return K_NUM_PAGES; } num_pages { yylval=NULL; return K_NUM_PAGES; } nvm_base { yylval=NULL; return K_NVM_BASE; } diff --git a/nanonote.c b/nanonote.c new file mode 100644 index 0000000..ff6ee81 --- /dev/null +++ b/nanonote.c @@ -0,0 +1,290 @@ +/* + * avrdude - A Downloader/Uploader for AVR device programmers + * Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean + * Copyright (C) 2005 Michael Holzt + * Copyright (C) 2006 Joerg Wunsch + * + * 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 + */ + +/* + * Posix serial bitbanging interface for avrdude. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "avr.h" +#include "pgm.h" +#include "bitbang.h" + + + +static volatile void *mem; + + +#define POWER_OFF 3, 2 /* PD02, drive low to enable power */ +#define CMD 3, 8 /* PD08, CMD */ +#define CLK 3, 9 /* PD09, CLK */ +#define DAT0 3, 10 /* PD10, DAT0 */ +#define DAT1 3, 11 /* PD11, DAT1 */ +#define DAT2 3, 12 /* PD12, DAT2 */ +#define DAT3 3, 13 /* PD13, DAT3 */ + + +static struct { + unsigned port; + unsigned bit; +} pin_map[] = { + { 0, 0}, /* 0: not assigned */ + { 3, 11 }, /* 1: PD11, DAT1 */ + { 3, 10 }, /* 2: PD12, DAT0 */ + { 0, 0 }, /* 3: VSS */ + { 0, 0 }, /* 4: PD09, CLK (reserved) */ + { 0, 0 }, /* 5: VDD */ + { 3, 8 }, /* 6: PD08, CMD */ + { 3, 13 }, /* 7: PD13, DAT3 */ + { 3, 12 } /* 8: PD13, DAT2 */ +}; + + +#define BASE 0x10010000 + +#define REG(off) (*(volatile uint32_t *) (mem+(off))) + +#define port_pin(port) REG(port*0x100) +#define port_dats(port) REG(port*0x100+0x14) +#define port_datc(port) REG(port*0x100+0x18) +#define port_func(port) REG(port*0x100+0x48) +#define port_dirs(port) REG(port*0x100+0x64) +#define port_dirc(port) REG(port*0x100+0x68) + + +static inline void gpio_high(unsigned port, unsigned bit) +{ + port_dats(port) = 1 << bit; +} + + +static void gpio_low(unsigned port, unsigned bit) +{ + port_datc(port) = 1 << bit; +} + + +static void gpio_set(unsigned port, unsigned bit, int value) +{ + if (value) + gpio_high(port, bit); + else + gpio_low(port, bit); +} + + +static int gpio_get(unsigned port, unsigned bit) +{ + return (port_pin(port) >> bit) & 1; +} + + +static void gpio_output(unsigned port, unsigned bit) +{ + port_dirs(port) = 1 << bit; +} + + +static void gpio_input(unsigned port, unsigned bit) +{ + port_dirc(port) = 1 << bit; +} + + +static int nanonote_setpin(PROGRAMMER *pgm, int pin, int value) +{ + if (pin & PIN_INVERSE) { + value = !value; + pin &= PIN_MASK; + } + + if (pin < 1 || pin >= sizeof(pin_map)/sizeof(*pin_map)) + return -1; + if (!pin_map[pin].port) + return -1; + +#if 0 +fprintf(stderr, "pin %d (%u, %u) = %d\n", +pin, pin_map[pin].port, pin_map[pin].bit, value); +#endif + gpio_set(pin_map[pin].port, pin_map[pin].bit, value); + + /* + * We get unstable results with values <= 16 but stable results + * with 17 and above. + */ + bitbang_delay(pgm->ispdelay+20); + + return 0; +} + + +static int nanonote_getpin(PROGRAMMER *pgm, int pin) +{ + int invert = 0; + int v; + + if (pin & PIN_INVERSE) { + invert = 1; + pin &= PIN_MASK; + } + + if (pin < 1 || pin >= sizeof(pin_map)/sizeof(*pin_map)) + return -1; + if (!pin_map[pin].port) + return -1; + + gpio_input(pin_map[pin].port, pin_map[pin].bit); /* @@@ hack */ + v = gpio_get(pin_map[pin].port, pin_map[pin].bit); +#if 0 +fprintf(stderr, "pin %d (%u, %u): %d\n", +pin, pin_map[pin].port, pin_map[pin].bit, v); +#endif + return pin & PIN_INVERSE ? !v : v; +} + + +static int nanonote_highpulsepin(PROGRAMMER *pgm, int pin) +{ + return -1; +} + + +static void nanonote_display(PROGRAMMER *pgm, const char *p) +{ + /* nothing */ +} + + +static void misc_high(PROGRAMMER *pgm) +{ + gpio_high(POWER_OFF); + gpio_high(DAT1); + gpio_high(DAT0); + gpio_high(CMD); + gpio_high(DAT3); + gpio_high(DAT2); +} + + +static void nanonote_enable(PROGRAMMER *pgm) +{ + misc_high(pgm); + /* @@@ set CLK to function and output clock */ +} + + +static void nanonote_disable(PROGRAMMER *pgm) +{ + misc_high(pgm); + /* @@@ set CLK to GPIO */ + gpio_high(CLK); +} + + +static void nanonote_powerup(PROGRAMMER *pgm) +{ + gpio_low(POWER_OFF); +} + + +static void nanonote_powerdown(PROGRAMMER *pgm) +{ + gpio_input(DAT0); + gpio_input(CLK); + gpio_input(CMD); + gpio_input(DAT3); + gpio_input(DAT2); + gpio_input(DAT1); + gpio_high(POWER_OFF); +} + + +static int nanonote_open(PROGRAMMER *pgm, char *port) +{ + bitbang_check_prerequisites(pgm); + + pgm->fd.ifd = open("/dev/mem", O_RDWR | O_SYNC); + if (pgm->fd.ifd < 0) { + perror("/dev/mem"); + return -1; + } + mem = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, + pgm->fd.ifd, BASE); + if (mem == MAP_FAILED) { + perror("mmap"); + return -1; + } + + gpio_output(POWER_OFF); + gpio_output(DAT0); + gpio_output(CLK); + gpio_output(CMD); + gpio_output(DAT3); + gpio_output(DAT2); + gpio_output(DAT1); + + nanonote_disable(pgm); + + return 0; +} + + +static void nanonote_close(PROGRAMMER *pgm) +{ + if (pgm->fd.ifd != -1) + close(pgm->fd.ifd); +} + + +void nanonote_initpgm(PROGRAMMER *pgm) +{ + strcpy(pgm->type, "NANONOTE"); + + pgm->rdy_led = bitbang_rdy_led; + pgm->err_led = bitbang_err_led; + pgm->pgm_led = bitbang_pgm_led; + pgm->vfy_led = bitbang_vfy_led; + pgm->initialize = bitbang_initialize; + pgm->display = nanonote_display; + pgm->enable = nanonote_enable; + pgm->disable = nanonote_disable; + pgm->powerup = nanonote_powerup; + pgm->powerdown = nanonote_powerdown; + pgm->program_enable = bitbang_program_enable; + pgm->chip_erase = bitbang_chip_erase; + pgm->cmd = bitbang_cmd; + pgm->open = nanonote_open; + pgm->close = nanonote_close; + pgm->setpin = nanonote_setpin; + pgm->getpin = nanonote_getpin; + pgm->highpulsepin = nanonote_highpulsepin; + pgm->read_byte = avr_read_byte_default; + pgm->write_byte = avr_write_byte_default; +} diff --git a/nanonote.h b/nanonote.h new file mode 100644 index 0000000..bfd9333 --- /dev/null +++ b/nanonote.h @@ -0,0 +1,6 @@ +#ifndef nanonote_h +#define nanonote_h + +void nanonote_initpgm(PROGRAMMER *pgm); + +#endif -- 1.7.0.4