Add a driver for the Parallel Port based PowerOnReset In System Serial Programmer. --- prog/Makefile | 2 prog/drv/ppporissp.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 1 deletion(-) --- m8cutils-22.orig/prog/Makefile +++ m8cutils-22/prog/Makefile @@ -8,7 +8,7 @@ include ../Common.make -DRIVERS=waspic watsp watpp wadsp ecb_at91 dummy +DRIVERS=waspic watsp watpp wadsp ecb_at91 dummy ppporissp TESTS=rd errd ercmok ercmf wrrd wrcmok wrcmf wrlkcmok wrlkcmf wrlkrdf wrlkrdz \ secu secf secr secw secfsrw secfsur secfsfw \ secfspu secfspf secfspr secfspw secmir inrom inhex outrom outhex \ --- /dev/null +++ m8cutils-22/prog/drv/ppporissp.c @@ -0,0 +1,143 @@ +/* + * ppporissp.c - Parallel Port based PowerOnReset In System Serial Programmer + * + * Copyright (c) 2009 Michael Buesch + * Derived from wadsp.c Copyright 2006 Werner Almesberger + * Derived from watpp.c Copyright 2006 Werner Almesberger + */ + +#include +#include +#include +#include + +#include "prog.h" +#include "pp.h" + +/* + * Programmer connections: + * + * Logical + * 1 0 + * Data 0 (pin 2) SDATA to device SDATA !SDATA + * Data 1 (pin 3) SCLK to device SCLK !SCLK + * Data 2 (pin 4) Device power PWR !PWR + * Status 3 (pin 15) SDATA from device SDATA !SDATA + */ + +#define PWR_TARGET(on) ((on) ? (data |= (1 << 2)) : (data &= ~(1 << 2))) +#define SCLK(on) ((on) ? (data |= (1 << 1)) : (data &= ~(1 << 1))) +#define SDATA_OUT(on) ((on) ? (data |= (1 << 0)) : (data &= ~(1 << 0))) +#define SDATA_IN() (!!(pp_read_status() & (1 << 3))) +#define COMMIT() pp_write_data(data) + +static int fd; +static int inverted; +static uint8_t data; + + +void delay_hook(int rising); +void __attribute__((weak)) delay_hook(int rising) +{ +} + +static void ppporissp_send_bit(int bit) +{ + SDATA_OUT(bit); + SCLK(1); + COMMIT(); + delay_hook(1); + SCLK(0); + COMMIT(); + delay_hook(0); +} + +static void ppporissp_send_z(void) +{ + SDATA_OUT(0); + SCLK(!inverted); + COMMIT(); + delay_hook(1); + SCLK(inverted); + COMMIT(); + delay_hook(0); +} + +static int ppporissp_read_bit(void) +{ + return SDATA_IN(); +} + +static void ppporissp_invert_phase(void) +{ + inverted = !inverted; + if (inverted) { + SCLK(1); + COMMIT(); + } +} + +static struct prog_bit ppporissp_bit = { + .send_bit = ppporissp_send_bit, + .send_z = ppporissp_send_z, + .read_bit = ppporissp_read_bit, + .invert_phase = ppporissp_invert_phase, +}; + +static void ppporissp_initialize(int power_on) +{ + struct timeval t0; + + printf("Performing power-on-reset...\n"); + PWR_TARGET(1); + COMMIT(); + start_time(&t0); + /* This is much safer than usleep. */ + while (delta_time_us(&t0) < T_VDDWAIT); +} + +static int ppporissp_open(const char *dev, int voltage, int power_on, + const char *args[]) +{ + prog_init(NULL, NULL, NULL, &ppporissp_bit); + + if (!power_on) { + fprintf(stderr, "ppporissp does not support XRES\n"); + return -1; + } + if (voltage != 5) + printf("Warning: Not operating on 5V. Trying anyway...\n"); + + fd = pp_open(dev, 0); + + inverted = 0; + PWR_TARGET(0); + SCLK(0); + SDATA_OUT(0); + COMMIT(); + /* + * With the power off, we now wait for capacitors on the board to + * discharge. Using v(t) = v(0)*exp(-t/RC) and + * v(0) = 5V, R = 4.7kOhm, t = 100ms, we can discharge up to + * C = 10uF down to a diode drop of 0.6V. + */ + printf("Waiting for device to power down...\n"); + sleep(2); /* 2000 ms */ + + return voltage; +} + +static void ppporissp_close(void) +{ + SCLK(0); + PWR_TARGET(0); + COMMIT(); + pp_close(); +} + +struct prog_common ppporissp = { + .name = "ppporissp", + .open = ppporissp_open, + .close = ppporissp_close, + .initialize = ppporissp_initialize, +};