Provide urclock programmer
This commit is contained in:
parent
4c92030e3a
commit
e6c26d8db4
|
@ -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
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
|
@ -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
|
||||||
#------------------------------------------------------------
|
#------------------------------------------------------------
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -119,12 +119,12 @@ PROGRAMMER *pgm_new(void) {
|
||||||
pgm->err_led = pgm_default_led;
|
pgm->err_led = pgm_default_led;
|
||||||
pgm->pgm_led = pgm_default_led;
|
pgm->pgm_led = pgm_default_led;
|
||||||
pgm->vfy_led = pgm_default_led;
|
pgm->vfy_led = pgm_default_led;
|
||||||
pgm->read_byte_cached = avr_read_byte_cached;
|
pgm->read_byte_cached = avr_read_byte_cached;
|
||||||
pgm->write_byte_cached = avr_write_byte_cached;
|
pgm->write_byte_cached = avr_write_byte_cached;
|
||||||
pgm->chip_erase_cached = avr_chip_erase_cached;
|
pgm->chip_erase_cached = avr_chip_erase_cached;
|
||||||
pgm->page_erase_cached = avr_page_erase_cached;
|
pgm->page_erase_cached = avr_page_erase_cached;
|
||||||
pgm->flush_cache = avr_flush_cache;
|
pgm->flush_cache = avr_flush_cache;
|
||||||
pgm->reset_cache = avr_reset_cache;
|
pgm->reset_cache = avr_reset_cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* optional functions - these are checked to make sure they are
|
* optional functions - these are checked to make sure they are
|
||||||
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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>");
|
||||||
|
|
|
@ -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>");
|
||||||
|
|
11
src/update.c
11
src/update.c
|
@ -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",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue