Provide urclock programmer

This commit is contained in:
Stefan Rueger 2022-11-06 01:29:07 +00:00
parent 4c92030e3a
commit e6c26d8db4
No known key found for this signature in database
GPG Key ID: B0B4F1FD86B1EC55
14 changed files with 2286 additions and 11 deletions

View File

@ -225,6 +225,9 @@ add_library(libavrdude
updi_readwrite.h updi_readwrite.h
updi_state.c updi_state.c
updi_state.h updi_state.h
urclock.c
urclock.h
urclock_private.h
usbasp.c usbasp.c
usbasp.h usbasp.h
usbdevs.h usbdevs.h

View File

@ -180,6 +180,9 @@ libavrdude_a_SOURCES = \
updi_readwrite.h \ updi_readwrite.h \
updi_nvm.c \ updi_nvm.c \
updi_nvm.h \ updi_nvm.h \
urclock.c \
urclock.h \
urclock_private.h \
usbdevs.h \ usbdevs.h \
usb_hidapi.c \ usb_hidapi.c \
usb_libusb.c \ usb_libusb.c \

View File

@ -756,6 +756,19 @@ programmer
connection_type = serial; connection_type = serial;
; ;
#------------------------------------------------------------
# urclock
#------------------------------------------------------------
# See https://github.com/stefanrueger/urboot
programmer
id = "urclock";
desc = "Urclock programmer for urboot bootloaders (arduino compatible)";
type = "urclock";
prog_modes = PM_SPM;
connection_type = serial;
;
#------------------------------------------------------------ #------------------------------------------------------------
# xbee # xbee
#------------------------------------------------------------ #------------------------------------------------------------

View File

@ -6,10 +6,10 @@
* Atmel AVR8L, AVR8, XMEGA and AVR8X family description of interrupts and more * Atmel AVR8L, AVR8, XMEGA and AVR8X family description of interrupts and more
* *
* published under GNU General Public License, version 3 (GPL-3.0) * published under GNU General Public License, version 3 (GPL-3.0)
* meta-author: Stefan Rueger <stefan.rueger@urclocks.com> * meta-author Stefan Rueger <stefan.rueger@urclocks.com>
* *
* v 1.1 * v 1.1
* 30.08.2022 * 04.11.2022
* *
*/ */

View File

@ -9,7 +9,7 @@
* meta-author Stefan Rueger <stefan.rueger@urclocks.com> * meta-author Stefan Rueger <stefan.rueger@urclocks.com>
* *
* v 1.1 * v 1.1
* 30.08.2022 * 04.11.2022
* *
*/ */
@ -770,7 +770,7 @@ typedef struct { // Value of -1 typically means unknown
#define vts_avr128da64 64 #define vts_avr128da64 64
#define vts_avr128db64 65 #define vts_avr128db64 65
// Suggested vector bootloader interrupt number (first unused vector or, failing that, slot just above vector table) // Suggested vector bootloader interrupt: first unused vector or slot just above vector table
#define vbu_attiny4 10 #define vbu_attiny4 10
#define vbu_attiny5 11 #define vbu_attiny5 11
#define vbu_attiny9 10 #define vbu_attiny9 10

View File

@ -580,6 +580,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask);
The target file will be selected at configure time. */ The target file will be selected at configure time. */
extern long serial_recv_timeout; /* ms */ extern long serial_recv_timeout; /* ms */
extern long serial_drain_timeout; /* ms */
union filedescriptor union filedescriptor
{ {
@ -798,6 +799,7 @@ typedef struct programmer_t {
int (*parseextparams) (const struct programmer_t *pgm, const LISTID xparams); int (*parseextparams) (const struct programmer_t *pgm, const LISTID xparams);
void (*setup) (struct programmer_t *pgm); void (*setup) (struct programmer_t *pgm);
void (*teardown) (struct programmer_t *pgm); void (*teardown) (struct programmer_t *pgm);
int (*flash_readhook) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *flm, const char *fname, int size);
// Cached r/w API for terminal reads/writes // Cached r/w API for terminal reads/writes
int (*write_byte_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m, int (*write_byte_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
unsigned long addr, unsigned char value); unsigned long addr, unsigned char value);

View File

@ -154,6 +154,7 @@ PROGRAMMER *pgm_new(void) {
pgm->parseextparams = NULL; pgm->parseextparams = NULL;
pgm->setup = NULL; pgm->setup = NULL;
pgm->teardown = NULL; pgm->teardown = NULL;
pgm->flash_readhook = NULL;
// For allocating "global" memory by the programmer // For allocating "global" memory by the programmer
pgm->cookie = NULL; pgm->cookie = NULL;

View File

@ -51,6 +51,7 @@
#include "stk500generic.h" #include "stk500generic.h"
#include "stk500v2.h" #include "stk500v2.h"
#include "teensy.h" #include "teensy.h"
#include "urclock.h"
#include "usbasp.h" #include "usbasp.h"
#include "usbtiny.h" #include "usbtiny.h"
#include "wiring.h" #include "wiring.h"
@ -102,6 +103,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th
{"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP" {"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP"
{"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP" {"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP"
{"teensy", teensy_initpgm, teensy_desc}, // "teensy" {"teensy", teensy_initpgm, teensy_desc}, // "teensy"
{"urclock", urclock_initpgm, urclock_desc}, // "Urclock"
{"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp" {"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp"
{"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny" {"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny"
{"wiring", wiring_initpgm, wiring_desc}, // "Wiring" {"wiring", wiring_initpgm, wiring_desc}, // "Wiring"
@ -171,5 +173,3 @@ void walk_programmer_types(walk_programmer_types_cb cb, void *cookie)
cb(p->id, p->desc, cookie); cb(p->id, p->desc, cookie);
} }
} }

View File

@ -51,6 +51,7 @@
#include "libavrdude.h" #include "libavrdude.h"
long serial_recv_timeout = 5000; /* ms */ long serial_recv_timeout = 5000; /* ms */
long serial_drain_timeout = 250; /* ms */
struct baud_mapping { struct baud_mapping {
long baud; long baud;
@ -549,7 +550,7 @@ static int ser_drain(const union filedescriptor *fd, int display) {
unsigned char buf; unsigned char buf;
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 250000; timeout.tv_usec = serial_drain_timeout*1000L;
if (display) { if (display) {
msg_info("drain>"); msg_info("drain>");

View File

@ -37,6 +37,7 @@
#include "libavrdude.h" #include "libavrdude.h"
long serial_recv_timeout = 5000; /* ms */ long serial_recv_timeout = 5000; /* ms */
long serial_drain_timeout = 250; /* ms */
#define W32SERBUFSIZE 1024 #define W32SERBUFSIZE 1024
@ -635,7 +636,7 @@ static int net_drain(const union filedescriptor *fd, int display) {
} }
timeout.tv_sec = 0; timeout.tv_sec = 0;
timeout.tv_usec = 250000; timeout.tv_usec = serial_drain_timeout*1000L;
while (1) { while (1) {
FD_ZERO(&rfds); FD_ZERO(&rfds);
@ -712,7 +713,7 @@ static int ser_drain(const union filedescriptor *fd, int display) {
return -1; return -1;
} }
serial_w32SetTimeOut(hComPort,250); serial_w32SetTimeOut(hComPort, serial_drain_timeout);
if (display) { if (display) {
msg_info("drain>"); msg_info("drain>");

View File

@ -485,6 +485,17 @@ int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd, enum updateflags
pmsg_error("read from file %s failed\n", update_inname(upd->filename)); pmsg_error("read from file %s failed\n", update_inname(upd->filename));
return LIBAVRDUDE_GENERAL_FAILURE; return LIBAVRDUDE_GENERAL_FAILURE;
} }
// Patch input if for flash, eg, for vector bootloaders?
if(pgm->flash_readhook) {
AVRMEM *mem = avr_locate_mem(p, upd->memtype);
if(mem && !strcmp(mem->desc, "flash")) {
rc = pgm->flash_readhook(pgm, p, mem, upd->filename, rc);
if (rc < 0) {
pmsg_notice("readhook for file %s failed\n", update_inname(upd->filename));
return LIBAVRDUDE_GENERAL_FAILURE;
}
}
}
size = rc; size = rc;
pmsg_info("reading input file %s for %s%s\n", pmsg_info("reading input file %s for %s%s\n",

2067
src/urclock.c Normal file

File diff suppressed because it is too large Load Diff

29
src/urclock.h Normal file
View File

@ -0,0 +1,29 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2022, Stefan Rueger <stefan.rueger@urclocks.com>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/* $Id$ */
#ifndef urclock_h__
#define urclock_h__
extern const char urclock_desc[];
void urclock_initpgm (PROGRAMMER *pgm);
#endif

144
src/urclock_private.h Normal file
View File

@ -0,0 +1,144 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2022, Stefan Rueger <stefan.rueger@urclocks.com>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/* $Id$ */
#ifndef urclock_private_h__
#define urclock_private_h__
#include "avrintel.h"
// EEPROM or flash cache for bytewise access
typedef struct {
int base, size;
char *page, *copy;
} Cache;
// STK500v1 protocol constants
#define Resp_STK_OK 0x10
#define Resp_STK_INSYNC 0x14
#define Sync_CRC_EOP 0x20
#define Cmnd_STK_GET_SYNC 0x30
#define Cmnd_STK_ENTER_PROGMODE 0x50
#define Cmnd_STK_LEAVE_PROGMODE 0x51
#define Cmnd_STK_CHIP_ERASE 0x52
#define Cmnd_STK_LOAD_ADDRESS 0x55
#define Cmnd_STK_UNIVERSAL 0x56
#define Cmnd_STK_PROG_PAGE 0x64
#define Cmnd_STK_READ_PAGE 0x74
#define Cmnd_STK_READ_SIGN 0x75
#define Cmnd_UR_PROG_PAGE_EE 0x00
#define Cmnd_UR_READ_PAGE_EE 0x01
#define Cmnd_UR_PROG_PAGE_FL 0x02
#define Cmnd_UR_READ_PAGE_FL 0x03
// STK_UNIVERSAL commands for backward compatibility
#define Subc_STK_UNIVERSAL_LEXT 0x4d000000u // Load extended address
#define Subc_STK_UNIVERSAL_CE 0xac800000u // Chip erase
// Urboot protocol side channel info about MCU id and 5 binary bootloader features
// Number of differnt MCU ids
#define UB_N_MCU 2040 // MCU id 0..2039
// 5 bootloader features
#define UB_RESERVED_1 1
#define UB_RESERVED_2 2
#define UB_READ_FLASH 4 // Bootloader can read flash
#define UB_FLASH_LL_NOR 8 // Bootloader flash programming looks like a NOR memory
#define UB_CHIP_ERASE 16 // Bootloader has a flash-only chip erase that protects itself
#define UB_INFO(ub_features, ub_mcuid) (ub_features*UB_N_MCU + ub_mcuid)
#define UB_FEATURES(ub_info) ((uint16_t)(ub_info)/UB_N_MCU)
#define UB_MCUID(ub_info) ((uint16_t)(ub_info)%UB_N_MCU)
/*
* Urboot layout of top six bytes
*
* FLASHEND-5: numblpags, only from v7.5: 1 byte number 1..127 of bootloader flash pages
* FLASHEND-4: vblvecnum, only from v7.5: 1 byte vector number 1..127 for vector bootloader
* FLASHEND-3: 2 byte rjmp opcode to bootloader pgm_write_page(sram, flash) or ret opcode
* FLASHEND-1: capability byte of bootloader
* FLASHEND-0: version number of bootloader: 5 msb = major version, 3 lsb = minor version
*/
// Capability byte of bootloader from version 7.2 onwards
#define UR_PGMWRITEPAGE 128 // pgm_write_page() can be called from application at FLASHEND+1-4
#define UR_EEPROM 64 // EEPROM read/write support
#define UR_URPROTOCOL 32 // Bootloader uses urprotocol that requires avrdude -c urclock
#define UR_DUAL 16 // Dual boot
#define UR_VBLMASK 12 // Vector bootloader bits
#define UR_VBLPATCHVERIFY 12 // Patch reset/interrupt vectors and show original ones on verify
#define UR_VBLPATCH 8 // Patch reset/interrupt vectors only (expect an error on verify)
#define UR_VBL 4 // Merely start application via interrupt vector instead of reset
#define UR_NO_VBL 0 // Not a vector bootloader, must set fuses to HW bootloader support
#define UR_PROTECTME 2 // Bootloader safeguards against overwriting itself
#define UR_RESETFLAGS 1 // Load reset flags into register R2 before starting application
#define verbyte_cv(capver) ((uint8_t) ((uint16_t) (capver) >> 8))
#define hascapbyte_cv(capver) ({ uint8_t _vh = verbyte_cv(capver); _vh >= 072 && _vh != 0xff; })
#define hasextendedv_cv(capver) ({ uint8_t _vh = verbyte_cv(capver); _vh >= 075 && _vh != 0xff; })
#define capabilities_cv(capver) ({ uint16_t _vc = capver; \
(uint8_t) (hascapbyte_cv(_vc)? _vc&0xff: 0); })
#define vblvecnum_cv(capver) ({ uint16_t _vc = capver; \
(uint8_t) (hasextendedv_cv(_vc)? pgm_read_b1(FLASHEND-4): 0); })
#define numblpages_cv(capver) ({ uint16_t _vc = capver; \
(uint8_t) (hasextendedv_cv(_vc)? pgm_read_b1(FLASHEND-5): 0); })
#define blurversion_cv(capver) ({ uint8_t _vh = verbyte_cv(capver); \
(uint8_t) (_vh >= 072 && _vh != 0xff? _vh: 0); })
#define vercapis(capver, mask) ({ uint16_t _vi = capver; !!(capabilities_cv(_vi) & (mask)); })
#define ispgmwritepage_cv(capver) vercapis(capver, UR_PGMWRITEPAGE)
#define iseeprom_cv(capver) vercapis(capver, UR_EEPROM)
#define isurprotocol_cv(capver) vercapis(capver, UR_URPROTOCOL)
#define isdual_cv(capver) vercapis(capver, UR_DUAL)
#define isvectorbl_cv(capver) vercapis(capver, UR_VBLMASK)
#define isprotectme_cv(capver) vercapis(capver, UR_PROTECTME)
#define isresetflags_cv(capver) vercapis(capver, UR_RESETFLAGS)
// Capability bits incl position
#define pgmwritepage_bit_cap(cap) ((cap) & UR_PGMWRITEPAGE)
#define eeprom_bit_cap(cap) ((cap) & UR_EEPROM)
#define dual_bit_cap(cap) ((cap) & UR_DUAL)
#define vector_bits_cap(cap) ((cap) & UR_VBLMASK))
#define protectme_bit_cap(cap) ((cap) & UR_PROTECTME)
#define urprotocol_bit_cap(cap) ((cap) & UR_URPROTOCOL)
#define resetflags_bit_cap(cap) ((cap) & UR_RESETFLAGS)
// Boolean capabilities
#define ispgmwritepage_cap(cap) (!!((cap) & UR_PGMWRITEPAGE))
#define iseeprom_cap(cap) (!!((cap) & UR_EEPROM))
#define isdual_cap(cap) (!!((cap) & UR_DUAL))
#define isvectorbl_cap(cap) (!!((cap) & UR_VBLMASK)))
#define isprotectme_cap(cap) (!!((cap) & UR_PROTECTME))
#define isurprotocol_cap(cap) (!!((cap) & UR_URPROTOCOL))
#define isresetflags_cap(cap) (!!((cap) & UR_RESETFLAGS))
// Capability levels 0, 1, 2 or 3
#define vectorbl_level_cap(cap) (((cap) & UR_VBLMASK)/UR_VBL)
#endif