REKLAMA

pic32prog-201612.zip

Pierwsze starcie z wytrawianiem i lutowaniem TQFP - płytka z PIC32MX795F512H

http://obrazki.elektroda.pl/9078633900_1482696778_thumb.jpg Witajcie moi drodzy Dzisiaj opiszę tu niezwykle prostą konstrukcję, której głównym celem było sprawdzenie jak wyjdzie mi termotransfer płytki pod TQFP w warunkach domowych, lutowanie TQFP najtańszą lutownicą grotową oraz uruchomienie PICa w obudowie TQFP (PIC32MX795F512H). Krótko o PIC32MX795F512H http://obrazki.elektroda.pl/1931628000_1482696876_thumb.jpg PIC32MX795F512H jest 32-bitowym mikrokontrolerem od Microchipa. Występuje jedynie w obudowach TQFP i TQFN. Jego cechy to: - 512KB pamięci flash - 128KB pamięci RAM - napięcie zasilania od 2.3 do 3.6V - USB (również w trybie hostu) - taktowanie 80MHz - 16 kanałów A/D - 6 UART - 3 SPI - 4 I2C - 5 PWM - 53 piny IO - i wiele więcej Projekt płytki Głównym założeniem była tutaj prostota, dlatego wyprowadziłem tylko małą część wszystkich pinów. Chciałem sprawdzić, czy w ogóle uda się wykonać płytkę pod TQFP oraz poprawnie zaprogramować układ w warunkach amatorskich. Na płytce umieściłem w zasadzie tylko to, co niezbędne, czyli: - PIC32MX w obudowie TQFP64 (oczywiście) - rezystor 10k na pinie RESET dla PICa - kondensatory odsprzęgające - kondensator VCAP dla PICa (10uF, musi być low-esr, ceramiczny bądź tantalowy, przekonałem się o tym osobiście jak dałem na jego miejsce elektrolita) - rezonator kwarcowy (sprawdzałem działanie z nim i bez niego) - zielona dioda LED sygnalizująca podłączenie zasilania Wzór ścieżek: http://obrazki.elektroda.pl/5645994100_1482677669_thumb.jpg Wykonanie płytki Wykonanie płytki postaram się opisać bardzo dokładnie, ze względu na to, że główny PIC jest tutaj w malutkiej obudowie TQFP. Tworzenie płytek i lutowanie TQFP zazwyczaj odstrasza początkujących, dlatego chcę tu pokazać, że to nie jest wcale takie trudne... Zacząłem od skrawka laminatu: http://obrazki.elektroda.pl/5252686500_1482670842_thumb.jpg Wydrukowałem mozaikę ścieżek drukarką laserową na odpowiednim papierze: http://obrazki.elektroda.pl/1251811200_1482670874_thumb.jpg Po wyczyszczeniu płytki dokonałem termotransferu ścieżek z pomocą żelazka: http://obrazki.elektroda.pl/6406883200_1482670934_thumb.jpg Następnie odmoczyłem papier, by dobrze schodził: http://obrazki.elektroda.pl/9320836700_1482670976_thumb.jpg Płytka po odmoczeniu: http://obrazki.elektroda.pl/2719953700_1482671017_thumb.jpg http://obrazki.elektroda.pl/4476047700_1482671020_thumb.jpg Następnie wyczyściłem dokładnie laminat z papieru z pomocą twardej szczotki: http://obrazki.elektroda.pl/7705370800_1482671100_thumb.jpg http://obrazki.elektroda.pl/5565870100_1482671103_thumb.jpg Po wyczyszczeniu przygotowałem ciepły roztwór wytrawiacza i umieściłem w nim płytkę: http://obrazki.elektroda.pl/2198560100_1482671217_thumb.jpg Tak wyglądała płytka po wytrawieniu miedzi: http://obrazki.elektroda.pl/5363884000_1482671274_thumb.jpg Toner zmyłem zmywaczem do paznokci i wyczyściłem jeszcze raz płytkę: http://obrazki.elektroda.pl/3165484900_1482671350_thumb.jpg Otwory wykonałem małą wierteraczkę od Vellmana (po wywierceniu jeszcze przetarłem płytkę papierem ściernym): http://obrazki.elektroda.pl/6294410200_1482671409_thumb.jpg Lutowanie płytki Lutowanie PICa w obudowie TQFP64 do płytki też przedstawię tutaj dokładnie, ponieważ z reguły sprawia to problemy początkującym. W całym procesie używałem takiej lutownicy: http://obrazki.elektroda.pl/4118768000_1482671673_thumb.jpg Pasty do lutowania: http://obrazki.elektroda.pl/2316044500_1482678023_thumb.jpg I spoiwa 0.25mm Sn60Pb40: http://obrazki.elektroda.pl/6862078500_1482678056_thumb.jpg Zacząłem od wyczyszczenia płytki i lutownicy. Jest to bardzo ważny krok, pominięcie go może skutkować tym, że lutowanie się nie powiedzie... Następnie nałożyłem topnik: http://obrazki.elektroda.pl/4283195000_1482671492_thumb.jpg Umieściłem dokładnie PICa na miejscu i docisnąłem: http://obrazki.elektroda.pl/3023582000_1482672980_thumb.jpg Zacząłem lutowanie. http://obrazki.elektroda.pl/1189347700_1482673095_thumb.jpg Najpierw przylutowałem piny przy rogach obudowy (trochę za dużo cyny się nałożyło, ale z czasem można nabrać wprawy): http://obrazki.elektroda.pl/2829586700_1482673254_thumb.jpg W tym miejscu należy pamiętać, by nie dotykać cyną bezpośrednio grotu lutownicy, lecz pinów układu. http://obrazki.elektroda.pl/3355175900_1482677730_thumb.jpg Gotowa płytka: http://obrazki.elektroda.pl/3263452300_1482692816_thumb.jpg Uruchomienie płytki i obserwacje Wersja bez rezonatora kwarcowego (wewnętrzny oscylator) zadziałała od razu. Natomiast w przypadku wersji z rezonatorem kwarcowym okazało się, że wstawiony przeze mnie (tymczasowo) na miejsce VUSB kondensator sobie nie radzi - musiałem go wymienić na taki, o jakim jest mowa w datasheecie: http://obrazki.elektroda.pl/9821344600_1482692415_thumb.jpg Po wymianie na odpowiedni wszystko zaczęło działać poprawnie. Programy dla tej płytki pisałem w mikroC PRO for PIC32 i wgrywałem poprzez mojego klona PICKIT2 (przystosowanego do poziomów logicznych 0-3.3V, napięcie 5V na PGD/PGC tutaj nie zda egzaminu i uszkodzi PICa) z pomocą pic32prog. Blink dla PIC32MX795F512H Kod "blink", czyli do mrugania diodą, dla wszystkich portów, napisany w środowidku mikroC PRO for PIC32. /* Simplest BLINK. It works without any external components (except 10k resistor on MCLR). No capacitors, no VCAP, no crystal. */ void main() { JTAGEN_bit = 0; // Disable JTAG AD1PCFG = 0xFFFF; // Configure AN pins as digital I/O /* ADC Digital Mode */ TRISB = 0; // Initialize PORTB as output TRISC = 0; // Initialize PORTC as output TRISD = 0; // Initialize PORTD as output TRISE = 0; // Initialize PORTE as output TRISF = 0; // Initialize PORTF as output LATB = 0; // Set PORTB to zero LATC = 0; // Set PORTC to zero LATD = 0; // Set PORTD to zero LATE = 0; // Set PORTE to zero LATF = 0; // Set PORTF to zero while(1) { LATB = ~PORTB; // Invert PORTB value LATC = ~PORTC; // Invert PORTC value LATD = ~PORTD; // Invert PORTD value LATE = ~PORTE; // Invert PORTE value LATF = ~PORTF; // Invert PORTF value Delay_ms(1000); } } UART dla PIC32MX795F512H Kod do testowania UART (z dodatkowym mruganiem), napisany w środowisku mikroC PRO for PIC32. /* Simplest BLINK + UART print. It works without any oscillator, with default configuration bits. The oscillator value in the settings is 8MHz. */ void main() { JTAGEN_bit = 0; // Disable JTAG AD1PCFG = 0xFFFF; // Configure AN pins as digital I/O /* ADC Digital Mode */ TRISB = 0; // Initialize PORTB as output TRISC = 0; // Initialize PORTC as output TRISD = 0; // Initialize PORTD as output TRISE = 0; // Initialize PORTE as output TRISF = 0; // Initialize PORTF as output LATB = 0; // Set PORTB to zero LATC = 0; // Set PORTC to zero LATD = 0; // Set PORTD to zero LATE = 0; // Set PORTE to zero LATF = 0; // Set PORTF to zero UART1_Init(9600); // Initialize the UART while(1) { LATB = ~PORTB; // Invert PORTB value LATC = ~PORTC; // Invert PORTC value LATD = ~PORTD; // Invert PORTD value LATE = ~PORTE; // Invert PORTE value LATF = ~PORTF; // Invert PORTF value Delay_ms(1000); UART1_Write_Text("UART1 test."); // Send message } } Dalsze plany Niedługo zamierzam odlutować z tej płytki PIC32MX795F512H i użyć go do jakiegoś wiekszego projektu, bo na tej płytce taki mikroprocesor tylko się marnuje. W planach mam eksperymenty z USB (również w trybie hostu), ale co z tego wyjdzie, to czas pokaże...


Pobierz plik - link do postu
  • pic32prog-201612.zip
    • family-mz.c
    • .gitmodules
    • pic32prog.exe
    • adapter.h
    • adapter-an1388-uart.c
    • serial.c
    • target.c
    • compile.bat
    • family-mx1.c
    • adapter-pickit2.c
    • target.h
    • README.txt
    • libusb-win32
      • README.txt
      • libusb-1.0
        • libusb.h
      • libusb-1.0.a
    • makefile
    • executive.c
    • pickit2.h
    • adapter-hidboot.c
    • macosx
      • README.txt
      • pic32prog
    • adapter-an1388.c
    • libintl.dll
    • pic32prog.c
    • family-mx3.c
    • adapter-uhb.c
    • adapter-bitbang.c
    • .le.ini
    • serial.h
    • clean.bat
    • linux64
      • README.txt
      • pic32prog
    • linux32
      • README.txt
      • pic32prog
    • adapter-stk500v2.c
    • pic32prog.conf
    • make-mingw
    • make-cygwin
    • bitbang
      • ICSP_v1C.ino
      • ICSP_v1E.inc
      • ICSP_v1E.ino
      • ascii ICSP using arduino nano v1_1.pdf
      • ICSP_v1C.inc
    • linuxarmhf
      • pic32prog
    • .gitignore
    • localize.h
    • pic32.h
    • adapter-mpsse.c
    • configure.c
    • Array
    • hex-to-c.py
    • COPYING.txt


pic32prog-201612.zip > libusb.h

/*
* Public libusb header file
* Copyright © 2001 Johannes Erdfelt & lt; johannes@erdfelt.com & gt;
* Copyright © 2007-2008 Daniel Drake & lt; dsd@gentoo.org & gt;
* Copyright © 2012 Pete Batard & lt; pete@akeo.ie & gt;
* Copyright © 2012 Nathan Hjelm & lt; hjelmn@cs.unm.edu & gt;
* For more information, please visit: http://libusb.info
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef LIBUSB_H
#define LIBUSB_H

#ifdef _MSC_VER
/* on MS environments, the inline keyword is available in C++ only */
#if !defined(__cplusplus)
#define inline __inline
#endif
/* ssize_t is also not available (copy/paste from MinGW) */
#ifndef _SSIZE_T_DEFINED
#define _SSIZE_T_DEFINED
#undef ssize_t
#ifdef _WIN64
typedef __int64 ssize_t;
#else
typedef int ssize_t;
#endif /* _WIN64 */
#endif /* _SSIZE_T_DEFINED */
#endif /* _MSC_VER */

/* stdint.h is not available on older MSVC */
#if defined(_MSC_VER) & & (_MSC_VER & lt; 1600) & & (!defined(_STDINT)) & & (!defined(_STDINT_H))
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#else
#include & lt; stdint.h & gt;
#endif

#if !defined(_WIN32_WCE)
#include & lt; sys/types.h & gt;
#endif

#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
#include & lt; sys/time.h & gt;
#endif

#include & lt; time.h & gt;
#include & lt; limits.h & gt;

/* 'interface' might be defined as a macro on Windows, so we need to
* undefine it so as not to break the current libusb API, because
* libusb_config_descriptor has an 'interface' member
* As this can be problematic if you include windows.h after libusb.h
* in your sources, we force windows.h to be included first. */
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
#include & lt; windows.h & gt;
#if defined(interface)
#undef interface
#endif
#if !defined(__CYGWIN__)
#include & lt; winsock.h & gt;
#endif
#endif

#if __GNUC__ & gt; 4 || (__GNUC__ == 4 & & __GNUC_MINOR__ & gt; = 5)
#define LIBUSB_DEPRECATED_FOR(f) \
__attribute__((deprecated( " Use " #f " instead " )))
#else
#define LIBUSB_DEPRECATED_FOR(f)
#endif /* __GNUC__ */

/** \def LIBUSB_CALL
* \ingroup misc
* libusb's Windows calling convention.
*
* Under Windows, the selection of available compilers and configurations
* means that, unlike other platforms, there is not & lt; em & gt; one true calling
* convention & lt; /em & gt; (calling convention: the manner in which parameters are
* passed to functions in the generated assembly code).
*
* Matching the Windows API itself, libusb uses the WINAPI convention (which
* translates to the & lt; tt & gt; stdcall & lt; /tt & gt; convention) and guarantees that the
* library is compiled in this way. The public header file also includes
* appropriate annotations so that your own software will use the right
* convention, even if another convention is being used by default within
* your codebase.
*
* The one consideration that you must apply in your software is to mark
* all functions which you use as libusb callbacks with this LIBUSB_CALL
* annotation, so that they too get compiled for the correct calling
* convention.
*
* On non-Windows operating systems, this macro is defined as nothing. This
* means that you can apply it to your code without worrying about
* cross-platform compatibility.
*/
/* LIBUSB_CALL must be defined on both definition and declaration of libusb
* functions. You'd think that declaration would be enough, but cygwin will
* complain about conflicting types unless both are marked this way.
* The placement of this macro is important too; it must appear after the
* return type, before the function name. See internal documentation for
* API_EXPORTED.
*/
#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE)
#define LIBUSB_CALL WINAPI
#else
#define LIBUSB_CALL
#endif

/** \def LIBUSB_API_VERSION
* \ingroup misc
* libusb's API version.
*
* Since version 1.0.13, to help with feature detection, libusb defines
* a LIBUSB_API_VERSION macro that gets increased every time there is a
* significant change to the API, such as the introduction of a new call,
* the definition of a new macro/enum member, or any other element that
* libusb applications may want to detect at compilation time.
*
* The macro is typically used in an application as follows:
* \code
* #if defined(LIBUSB_API_VERSION) & & (LIBUSB_API_VERSION & gt; = 0x01001234)
* // Use one of the newer features from the libusb API
* #endif
* \endcode
*
* Internally, LIBUSB_API_VERSION is defined as follows:
* (libusb major & lt; & lt; 24) | (libusb minor & lt; & lt; 16) | (16 bit incremental)
*/
#define LIBUSB_API_VERSION 0x01000104

/* The following is kept for compatibility, but will be deprecated in the future */
#define LIBUSBX_API_VERSION LIBUSB_API_VERSION

#ifdef __cplusplus
extern " C " {
#endif

/**
* \ingroup misc
* Convert a 16-bit value from host-endian to little-endian format. On
* little endian systems, this function does nothing. On big endian systems,
* the bytes are swapped.
* \param x the host-endian value to convert
* \returns the value in little-endian byte order
*/
static inline uint16_t libusb_cpu_to_le16(const uint16_t x)
{
union {
uint8_t b8[2];
uint16_t b16;
} _tmp;
_tmp.b8[1] = (uint8_t) (x & gt; & gt; 8);
_tmp.b8[0] = (uint8_t) (x & 0xff);
return _tmp.b16;
}

/** \def libusb_le16_to_cpu
* \ingroup misc
* Convert a 16-bit value from little-endian to host-endian format. On
* little endian systems, this function does nothing. On big endian systems,
* the bytes are swapped.
* \param x the little-endian value to convert
* \returns the value in host-endian byte order
*/
#define libusb_le16_to_cpu libusb_cpu_to_le16

/* standard USB stuff */

/** \ingroup desc
* Device and/or Interface Class codes */
enum libusb_class_code {
/** In the context of a \ref libusb_device_descriptor " device descriptor " ,
* this bDeviceClass value indicates that each interface specifies its
* own class information and all interfaces operate independently.
*/
LIBUSB_CLASS_PER_INTERFACE = 0,

/** Audio class */
LIBUSB_CLASS_AUDIO = 1,

/** Communications class */
LIBUSB_CLASS_COMM = 2,

/** Human Interface Device class */
LIBUSB_CLASS_HID = 3,

/** Physical */
LIBUSB_CLASS_PHYSICAL = 5,

/** Printer class */
LIBUSB_CLASS_PRINTER = 7,

/** Image class */
LIBUSB_CLASS_PTP = 6, /* legacy name from libusb-0.1 usb.h */
LIBUSB_CLASS_IMAGE = 6,

/** Mass storage class */
LIBUSB_CLASS_MASS_STORAGE = 8,

/** Hub class */
LIBUSB_CLASS_HUB = 9,

/** Data class */
LIBUSB_CLASS_DATA = 10,

/** Smart Card */
LIBUSB_CLASS_SMART_CARD = 0x0b,

/** Content Security */
LIBUSB_CLASS_CONTENT_SECURITY = 0x0d,

/** Video */
LIBUSB_CLASS_VIDEO = 0x0e,

/** Personal Healthcare */
LIBUSB_CLASS_PERSONAL_HEALTHCARE = 0x0f,

/** Diagnostic Device */
LIBUSB_CLASS_DIAGNOSTIC_DEVICE = 0xdc,

/** Wireless class */
LIBUSB_CLASS_WIRELESS = 0xe0,

/** Application class */
LIBUSB_CLASS_APPLICATION = 0xfe,

/** Class is vendor-specific */
LIBUSB_CLASS_VENDOR_SPEC = 0xff
};

/** \ingroup desc
* Descriptor types as defined by the USB specification. */
enum libusb_descriptor_type {
/** Device descriptor. See libusb_device_descriptor. */
LIBUSB_DT_DEVICE = 0x01,

/** Configuration descriptor. See libusb_config_descriptor. */
LIBUSB_DT_CONFIG = 0x02,

/** String descriptor */
LIBUSB_DT_STRING = 0x03,

/** Interface descriptor. See libusb_interface_descriptor. */
LIBUSB_DT_INTERFACE = 0x04,

/** Endpoint descriptor. See libusb_endpoint_descriptor. */
LIBUSB_DT_ENDPOINT = 0x05,

/** BOS descriptor */
LIBUSB_DT_BOS = 0x0f,

/** Device Capability descriptor */
LIBUSB_DT_DEVICE_CAPABILITY = 0x10,

/** HID descriptor */
LIBUSB_DT_HID = 0x21,

/** HID report descriptor */
LIBUSB_DT_REPORT = 0x22,

/** Physical descriptor */
LIBUSB_DT_PHYSICAL = 0x23,

/** Hub descriptor */
LIBUSB_DT_HUB = 0x29,

/** SuperSpeed Hub descriptor */
LIBUSB_DT_SUPERSPEED_HUB = 0x2a,

/** SuperSpeed Endpoint Companion descriptor */
LIBUSB_DT_SS_ENDPOINT_COMPANION = 0x30
};

/* Descriptor sizes per descriptor type */
#define LIBUSB_DT_DEVICE_SIZE 18
#define LIBUSB_DT_CONFIG_SIZE 9
#define LIBUSB_DT_INTERFACE_SIZE 9
#define LIBUSB_DT_ENDPOINT_SIZE 7
#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
#define LIBUSB_DT_HUB_NONVAR_SIZE 7
#define LIBUSB_DT_SS_ENDPOINT_COMPANION_SIZE 6
#define LIBUSB_DT_BOS_SIZE 5
#define LIBUSB_DT_DEVICE_CAPABILITY_SIZE 3

/* BOS descriptor sizes */
#define LIBUSB_BT_USB_2_0_EXTENSION_SIZE 7
#define LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE 10
#define LIBUSB_BT_CONTAINER_ID_SIZE 20

/* We unwrap the BOS = & gt; define its max size */
#define LIBUSB_DT_BOS_MAX_SIZE ((LIBUSB_DT_BOS_SIZE) +\
(LIBUSB_BT_USB_2_0_EXTENSION_SIZE) +\
(LIBUSB_BT_SS_USB_DEVICE_CAPABILITY_SIZE) +\
(LIBUSB_BT_CONTAINER_ID_SIZE))

#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */
#define LIBUSB_ENDPOINT_DIR_MASK 0x80

/** \ingroup desc
* Endpoint direction. Values for bit 7 of the
* \ref libusb_endpoint_descriptor::bEndpointAddress " endpoint address " scheme.
*/
enum libusb_endpoint_direction {
/** In: device-to-host */
LIBUSB_ENDPOINT_IN = 0x80,

/** Out: host-to-device */
LIBUSB_ENDPOINT_OUT = 0x00
};

#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */

/** \ingroup desc
* Endpoint transfer type. Values for bits 0:1 of the
* \ref libusb_endpoint_descriptor::bmAttributes " endpoint attributes " field.
*/
enum libusb_transfer_type {
/** Control endpoint */
LIBUSB_TRANSFER_TYPE_CONTROL = 0,

/** Isochronous endpoint */
LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1,

/** Bulk endpoint */
LIBUSB_TRANSFER_TYPE_BULK = 2,

/** Interrupt endpoint */
LIBUSB_TRANSFER_TYPE_INTERRUPT = 3,

/** Stream endpoint */
LIBUSB_TRANSFER_TYPE_BULK_STREAM = 4,
};

/** \ingroup misc
* Standard requests, as defined in table 9-5 of the USB 3.0 specifications */
enum libusb_standard_request {
/** Request status of the specific recipient */
LIBUSB_REQUEST_GET_STATUS = 0x00,

/** Clear or disable a specific feature */
LIBUSB_REQUEST_CLEAR_FEATURE = 0x01,

/* 0x02 is reserved */

/** Set or enable a specific feature */
LIBUSB_REQUEST_SET_FEATURE = 0x03,

/* 0x04 is reserved */

/** Set device address for all future accesses */
LIBUSB_REQUEST_SET_ADDRESS = 0x05,

/** Get the specified descriptor */
LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06,

/** Used to update existing descriptors or add new descriptors */
LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07,

/** Get the current device configuration value */
LIBUSB_REQUEST_GET_CONFIGURATION = 0x08,

/** Set device configuration */
LIBUSB_REQUEST_SET_CONFIGURATION = 0x09,

/** Return the selected alternate setting for the specified interface */
LIBUSB_REQUEST_GET_INTERFACE = 0x0A,

/** Select an alternate interface for the specified interface */
LIBUSB_REQUEST_SET_INTERFACE = 0x0B,

/** Set then report an endpoint's synchronization frame */
LIBUSB_REQUEST_SYNCH_FRAME = 0x0C,

/** Sets both the U1 and U2 Exit Latency */
LIBUSB_REQUEST_SET_SEL = 0x30,

/** Delay from the time a host transmits a packet to the time it is
* received by the device. */
LIBUSB_SET_ISOCH_DELAY = 0x31,
};

/** \ingroup misc
* Request type bits of the
* \ref libusb_control_setup::bmRequestType " bmRequestType " field in control
* transfers. */
enum libusb_request_type {
/** Standard */
LIBUSB_REQUEST_TYPE_STANDARD = (0x00 & lt; & lt; 5),

/** Class */
LIBUSB_REQUEST_TYPE_CLASS = (0x01 & lt; & lt; 5),

/** Vendor */
LIBUSB_REQUEST_TYPE_VENDOR = (0x02 & lt; & lt; 5),

/** Reserved */
LIBUSB_REQUEST_TYPE_RESERVED = (0x03 & lt; & lt; 5)
};

/** \ingroup misc
* Recipient bits of the
* \ref libusb_control_setup::bmRequestType " bmRequestType " field in control
* transfers. Values 4 through 31 are reserved. */
enum libusb_request_recipient {
/** Device */
LIBUSB_RECIPIENT_DEVICE = 0x00,

/** Interface */
LIBUSB_RECIPIENT_INTERFACE = 0x01,

/** Endpoint */
LIBUSB_RECIPIENT_ENDPOINT = 0x02,

/** Other */
LIBUSB_RECIPIENT_OTHER = 0x03,
};

#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C

/** \ingroup desc
* Synchronization type for isochronous endpoints. Values for bits 2:3 of the
* \ref libusb_endpoint_descriptor::bmAttributes " bmAttributes " field in
* libusb_endpoint_descriptor.
*/
enum libusb_iso_sync_type {
/** No synchronization */
LIBUSB_ISO_SYNC_TYPE_NONE = 0,

/** Asynchronous */
LIBUSB_ISO_SYNC_TYPE_ASYNC = 1,

/** Adaptive */
LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2,

/** Synchronous */
LIBUSB_ISO_SYNC_TYPE_SYNC = 3
};

#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30

/** \ingroup desc
* Usage type for isochronous endpoints. Values for bits 4:5 of the
* \ref libusb_endpoint_descriptor::bmAttributes " bmAttributes " field in
* libusb_endpoint_descriptor.
*/
enum libusb_iso_usage_type {
/** Data endpoint */
LIBUSB_ISO_USAGE_TYPE_DATA = 0,

/** Feedback endpoint */
LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1,

/** Implicit feedback Data endpoint */
LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2,
};

/** \ingroup desc
* A structure representing the standard USB device descriptor. This
* descriptor is documented in section 9.6.1 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_device_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this
* context. */
uint8_t bDescriptorType;

/** USB specification release number in binary-coded decimal. A value of
* 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */
uint16_t bcdUSB;

/** USB-IF class code for the device. See \ref libusb_class_code. */
uint8_t bDeviceClass;

/** USB-IF subclass code for the device, qualified by the bDeviceClass
* value */
uint8_t bDeviceSubClass;

/** USB-IF protocol code for the device, qualified by the bDeviceClass and
* bDeviceSubClass values */
uint8_t bDeviceProtocol;

/** Maximum packet size for endpoint 0 */
uint8_t bMaxPacketSize0;

/** USB-IF vendor ID */
uint16_t idVendor;

/** USB-IF product ID */
uint16_t idProduct;

/** Device release number in binary-coded decimal */
uint16_t bcdDevice;

/** Index of string descriptor describing manufacturer */
uint8_t iManufacturer;

/** Index of string descriptor describing product */
uint8_t iProduct;

/** Index of string descriptor containing device serial number */
uint8_t iSerialNumber;

/** Number of possible configurations */
uint8_t bNumConfigurations;
};

/** \ingroup desc
* A structure representing the standard USB endpoint descriptor. This
* descriptor is documented in section 9.6.6 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_endpoint_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in
* this context. */
uint8_t bDescriptorType;

/** The address of the endpoint described by this descriptor. Bits 0:3 are
* the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction,
* see \ref libusb_endpoint_direction.
*/
uint8_t bEndpointAddress;

/** Attributes which apply to the endpoint when it is configured using
* the bConfigurationValue. Bits 0:1 determine the transfer type and
* correspond to \ref libusb_transfer_type. Bits 2:3 are only used for
* isochronous endpoints and correspond to \ref libusb_iso_sync_type.
* Bits 4:5 are also only used for isochronous endpoints and correspond to
* \ref libusb_iso_usage_type. Bits 6:7 are reserved.
*/
uint8_t bmAttributes;

/** Maximum packet size this endpoint is capable of sending/receiving. */
uint16_t wMaxPacketSize;

/** Interval for polling endpoint for data transfers. */
uint8_t bInterval;

/** For audio devices only: the rate at which synchronization feedback
* is provided. */
uint8_t bRefresh;

/** For audio devices only: the address if the synch endpoint */
uint8_t bSynchAddress;

/** Extra descriptors. If libusb encounters unknown endpoint descriptors,
* it will store them here, should you wish to parse them. */
const unsigned char *extra;

/** Length of the extra descriptors, in bytes. */
int extra_length;
};

/** \ingroup desc
* A structure representing the standard USB interface descriptor. This
* descriptor is documented in section 9.6.5 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_interface_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE
* in this context. */
uint8_t bDescriptorType;

/** Number of this interface */
uint8_t bInterfaceNumber;

/** Value used to select this alternate setting for this interface */
uint8_t bAlternateSetting;

/** Number of endpoints used by this interface (excluding the control
* endpoint). */
uint8_t bNumEndpoints;

/** USB-IF class code for this interface. See \ref libusb_class_code. */
uint8_t bInterfaceClass;

/** USB-IF subclass code for this interface, qualified by the
* bInterfaceClass value */
uint8_t bInterfaceSubClass;

/** USB-IF protocol code for this interface, qualified by the
* bInterfaceClass and bInterfaceSubClass values */
uint8_t bInterfaceProtocol;

/** Index of string descriptor describing this interface */
uint8_t iInterface;

/** Array of endpoint descriptors. This length of this array is determined
* by the bNumEndpoints field. */
const struct libusb_endpoint_descriptor *endpoint;

/** Extra descriptors. If libusb encounters unknown interface descriptors,
* it will store them here, should you wish to parse them. */
const unsigned char *extra;

/** Length of the extra descriptors, in bytes. */
int extra_length;
};

/** \ingroup desc
* A collection of alternate settings for a particular USB interface.
*/
struct libusb_interface {
/** Array of interface descriptors. The length of this array is determined
* by the num_altsetting field. */
const struct libusb_interface_descriptor *altsetting;

/** The number of alternate settings that belong to this interface */
int num_altsetting;
};

/** \ingroup desc
* A structure representing the standard USB configuration descriptor. This
* descriptor is documented in section 9.6.3 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_config_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG
* in this context. */
uint8_t bDescriptorType;

/** Total length of data returned for this configuration */
uint16_t wTotalLength;

/** Number of interfaces supported by this configuration */
uint8_t bNumInterfaces;

/** Identifier value for this configuration */
uint8_t bConfigurationValue;

/** Index of string descriptor describing this configuration */
uint8_t iConfiguration;

/** Configuration characteristics */
uint8_t bmAttributes;

/** Maximum power consumption of the USB device from this bus in this
* configuration when the device is fully operation. Expressed in units
* of 2 mA when the device is operating in high-speed mode and in units
* of 8 mA when the device is operating in super-speed mode. */
uint8_t MaxPower;

/** Array of interfaces supported by this configuration. The length of
* this array is determined by the bNumInterfaces field. */
const struct libusb_interface *interface;

/** Extra descriptors. If libusb encounters unknown configuration
* descriptors, it will store them here, should you wish to parse them. */
const unsigned char *extra;

/** Length of the extra descriptors, in bytes. */
int extra_length;
};

/** \ingroup desc
* A structure representing the superspeed endpoint companion
* descriptor. This descriptor is documented in section 9.6.7 of
* the USB 3.0 specification. All multiple-byte fields are represented in
* host-endian format.
*/
struct libusb_ss_endpoint_companion_descriptor {

/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in
* this context. */
uint8_t bDescriptorType;


/** The maximum number of packets the endpoint can send or
* recieve as part of a burst. */
uint8_t bMaxBurst;

/** In bulk EP: bits 4:0 represents the maximum number of
* streams the EP supports. In isochronous EP: bits 1:0
* represents the Mult - a zero based value that determines
* the maximum number of packets within a service interval */
uint8_t bmAttributes;

/** The total number of bytes this EP will transfer every
* service interval. valid only for periodic EPs. */
uint16_t wBytesPerInterval;
};

/** \ingroup desc
* A generic representation of a BOS Device Capability descriptor. It is
* advised to check bDevCapabilityType and call the matching
* libusb_get_*_descriptor function to get a structure fully matching the type.
*/
struct libusb_bos_dev_capability_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;
/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
* LIBUSB_DT_DEVICE_CAPABILITY in this context. */
uint8_t bDescriptorType;
/** Device Capability type */
uint8_t bDevCapabilityType;
/** Device Capability data (bLength - 3 bytes) */
uint8_t dev_capability_data
#if defined(__STDC_VERSION__) & & (__STDC_VERSION__ & gt; = 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
};

/** \ingroup desc
* A structure representing the Binary Device Object Store (BOS) descriptor.
* This descriptor is documented in section 9.6.2 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_bos_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS
* in this context. */
uint8_t bDescriptorType;

/** Length of this descriptor and all of its sub descriptors */
uint16_t wTotalLength;

/** The number of separate device capability descriptors in
* the BOS */
uint8_t bNumDeviceCaps;

/** bNumDeviceCap Device Capability Descriptors */
struct libusb_bos_dev_capability_descriptor *dev_capability
#if defined(__STDC_VERSION__) & & (__STDC_VERSION__ & gt; = 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
};

/** \ingroup desc
* A structure representing the USB 2.0 Extension descriptor
* This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_usb_2_0_extension_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
* LIBUSB_DT_DEVICE_CAPABILITY in this context. */
uint8_t bDescriptorType;

/** Capability type. Will have value
* \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION
* LIBUSB_BT_USB_2_0_EXTENSION in this context. */
uint8_t bDevCapabilityType;

/** Bitmap encoding of supported device level features.
* A value of one in a bit location indicates a feature is
* supported; a value of zero indicates it is not supported.
* See \ref libusb_usb_2_0_extension_attributes. */
uint32_t bmAttributes;
};

/** \ingroup desc
* A structure representing the SuperSpeed USB Device Capability descriptor
* This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification.
* All multiple-byte fields are represented in host-endian format.
*/
struct libusb_ss_usb_device_capability_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
* LIBUSB_DT_DEVICE_CAPABILITY in this context. */
uint8_t bDescriptorType;

/** Capability type. Will have value
* \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY
* LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */
uint8_t bDevCapabilityType;

/** Bitmap encoding of supported device level features.
* A value of one in a bit location indicates a feature is
* supported; a value of zero indicates it is not supported.
* See \ref libusb_ss_usb_device_capability_attributes. */
uint8_t bmAttributes;

/** Bitmap encoding of the speed supported by this device when
* operating in SuperSpeed mode. See \ref libusb_supported_speed. */
uint16_t wSpeedSupported;

/** The lowest speed at which all the functionality supported
* by the device is available to the user. For example if the
* device supports all its functionality when connected at
* full speed and above then it sets this value to 1. */
uint8_t bFunctionalitySupport;

/** U1 Device Exit Latency. */
uint8_t bU1DevExitLat;

/** U2 Device Exit Latency. */
uint16_t bU2DevExitLat;
};

/** \ingroup desc
* A structure representing the Container ID descriptor.
* This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification.
* All multiple-byte fields, except UUIDs, are represented in host-endian format.
*/
struct libusb_container_id_descriptor {
/** Size of this descriptor (in bytes) */
uint8_t bLength;

/** Descriptor type. Will have value
* \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY
* LIBUSB_DT_DEVICE_CAPABILITY in this context. */
uint8_t bDescriptorType;

/** Capability type. Will have value
* \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID
* LIBUSB_BT_CONTAINER_ID in this context. */
uint8_t bDevCapabilityType;

/** Reserved field */
uint8_t bReserved;

/** 128 bit UUID */
uint8_t ContainerID[16];
};

/** \ingroup asyncio
* Setup packet for control transfers. */
struct libusb_control_setup {
/** Request type. Bits 0:4 determine recipient, see
* \ref libusb_request_recipient. Bits 5:6 determine type, see
* \ref libusb_request_type. Bit 7 determines data transfer direction, see
* \ref libusb_endpoint_direction.
*/
uint8_t bmRequestType;

/** Request. If the type bits of bmRequestType are equal to
* \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD
* " LIBUSB_REQUEST_TYPE_STANDARD " then this field refers to
* \ref libusb_standard_request. For other cases, use of this field is
* application-specific. */
uint8_t bRequest;

/** Value. Varies according to request */
uint16_t wValue;

/** Index. Varies according to request, typically used to pass an index
* or offset */
uint16_t wIndex;

/** Number of bytes to transfer */
uint16_t wLength;
};

#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup))

/* libusb */

struct libusb_context;
struct libusb_device;
struct libusb_device_handle;

/** \ingroup lib
* Structure providing the version of the libusb runtime
*/
struct libusb_version {
/** Library major version. */
const uint16_t major;

/** Library minor version. */
const uint16_t minor;

/** Library micro version. */
const uint16_t micro;

/** Library nano version. */
const uint16_t nano;

/** Library release candidate suffix string, e.g. " -rc4 " . */
const char *rc;

/** For ABI compatibility only. */
const char* describe;
};

/** \ingroup lib
* Structure representing a libusb session. The concept of individual libusb
* sessions allows for your program to use two libraries (or dynamically
* load two modules) which both independently use libusb. This will prevent
* interference between the individual libusb users - for example
* libusb_set_debug() will not affect the other user of the library, and
* libusb_exit() will not destroy resources that the other user is still
* using.
*
* Sessions are created by libusb_init() and destroyed through libusb_exit().
* If your application is guaranteed to only ever include a single libusb
* user (i.e. you), you do not have to worry about contexts: pass NULL in
* every function call where a context is required. The default context
* will be used.
*
* For more information, see \ref contexts.
*/
typedef struct libusb_context libusb_context;

/** \ingroup dev
* Structure representing a USB device detected on the system. This is an
* opaque type for which you are only ever provided with a pointer, usually
* originating from libusb_get_device_list().
*
* Certain operations can be performed on a device, but in order to do any
* I/O you will have to first obtain a device handle using libusb_open().
*
* Devices are reference counted with libusb_ref_device() and
* libusb_unref_device(), and are freed when the reference count reaches 0.
* New devices presented by libusb_get_device_list() have a reference count of
* 1, and libusb_free_device_list() can optionally decrease the reference count
* on all devices in the list. libusb_open() adds another reference which is
* later destroyed by libusb_close().
*/
typedef struct libusb_device libusb_device;


/** \ingroup dev
* Structure representing a handle on a USB device. This is an opaque type for
* which you are only ever provided with a pointer, usually originating from
* libusb_open().
*
* A device handle is used to perform I/O and other operations. When finished
* with a device handle, you should call libusb_close().
*/
typedef struct libusb_device_handle libusb_device_handle;

/** \ingroup dev
* Speed codes. Indicates the speed at which the device is operating.
*/
enum libusb_speed {
/** The OS doesn't report or know the device speed. */
LIBUSB_SPEED_UNKNOWN = 0,

/** The device is operating at low speed (1.5MBit/s). */
LIBUSB_SPEED_LOW = 1,

/** The device is operating at full speed (12MBit/s). */
LIBUSB_SPEED_FULL = 2,

/** The device is operating at high speed (480MBit/s). */
LIBUSB_SPEED_HIGH = 3,

/** The device is operating at super speed (5000MBit/s). */
LIBUSB_SPEED_SUPER = 4,
};

/** \ingroup dev
* Supported speeds (wSpeedSupported) bitfield. Indicates what
* speeds the device supports.
*/
enum libusb_supported_speed {
/** Low speed operation supported (1.5MBit/s). */
LIBUSB_LOW_SPEED_OPERATION = 1,

/** Full speed operation supported (12MBit/s). */
LIBUSB_FULL_SPEED_OPERATION = 2,

/** High speed operation supported (480MBit/s). */
LIBUSB_HIGH_SPEED_OPERATION = 4,

/** Superspeed operation supported (5000MBit/s). */
LIBUSB_SUPER_SPEED_OPERATION = 8,
};

/** \ingroup dev
* Masks for the bits of the
* \ref libusb_usb_2_0_extension_descriptor::bmAttributes " bmAttributes " field
* of the USB 2.0 Extension descriptor.
*/
enum libusb_usb_2_0_extension_attributes {
/** Supports Link Power Management (LPM) */
LIBUSB_BM_LPM_SUPPORT = 2,
};

/** \ingroup dev
* Masks for the bits of the
* \ref libusb_ss_usb_device_capability_descriptor::bmAttributes " bmAttributes " field
* field of the SuperSpeed USB Device Capability descriptor.
*/
enum libusb_ss_usb_device_capability_attributes {
/** Supports Latency Tolerance Messages (LTM) */
LIBUSB_BM_LTM_SUPPORT = 2,
};

/** \ingroup dev
* USB capability types
*/
enum libusb_bos_type {
/** Wireless USB device capability */
LIBUSB_BT_WIRELESS_USB_DEVICE_CAPABILITY = 1,

/** USB 2.0 extensions */
LIBUSB_BT_USB_2_0_EXTENSION = 2,

/** SuperSpeed USB device capability */
LIBUSB_BT_SS_USB_DEVICE_CAPABILITY = 3,

/** Container ID type */
LIBUSB_BT_CONTAINER_ID = 4,
};

/** \ingroup misc
* Error codes. Most libusb functions return 0 on success or one of these
* codes on failure.
* You can call libusb_error_name() to retrieve a string representation of an
* error code or libusb_strerror() to get an end-user suitable description of
* an error code.
*/
enum libusb_error {
/** Success (no error) */
LIBUSB_SUCCESS = 0,

/** Input/output error */
LIBUSB_ERROR_IO = -1,

/** Invalid parameter */
LIBUSB_ERROR_INVALID_PARAM = -2,

/** Access denied (insufficient permissions) */
LIBUSB_ERROR_ACCESS = -3,

/** No such device (it may have been disconnected) */
LIBUSB_ERROR_NO_DEVICE = -4,

/** Entity not found */
LIBUSB_ERROR_NOT_FOUND = -5,

/** Resource busy */
LIBUSB_ERROR_BUSY = -6,

/** Operation timed out */
LIBUSB_ERROR_TIMEOUT = -7,

/** Overflow */
LIBUSB_ERROR_OVERFLOW = -8,

/** Pipe error */
LIBUSB_ERROR_PIPE = -9,

/** System call interrupted (perhaps due to signal) */
LIBUSB_ERROR_INTERRUPTED = -10,

/** Insufficient memory */
LIBUSB_ERROR_NO_MEM = -11,

/** Operation not supported or unimplemented on this platform */
LIBUSB_ERROR_NOT_SUPPORTED = -12,

/* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the
message strings in strerror.c when adding new error codes here. */

/** Other error */
LIBUSB_ERROR_OTHER = -99,
};

/* Total number of error codes in enum libusb_error */
#define LIBUSB_ERROR_COUNT 14

/** \ingroup asyncio
* Transfer status codes */
enum libusb_transfer_status {
/** Transfer completed without error. Note that this does not indicate
* that the entire amount of requested data was transferred. */
LIBUSB_TRANSFER_COMPLETED,

/** Transfer failed */
LIBUSB_TRANSFER_ERROR,

/** Transfer timed out */
LIBUSB_TRANSFER_TIMED_OUT,

/** Transfer was cancelled */
LIBUSB_TRANSFER_CANCELLED,

/** For bulk/interrupt endpoints: halt condition detected (endpoint
* stalled). For control endpoints: control request not supported. */
LIBUSB_TRANSFER_STALL,

/** Device was disconnected */
LIBUSB_TRANSFER_NO_DEVICE,

/** Device sent more data than requested */
LIBUSB_TRANSFER_OVERFLOW,

/* NB! Remember to update libusb_error_name()
when adding new status codes here. */
};

/** \ingroup asyncio
* libusb_transfer.flags values */
enum libusb_transfer_flags {
/** Report short frames as errors */
LIBUSB_TRANSFER_SHORT_NOT_OK = 1 & lt; & lt; 0,

/** Automatically free() transfer buffer during libusb_free_transfer() */
LIBUSB_TRANSFER_FREE_BUFFER = 1 & lt; & lt; 1,

/** Automatically call libusb_free_transfer() after callback returns.
* If this flag is set, it is illegal to call libusb_free_transfer()
* from your transfer callback, as this will result in a double-free
* when this flag is acted upon. */
LIBUSB_TRANSFER_FREE_TRANSFER = 1 & lt; & lt; 2,

/** Terminate transfers that are a multiple of the endpoint's
* wMaxPacketSize with an extra zero length packet. This is useful
* when a device protocol mandates that each logical request is
* terminated by an incomplete packet (i.e. the logical requests are
* not separated by other means).
*
* This flag only affects host-to-device transfers to bulk and interrupt
* endpoints. In other situations, it is ignored.
*
* This flag only affects transfers with a length that is a multiple of
* the endpoint's wMaxPacketSize. On transfers of other lengths, this
* flag has no effect. Therefore, if you are working with a device that
* needs a ZLP whenever the end of the logical request falls on a packet
* boundary, then it is sensible to set this flag on & lt; em & gt; every & lt; /em & gt;
* transfer (you do not have to worry about only setting it on transfers
* that end on the boundary).
*
* This flag is currently only supported on Linux.
* On other systems, libusb_submit_transfer() will return
* LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this flag is set.
*
* Available since libusb-1.0.9.
*/
LIBUSB_TRANSFER_ADD_ZERO_PACKET = 1 & lt; & lt; 3,
};

/** \ingroup asyncio
* Isochronous packet descriptor. */
struct libusb_iso_packet_descriptor {
/** Length of data to request in this packet */
unsigned int length;

/** Amount of data that was actually transferred */
unsigned int actual_length;

/** Status code for this packet */
enum libusb_transfer_status status;
};

struct libusb_transfer;

/** \ingroup asyncio
* Asynchronous transfer callback function type. When submitting asynchronous
* transfers, you pass a pointer to a callback function of this type via the
* \ref libusb_transfer::callback " callback " member of the libusb_transfer
* structure. libusb will call this function later, when the transfer has
* completed or failed. See \ref asyncio for more information.
* \param transfer The libusb_transfer struct the callback function is being
* notified about.
*/
typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer);

/** \ingroup asyncio
* The generic USB transfer structure. The user populates this structure and
* then submits it in order to request a transfer. After the transfer has
* completed, the library populates the transfer with the results and passes
* it back to the user.
*/
struct libusb_transfer {
/** Handle of the device that this transfer will be submitted to */
libusb_device_handle *dev_handle;

/** A bitwise OR combination of \ref libusb_transfer_flags. */
uint8_t flags;

/** Address of the endpoint where this transfer will be sent. */
unsigned char endpoint;

/** Type of the endpoint from \ref libusb_transfer_type */
unsigned char type;

/** Timeout for this transfer in millseconds. A value of 0 indicates no
* timeout. */
unsigned int timeout;

/** The status of the transfer. Read-only, and only for use within
* transfer callback function.
*
* If this is an isochronous transfer, this field may read COMPLETED even
* if there were errors in the frames. Use the
* \ref libusb_iso_packet_descriptor::status " status " field in each packet
* to determine if errors occurred. */
enum libusb_transfer_status status;

/** Length of the data buffer */
int length;

/** Actual length of data that was transferred. Read-only, and only for
* use within transfer callback function. Not valid for isochronous
* endpoint transfers. */
int actual_length;

/** Callback function. This will be invoked when the transfer completes,
* fails, or is cancelled. */
libusb_transfer_cb_fn callback;

/** User context data to pass to the callback function. */
void *user_data;

/** Data buffer */
unsigned char *buffer;

/** Number of isochronous packets. Only used for I/O with isochronous
* endpoints. */
int num_iso_packets;

/** Isochronous packet descriptors, for isochronous transfers only. */
struct libusb_iso_packet_descriptor iso_packet_desc
#if defined(__STDC_VERSION__) & & (__STDC_VERSION__ & gt; = 199901L)
[] /* valid C99 code */
#else
[0] /* non-standard, but usually working code */
#endif
;
};

/** \ingroup misc
* Capabilities supported by an instance of libusb on the current running
* platform. Test if the loaded library supports a given capability by calling
* \ref libusb_has_capability().
*/
enum libusb_capability {
/** The libusb_has_capability() API is available. */
LIBUSB_CAP_HAS_CAPABILITY = 0x0000,
/** Hotplug support is available on this platform. */
LIBUSB_CAP_HAS_HOTPLUG = 0x0001,
/** The library can access HID devices without requiring user intervention.
* Note that before being able to actually access an HID device, you may
* still have to call additional libusb functions such as
* \ref libusb_detach_kernel_driver(). */
LIBUSB_CAP_HAS_HID_ACCESS = 0x0100,
/** The library supports detaching of the default USB driver, using
* \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */
LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101
};

/** \ingroup lib
* Log message levels.
* - LIBUSB_LOG_LEVEL_NONE (0) : no messages ever printed by the library (default)
* - LIBUSB_LOG_LEVEL_ERROR (1) : error messages are printed to stderr
* - LIBUSB_LOG_LEVEL_WARNING (2) : warning and error messages are printed to stderr
* - LIBUSB_LOG_LEVEL_INFO (3) : informational messages are printed to stdout, warning
* and error messages are printed to stderr
* - LIBUSB_LOG_LEVEL_DEBUG (4) : debug and informational messages are printed to stdout,
* warnings and errors to stderr
*/
enum libusb_log_level {
LIBUSB_LOG_LEVEL_NONE = 0,
LIBUSB_LOG_LEVEL_ERROR,
LIBUSB_LOG_LEVEL_WARNING,
LIBUSB_LOG_LEVEL_INFO,
LIBUSB_LOG_LEVEL_DEBUG,
};

int LIBUSB_CALL libusb_init(libusb_context **ctx);
void LIBUSB_CALL libusb_exit(libusb_context *ctx);
void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level);
const struct libusb_version * LIBUSB_CALL libusb_get_version(void);
int LIBUSB_CALL libusb_has_capability(uint32_t capability);
const char * LIBUSB_CALL libusb_error_name(int errcode);
int LIBUSB_CALL libusb_setlocale(const char *locale);
const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode);

ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,
libusb_device ***list);
void LIBUSB_CALL libusb_free_device_list(libusb_device **list,
int unref_devices);
libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev);
void LIBUSB_CALL libusb_unref_device(libusb_device *dev);

int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev,
int *config);
int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev,
struct libusb_device_descriptor *desc);
int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev,
struct libusb_config_descriptor **config);
int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev,
uint8_t config_index, struct libusb_config_descriptor **config);
int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev,
uint8_t bConfigurationValue, struct libusb_config_descriptor **config);
void LIBUSB_CALL libusb_free_config_descriptor(
struct libusb_config_descriptor *config);
int LIBUSB_CALL libusb_get_ss_endpoint_companion_descriptor(
struct libusb_context *ctx,
const struct libusb_endpoint_descriptor *endpoint,
struct libusb_ss_endpoint_companion_descriptor **ep_comp);
void LIBUSB_CALL libusb_free_ss_endpoint_companion_descriptor(
struct libusb_ss_endpoint_companion_descriptor *ep_comp);
int LIBUSB_CALL libusb_get_bos_descriptor(libusb_device_handle *handle,
struct libusb_bos_descriptor **bos);
void LIBUSB_CALL libusb_free_bos_descriptor(struct libusb_bos_descriptor *bos);
int LIBUSB_CALL libusb_get_usb_2_0_extension_descriptor(
struct libusb_context *ctx,
struct libusb_bos_dev_capability_descriptor *dev_cap,
struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension);
void LIBUSB_CALL libusb_free_usb_2_0_extension_descriptor(
struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension);
int LIBUSB_CALL libusb_get_ss_usb_device_capability_descriptor(
struct libusb_context *ctx,
struct libusb_bos_dev_capability_descriptor *dev_cap,
struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_cap);
void LIBUSB_CALL libusb_free_ss_usb_device_capability_descriptor(
struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_cap);
int LIBUSB_CALL libusb_get_container_id_descriptor(struct libusb_context *ctx,
struct libusb_bos_dev_capability_descriptor *dev_cap,
struct libusb_container_id_descriptor **container_id);
void LIBUSB_CALL libusb_free_container_id_descriptor(
struct libusb_container_id_descriptor *container_id);
uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev);
uint8_t LIBUSB_CALL libusb_get_port_number(libusb_device *dev);
int LIBUSB_CALL libusb_get_port_numbers(libusb_device *dev, uint8_t* port_numbers, int port_numbers_len);
LIBUSB_DEPRECATED_FOR(libusb_get_port_numbers)
int LIBUSB_CALL libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t* path, uint8_t path_length);
libusb_device * LIBUSB_CALL libusb_get_parent(libusb_device *dev);
uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev);
int LIBUSB_CALL libusb_get_device_speed(libusb_device *dev);
int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev,
unsigned char endpoint);
int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev,
unsigned char endpoint);

int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle);

int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev,
int configuration);
int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev,
int interface_number);
int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev,
int interface_number);

libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(
libusb_context *ctx, uint16_t vendor_id, uint16_t product_id);

int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev,
int interface_number, int alternate_setting);
int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev,
unsigned char endpoint);
int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev);

int LIBUSB_CALL libusb_alloc_streams(libusb_device_handle *dev,
uint32_t num_streams, unsigned char *endpoints, int num_endpoints);
int LIBUSB_CALL libusb_free_streams(libusb_device_handle *dev,
unsigned char *endpoints, int num_endpoints);

int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev,
int interface_number);
int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev,
int interface_number);
int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev,
int interface_number);
int LIBUSB_CALL libusb_set_auto_detach_kernel_driver(
libusb_device_handle *dev, int enable);

/* async I/O */

/** \ingroup asyncio
* Get the data section of a control transfer. This convenience function is here
* to remind you that the data does not start until 8 bytes into the actual
* buffer, as the setup packet comes first.
*
* Calling this function only makes sense from a transfer callback function,
* or situations where you have already allocated a suitably sized buffer at
* transfer- & gt; buffer.
*
* \param transfer a transfer
* \returns pointer to the first byte of the data section
*/
static inline unsigned char *libusb_control_transfer_get_data(
struct libusb_transfer *transfer)
{
return transfer- & gt; buffer + LIBUSB_CONTROL_SETUP_SIZE;
}

/** \ingroup asyncio
* Get the control setup packet of a control transfer. This convenience
* function is here to remind you that the control setup occupies the first
* 8 bytes of the transfer data buffer.
*
* Calling this function only makes sense from a transfer callback function,
* or situations where you have already allocated a suitably sized buffer at
* transfer- & gt; buffer.
*
* \param transfer a transfer
* \returns a casted pointer to the start of the transfer data buffer
*/
static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
struct libusb_transfer *transfer)
{
return (struct libusb_control_setup *)(void *) transfer- & gt; buffer;
}

/** \ingroup asyncio
* Helper function to populate the setup packet (first 8 bytes of the data
* buffer) for a control transfer. The wIndex, wValue and wLength values should
* be given in host-endian byte order.
*
* \param buffer buffer to output the setup packet into
* This pointer must be aligned to at least 2 bytes boundary.
* \param bmRequestType see the
* \ref libusb_control_setup::bmRequestType " bmRequestType " field of
* \ref libusb_control_setup
* \param bRequest see the
* \ref libusb_control_setup::bRequest " bRequest " field of
* \ref libusb_control_setup
* \param wValue see the
* \ref libusb_control_setup::wValue " wValue " field of
* \ref libusb_control_setup
* \param wIndex see the
* \ref libusb_control_setup::wIndex " wIndex " field of
* \ref libusb_control_setup
* \param wLength see the
* \ref libusb_control_setup::wLength " wLength " field of
* \ref libusb_control_setup
*/
static inline void libusb_fill_control_setup(unsigned char *buffer,
uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
uint16_t wLength)
{
struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
setup- & gt; bmRequestType = bmRequestType;
setup- & gt; bRequest = bRequest;
setup- & gt; wValue = libusb_cpu_to_le16(wValue);
setup- & gt; wIndex = libusb_cpu_to_le16(wIndex);
setup- & gt; wLength = libusb_cpu_to_le16(wLength);
}

struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets);
int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer);
int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer);
void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer);
void LIBUSB_CALL libusb_transfer_set_stream_id(
struct libusb_transfer *transfer, uint32_t stream_id);
uint32_t LIBUSB_CALL libusb_transfer_get_stream_id(
struct libusb_transfer *transfer);

/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for a control transfer.
*
* If you pass a transfer buffer to this function, the first 8 bytes will
* be interpreted as a control setup packet, and the wLength field will be
* used to automatically populate the \ref libusb_transfer::length " length "
* field of the transfer. Therefore the recommended approach is:
* -# Allocate a suitably sized data buffer (including space for control setup)
* -# Call libusb_fill_control_setup()
* -# If this is a host-to-device transfer with a data stage, put the data
* in place after the setup packet
* -# Call this function
* -# Call libusb_submit_transfer()
*
* It is also legal to pass a NULL buffer to this function, in which case this
* function will not attempt to populate the length field. Remember that you
* must then populate the buffer and length fields later.
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param buffer data buffer. If provided, this function will interpret the
* first 8 bytes as a setup packet and infer the transfer length from that.
* This pointer must be aligned to at least 2 bytes boundary.
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
*/
static inline void libusb_fill_control_transfer(
struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data,
unsigned int timeout)
{
struct libusb_control_setup *setup = (struct libusb_control_setup *)(void *) buffer;
transfer- & gt; dev_handle = dev_handle;
transfer- & gt; endpoint = 0;
transfer- & gt; type = LIBUSB_TRANSFER_TYPE_CONTROL;
transfer- & gt; timeout = timeout;
transfer- & gt; buffer = buffer;
if (setup)
transfer- & gt; length = (int) (LIBUSB_CONTROL_SETUP_SIZE
+ libusb_le16_to_cpu(setup- & gt; wLength));
transfer- & gt; user_data = user_data;
transfer- & gt; callback = callback;
}

/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for a bulk transfer.
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
*/
static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer,
libusb_device_handle *dev_handle, unsigned char endpoint,
unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
void *user_data, unsigned int timeout)
{
transfer- & gt; dev_handle = dev_handle;
transfer- & gt; endpoint = endpoint;
transfer- & gt; type = LIBUSB_TRANSFER_TYPE_BULK;
transfer- & gt; timeout = timeout;
transfer- & gt; buffer = buffer;
transfer- & gt; length = length;
transfer- & gt; user_data = user_data;
transfer- & gt; callback = callback;
}

/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for a bulk transfer using bulk streams.
*
* Since version 1.0.19, \ref LIBUSB_API_VERSION & gt; = 0x01000103
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param stream_id bulk stream id for this transfer
* \param buffer data buffer
* \param length length of data buffer
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
*/
static inline void libusb_fill_bulk_stream_transfer(
struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
unsigned char endpoint, uint32_t stream_id,
unsigned char *buffer, int length, libusb_transfer_cb_fn callback,
void *user_data, unsigned int timeout)
{
libusb_fill_bulk_transfer(transfer, dev_handle, endpoint, buffer,
length, callback, user_data, timeout);
transfer- & gt; type = LIBUSB_TRANSFER_TYPE_BULK_STREAM;
libusb_transfer_set_stream_id(transfer, stream_id);
}

/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for an interrupt transfer.
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
*/
static inline void libusb_fill_interrupt_transfer(
struct libusb_transfer *transfer, libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *buffer, int length,
libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
{
transfer- & gt; dev_handle = dev_handle;
transfer- & gt; endpoint = endpoint;
transfer- & gt; type = LIBUSB_TRANSFER_TYPE_INTERRUPT;
transfer- & gt; timeout = timeout;
transfer- & gt; buffer = buffer;
transfer- & gt; length = length;
transfer- & gt; user_data = user_data;
transfer- & gt; callback = callback;
}

/** \ingroup asyncio
* Helper function to populate the required \ref libusb_transfer fields
* for an isochronous transfer.
*
* \param transfer the transfer to populate
* \param dev_handle handle of the device that will handle the transfer
* \param endpoint address of the endpoint where this transfer will be sent
* \param buffer data buffer
* \param length length of data buffer
* \param num_iso_packets the number of isochronous packets
* \param callback callback function to be invoked on transfer completion
* \param user_data user data to pass to callback function
* \param timeout timeout for the transfer in milliseconds
*/
static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer,
libusb_device_handle *dev_handle, unsigned char endpoint,
unsigned char *buffer, int length, int num_iso_packets,
libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout)
{
transfer- & gt; dev_handle = dev_handle;
transfer- & gt; endpoint = endpoint;
transfer- & gt; type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
transfer- & gt; timeout = timeout;
transfer- & gt; buffer = buffer;
transfer- & gt; length = length;
transfer- & gt; num_iso_packets = num_iso_packets;
transfer- & gt; user_data = user_data;
transfer- & gt; callback = callback;
}

/** \ingroup asyncio
* Convenience function to set the length of all packets in an isochronous
* transfer, based on the num_iso_packets field in the transfer structure.
*
* \param transfer a transfer
* \param length the length to set in each isochronous packet descriptor
* \see libusb_get_max_packet_size()
*/
static inline void libusb_set_iso_packet_lengths(
struct libusb_transfer *transfer, unsigned int length)
{
int i;
for (i = 0; i & lt; transfer- & gt; num_iso_packets; i++)
transfer- & gt; iso_packet_desc[i].length = length;
}

/** \ingroup asyncio
* Convenience function to locate the position of an isochronous packet
* within the buffer of an isochronous transfer.
*
* This is a thorough function which loops through all preceding packets,
* accumulating their lengths to find the position of the specified packet.
* Typically you will assign equal lengths to each packet in the transfer,
* and hence the above method is sub-optimal. You may wish to use
* libusb_get_iso_packet_buffer_simple() instead.
*
* \param transfer a transfer
* \param packet the packet to return the address of
* \returns the base address of the packet buffer inside the transfer buffer,
* or NULL if the packet does not exist.
* \see libusb_get_iso_packet_buffer_simple()
*/
static inline unsigned char *libusb_get_iso_packet_buffer(
struct libusb_transfer *transfer, unsigned int packet)
{
int i;
size_t offset = 0;
int _packet;

/* oops..slight bug in the API. packet is an unsigned int, but we use
* signed integers almost everywhere else. range-check and convert to
* signed to avoid compiler warnings. FIXME for libusb-2. */
if (packet & gt; INT_MAX)
return NULL;
_packet = (int) packet;

if (_packet & gt; = transfer- & gt; num_iso_packets)
return NULL;

for (i = 0; i & lt; _packet; i++)
offset += transfer- & gt; iso_packet_desc[i].length;

return transfer- & gt; buffer + offset;
}

/** \ingroup asyncio
* Convenience function to locate the position of an isochronous packet
* within the buffer of an isochronous transfer, for transfers where each
* packet is of identical size.
*
* This function relies on the assumption that every packet within the transfer
* is of identical size to the first packet. Calculating the location of
* the packet buffer is then just a simple calculation:
* & lt; tt & gt; buffer + (packet_size * packet) & lt; /tt & gt;
*
* Do not use this function on transfers other than those that have identical
* packet lengths for each packet.
*
* \param transfer a transfer
* \param packet the packet to return the address of
* \returns the base address of the packet buffer inside the transfer buffer,
* or NULL if the packet does not exist.
* \see libusb_get_iso_packet_buffer()
*/
static inline unsigned char *libusb_get_iso_packet_buffer_simple(
struct libusb_transfer *transfer, unsigned int packet)
{
int _packet;

/* oops..slight bug in the API. packet is an unsigned int, but we use
* signed integers almost everywhere else. range-check and convert to
* signed to avoid compiler warnings. FIXME for libusb-2. */
if (packet & gt; INT_MAX)
return NULL;
_packet = (int) packet;

if (_packet & gt; = transfer- & gt; num_iso_packets)
return NULL;

return transfer- & gt; buffer + ((int) transfer- & gt; iso_packet_desc[0].length * _packet);
}

/* sync I/O */

int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,
uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
unsigned char *data, uint16_t wLength, unsigned int timeout);

int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
int *actual_length, unsigned int timeout);

int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,
unsigned char endpoint, unsigned char *data, int length,
int *actual_length, unsigned int timeout);

/** \ingroup desc
* Retrieve a descriptor from the default control pipe.
* This is a convenience function which formulates the appropriate control
* message to retrieve the descriptor.
*
* \param dev a device handle
* \param desc_type the descriptor type, see \ref libusb_descriptor_type
* \param desc_index the index of the descriptor to retrieve
* \param data output buffer for descriptor
* \param length size of data buffer
* \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
*/
static inline int libusb_get_descriptor(libusb_device_handle *dev,
uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length)
{
return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t) ((desc_type & lt; & lt; 8) | desc_index),
0, data, (uint16_t) length, 1000);
}

/** \ingroup desc
* Retrieve a descriptor from a device.
* This is a convenience function which formulates the appropriate control
* message to retrieve the descriptor. The string returned is Unicode, as
* detailed in the USB specifications.
*
* \param dev a device handle
* \param desc_index the index of the descriptor to retrieve
* \param langid the language ID for the string descriptor
* \param data output buffer for descriptor
* \param length size of data buffer
* \returns number of bytes returned in data, or LIBUSB_ERROR code on failure
* \see libusb_get_string_descriptor_ascii()
*/
static inline int libusb_get_string_descriptor(libusb_device_handle *dev,
uint8_t desc_index, uint16_t langid, unsigned char *data, int length)
{
return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN,
LIBUSB_REQUEST_GET_DESCRIPTOR, (uint16_t)((LIBUSB_DT_STRING & lt; & lt; 8) | desc_index),
langid, data, (uint16_t) length, 1000);
}

int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev,
uint8_t desc_index, unsigned char *data, int length);

/* polling and timeouts */

int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx);
void LIBUSB_CALL libusb_lock_events(libusb_context *ctx);
void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx);
int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx);
int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx);
void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx);
void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx);
int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv);

int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx,
struct timeval *tv);
int LIBUSB_CALL libusb_handle_events_timeout_completed(libusb_context *ctx,
struct timeval *tv, int *completed);
int LIBUSB_CALL libusb_handle_events(libusb_context *ctx);
int LIBUSB_CALL libusb_handle_events_completed(libusb_context *ctx, int *completed);
int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx,
struct timeval *tv);
int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx);
int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx,
struct timeval *tv);

/** \ingroup poll
* File descriptor for polling
*/
struct libusb_pollfd {
/** Numeric file descriptor */
int fd;

/** Event flags to poll for from & lt; poll.h & gt; . POLLIN indicates that you
* should monitor this file descriptor for becoming ready to read from,
* and POLLOUT indicates that you should monitor this file descriptor for
* nonblocking write readiness. */
short events;
};

/** \ingroup poll
* Callback function, invoked when a new file descriptor should be added
* to the set of file descriptors monitored for events.
* \param fd the new file descriptor
* \param events events to monitor for, see \ref libusb_pollfd for a
* description
* \param user_data User data pointer specified in
* libusb_set_pollfd_notifiers() call
* \see libusb_set_pollfd_notifiers()
*/
typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events,
void *user_data);

/** \ingroup poll
* Callback function, invoked when a file descriptor should be removed from
* the set of file descriptors being monitored for events. After returning
* from this callback, do not use that file descriptor again.
* \param fd the file descriptor to stop monitoring
* \param user_data User data pointer specified in
* libusb_set_pollfd_notifiers() call
* \see libusb_set_pollfd_notifiers()
*/
typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data);

const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(
libusb_context *ctx);
void LIBUSB_CALL libusb_free_pollfds(const struct libusb_pollfd **pollfds);
void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx,
libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb,
void *user_data);

/** \ingroup hotplug
* Callback handle.
*
* Callbacks handles are generated by libusb_hotplug_register_callback()
* and can be used to deregister callbacks. Callback handles are unique
* per libusb_context and it is safe to call libusb_hotplug_deregister_callback()
* on an already deregisted callback.
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* For more information, see \ref hotplug.
*/
typedef int libusb_hotplug_callback_handle;

/** \ingroup hotplug
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* Flags for hotplug events */
typedef enum {
/** Default value when not using any flags. */
LIBUSB_HOTPLUG_NO_FLAGS = 0,

/** Arm the callback and fire it for all matching currently attached devices. */
LIBUSB_HOTPLUG_ENUMERATE = 1 & lt; & lt; 0,
} libusb_hotplug_flag;

/** \ingroup hotplug
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* Hotplug events */
typedef enum {
/** A device has been plugged in and is ready to use */
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED = 0x01,

/** A device has left and is no longer available.
* It is the user's responsibility to call libusb_close on any handle associated with a disconnected device.
* It is safe to call libusb_get_device_descriptor on a device that has left */
LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT = 0x02,
} libusb_hotplug_event;

/** \ingroup hotplug
* Wildcard matching for hotplug events */
#define LIBUSB_HOTPLUG_MATCH_ANY -1

/** \ingroup hotplug
* Hotplug callback function type. When requesting hotplug event notifications,
* you pass a pointer to a callback function of this type.
*
* This callback may be called by an internal event thread and as such it is
* recommended the callback do minimal processing before returning.
*
* libusb will call this function later, when a matching event had happened on
* a matching device. See \ref hotplug for more information.
*
* It is safe to call either libusb_hotplug_register_callback() or
* libusb_hotplug_deregister_callback() from within a callback function.
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* \param ctx context of this notification
* \param device libusb_device this event occurred on
* \param event event that occurred
* \param user_data user data provided when this callback was registered
* \returns bool whether this callback is finished processing events.
* returning 1 will cause this callback to be deregistered
*/
typedef int (LIBUSB_CALL *libusb_hotplug_callback_fn)(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data);

/** \ingroup hotplug
* Register a hotplug callback function
*
* Register a callback with the libusb_context. The callback will fire
* when a matching event occurs on a matching device. The callback is
* armed until either it is deregistered with libusb_hotplug_deregister_callback()
* or the supplied callback returns 1 to indicate it is finished processing events.
*
* If the \ref LIBUSB_HOTPLUG_ENUMERATE is passed the callback will be
* called with a \ref LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED for all devices
* already plugged into the machine. Note that libusb modifies its internal
* device list from a separate thread, while calling hotplug callbacks from
* libusb_handle_events(), so it is possible for a device to already be present
* on, or removed from, its internal device list, while the hotplug callbacks
* still need to be dispatched. This means that when using \ref
* LIBUSB_HOTPLUG_ENUMERATE, your callback may be called twice for the arrival
* of the same device, once from libusb_hotplug_register_callback() and once
* from libusb_handle_events(); and/or your callback may be called for the
* removal of a device for which an arrived call was never made.
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* \param[in] ctx context to register this callback with
* \param[in] events bitwise or of events that will trigger this callback. See \ref
* libusb_hotplug_event
* \param[in] flags hotplug callback flags. See \ref libusb_hotplug_flag
* \param[in] vendor_id the vendor id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
* \param[in] product_id the product id to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
* \param[in] dev_class the device class to match or \ref LIBUSB_HOTPLUG_MATCH_ANY
* \param[in] cb_fn the function to be invoked on a matching event/device
* \param[in] user_data user data to pass to the callback function
* \param[out] handle pointer to store the handle of the allocated callback (can be NULL)
* \returns LIBUSB_SUCCESS on success LIBUSB_ERROR code on failure
*/
int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,
libusb_hotplug_event events,
libusb_hotplug_flag flags,
int vendor_id, int product_id,
int dev_class,
libusb_hotplug_callback_fn cb_fn,
void *user_data,
libusb_hotplug_callback_handle *handle);

/** \ingroup hotplug
* Deregisters a hotplug callback.
*
* Deregister a callback from a libusb_context. This function is safe to call from within
* a hotplug callback.
*
* Since version 1.0.16, \ref LIBUSB_API_VERSION & gt; = 0x01000102
*
* \param[in] ctx context this callback is registered with
* \param[in] handle the handle of the callback to deregister
*/
void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,
libusb_hotplug_callback_handle handle);

#ifdef __cplusplus
}
#endif

#endif


pic32prog-201612.zip > executive.c

//
// Copyright (c) 2005-2013, Microchip Technology Inc. All rights reserved.
//
// You may use, copy, modify and distribute the Software for use with Microchip
// products only. If you distribute the Software or its derivatives, the
// Software must have this entire copyright and disclaimer notice prominently
// posted in a location where end users will see it (e.g., installation program,
// program headers, About Box, etc.). To the maximum extent permitted by law,
// this Software is distributed 'AS IS' and WITHOUT ANY WARRANTY INCLUDING BUT
// NOT LIMITED TO ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR
// PARTICULAR PURPOSE, or NON-INFRINGEMENT. IN NO EVENT WILL MICROCHIP OR ITS
// LICENSORS BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL
// DAMAGES OF ANY KIND ARISING FROM OR RELATED TO THE USE, MODIFICATION OR
// DISTRIBUTION OF THIS SOFTWARE OR ITS DERIVATIVES.
//
#include " pic32.h "

const unsigned short pic32_pe_loader [PIC32_PE_LOADER_LEN] = {
0x3C07, 0xDEAD,
0x3C06, 0xFF20,
0x3C05, 0xFF20,
0x8CC4, 0x0000,
0x8CC3, 0x0000,
0x1067, 0x000B,
0x0000, 0x0000,
0x1060, 0xFFFB,
0x0000, 0x0000,
0x8CA2, 0x0000,
0x2463, 0xFFFF,
0xAC82, 0x0000,
0x2484, 0x0004,
0x1460, 0xFFFB,
0x0000, 0x0000,
0x1000, 0xFFF3,
0x0000, 0x0000,
0x3C02, 0xA000,
0x3442, 0x0900,
0x0040, 0x0008,
0x0000, 0x0000,
};

/*
* Programming executive for PIC32MX1/MX2 series.
* Created by hex-to-c.py script from RIPE_11_000301.hex.
*/
const unsigned pic32_pemx1[] =
{
/*0000*/ 0x3c1ca000, 0x279c7ff0, 0x3c1da000, 0x37bd08fc,
/*0010*/ 0x3c08a000, 0x25080be9, 0x01000008, 0x00000000,
/*0020*/ 0x6e0035aa, 0xb20b2513, 0x2203ea8e, 0xeb8eb30a,
/*0030*/ 0x9c402b04, 0xeaeeb709, 0x9c401002, 0x2202ea4f,
/*0040*/ 0x6a01e820, 0xeea346c1, 0x61ed4484, 0x6a00e820,
/*0050*/ 0x1fc00bfc, 0xbfc00bfc, 0x7fffffff, 0xb3042506,
/*0060*/ 0x45af9c40, 0x4484db40, 0xe8a02dfb, 0xff20000c,
/*0070*/ 0x6f00b20b, 0x6103ea83, 0xea8db20a, 0xb30a1002,
/*0080*/ 0x6782e469, 0x2506456f, 0x436fa440, 0xe75ded6f,
/*0090*/ 0x2dfa4481, 0xe8206a00, 0x6500dee0, 0x3fffffff,
/*00a0*/ 0xa0000000, 0xc0000000, 0x1c0064c3, 0x6500037b,
/*00b0*/ 0xe8a06443, 0xd40564f5, 0x2536d504, 0x50219004,
/*00c0*/ 0x68206101, 0xea026a00, 0xb41b6008, 0xb5196770,
/*00d0*/ 0x9dc0436f, 0x4484dcc0, 0x70202bfa, 0xb3166111,
/*00e0*/ 0x60035300, 0xed6cb515, 0xb4151002, 0x1c00e395,
/*00f0*/ 0x94050373, 0x97052a1a, 0x47614f7f, 0x1010d305,
/*0100*/ 0xe9026900, 0xb50c600d, 0xe6a93628, 0x1c009405,
/*0110*/ 0x9aa0037b, 0x93052a0a, 0x43844121, 0x17f1d405,
/*0120*/ 0xe21f9204, 0x2fcad704, 0x64756a00, 0x6500e8a0,
/*0130*/ 0xff200000, 0xa0000008, 0x1fffffff, 0x40000000,
/*0140*/ 0xb50d64c3, 0x67c5b70b, 0x9f406b1f, 0x5300436f,
/*0150*/ 0x46c4de40, 0x550060fa, 0x60036745, 0xed4cb507,
/*0160*/ 0xb3071002, 0x1c00e575, 0x65000373, 0xe8a06443,
/*0170*/ 0xff200000, 0xa0000008, 0x1fffffff, 0x40000000,
/*0180*/ 0x64f4f008, 0x69006704, 0x1c00250a, 0x6790036d,
/*0190*/ 0x93092206, 0xe9634121, 0x4800f400, 0x647461f6,
/*01a0*/ 0x6500e8a0, 0x1c0064c3, 0x6500036b, 0xe8a06443,
/*01b0*/ 0x64f5f00c, 0x6704677d, 0xc3906c00, 0xf7ffc391,
/*01c0*/ 0x18006c1f, 0x672503be, 0xea03b20a, 0xb40a6103,
/*01d0*/ 0x1002ec0d, 0xe0b1b509, 0x03d01800, 0x180067b1,
/*01e0*/ 0x650003d7, 0xde40960c, 0x64756a00, 0x6500e8a0,
/*01f0*/ 0x3fffffff, 0xa0000000, 0xc0000000, 0x6a0064f6,
/*0200*/ 0xd2046b01, 0x6704d305, 0xd2066725, 0xb432214b,
/*0210*/ 0xb5306b1f, 0x9dc0436f, 0xdcc05300, 0x60f94484,
/*0220*/ 0x2c059405, 0x039d1c00, 0xd2046500, 0x6f001002,
/*0230*/ 0x9204d705, 0x67702203, 0xd3064b80, 0x2e0b9606,
/*0240*/ 0x5300b325, 0xb5256003, 0x1002ed6c, 0xe395b424,
/*0250*/ 0x03831c00, 0x49e06790, 0x5120487f, 0x61d64001,
/*0260*/ 0x6b1fb420, 0x436fb51b, 0x53009de0, 0x4484dce0,
/*0270*/ 0x1c0060f9, 0x6500039d, 0x2203d204, 0x4a806750,
/*0280*/ 0x9306d206, 0xb3172b0b, 0x60035300, 0xed6cb513,
/*0290*/ 0xb6131002, 0x1c00e3d5, 0x67900383, 0x49e0487f,
/*02a0*/ 0x17b44001, 0x039d1c00, 0x2a026500, 0x240a9406,
/*02b0*/ 0x9206b30d, 0xdbe06f02, 0xdb402202, 0x48801006,
/*02c0*/ 0x1003db00, 0x9206b508, 0x6a00dd40, 0xe8a06476,
/*02d0*/ 0xff200000, 0xa0000008, 0x1fffffff, 0x40000000,
/*02e0*/ 0xa0000088, 0xff20000c, 0xb54b64e7, 0x9d80b649,
/*02f0*/ 0x6f03f7c1, 0x32723382, 0xdee06702, 0xb547e811,
/*0300*/ 0x33429d40, 0xea313362, 0xd3045b0d, 0x6050d205,
/*0310*/ 0x3768b243, 0x9e80e759, 0x9d80ec80, 0x9da0d406,
/*0320*/ 0x026a1800, 0x1040d507, 0x18009d80, 0xd4060290,
/*0330*/ 0x1800103b, 0x650002a9, 0x9d801037, 0x18009505,
/*0340*/ 0xd40602a0, 0xf3001031, 0x10336b01, 0x5b019d60,
/*0350*/ 0xd30667b8, 0x102d33a4, 0xd4069d80, 0x35ca9dc0,
/*0360*/ 0x02bf1800, 0x1020d505, 0xd4069d80, 0x35ea9de0,
/*0370*/ 0x026d1800, 0x1018d505, 0xd4069d80, 0x18009da0,
/*0380*/ 0xd5050248, 0x9d801011, 0xd406060a, 0x18009da0,
/*0390*/ 0xd50502ac, 0x6c001009, 0x9d80d40b, 0xd406060b,
/*03a0*/ 0x18009da0, 0xd505025c, 0x10036762, 0x10016b00,
/*03b0*/ 0x92046b03, 0x61057207, 0x32403240, 0xea6deb31,
/*03c0*/ 0x720a1005, 0x35406106, 0xea0d32a0, 0xdb40b315,
/*03d0*/ 0x72021796, 0x36406094, 0x34c0b512, 0x6f022302,
/*03e0*/ 0xdd80eced, 0x72019204, 0x2b056106, 0x18009406,
/*03f0*/ 0x95050257, 0x72081784, 0x2b026103, 0x1006920a,
/*0400*/ 0xf77f720c, 0xf77f611c, 0x920b2b1a, 0x1777dd40,
/*0410*/ 0xbf883030, 0xbf80f220, 0xff200000, 0xa0000f64,
/*0420*/ 0xff20000c, 0x34844000, 0x3c05bf81, 0xaca4f400,
/*0430*/ 0x40034800, 0x40074800, 0x00e33023, 0x2cc200f0,
/*0440*/ 0x1440fffc, 0x00000000, 0x3c08bf80, 0x3508f400,
/*0450*/ 0x3c09aa99, 0x35296655, 0x3c0a5566, 0x354a99aa,
/*0460*/ 0x3c0b0000, 0x356b8000, 0xad090010, 0xad0a0010,
/*0470*/ 0xad0b0008, 0x8ca8f400, 0x31038000, 0x1460fffd,
/*0480*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
/*0490*/ 0x00000000, 0x240b4000, 0x3c0abf81, 0xad4bf404,
/*04a0*/ 0x8ca9f400, 0x03e00008, 0x31222000, 0x08000349,
/*04b0*/ 0x2404000e, 0x00801821, 0x3c02bf81, 0x24040004,
/*04c0*/ 0xac43f420, 0x08000349, 0x00000000, 0x00801821,
/*04d0*/ 0x3c06bf81, 0x3c02bf81, 0x24040003, 0xacc3f420,
/*04e0*/ 0xac45f440, 0x08000349, 0x00000000, 0x00801821,
/*04f0*/ 0x3c06bf81, 0x3c02bf81, 0x24040001, 0xacc3f420,
/*0500*/ 0xac45f430, 0x08000349, 0x00000000, 0x3c06bf81,
/*0510*/ 0xacc4f420, 0x24034003, 0x3c04bf81, 0x3c02bf81,
/*0520*/ 0xac85f440, 0xac43f400, 0x40034800, 0x40084800,
/*0530*/ 0x01033823, 0x2ce500f0, 0x14a0fffc, 0x00000000,
/*0540*/ 0x3c08bf80, 0x3508f400, 0x3c09aa99, 0x35296655,
/*0550*/ 0x3c0a5566, 0x354a99aa, 0x3c0b0000, 0x356b8000,
/*0560*/ 0xad090010, 0xad0a0010, 0xad0b0008, 0x03e00008,
/*0570*/ 0x00001021, 0x3c04bf81, 0x8c83f400, 0x30628000,
/*0580*/ 0x1440fffd, 0x00000000, 0x00000000, 0x00000000,
/*0590*/ 0x00000000, 0x00000000, 0x24074000, 0x3c06bf81,
/*05a0*/ 0xacc7f404, 0x8c85f400, 0x03e00008, 0x30a22000,
/*05b0*/ 0xb01164a1, 0x32e06f00, 0x67626d00, 0x67c5eb31,
/*05c0*/ 0xea6e6745, 0x329e3442, 0x67a434a4, 0x46c13364,
/*05d0*/ 0x2204ed31, 0x7401f022, 0xed3167b8, 0xeb315608,
/*05e0*/ 0x47e161ef, 0x5700f100, 0x4004d8a0, 0x642161e4,
/*05f0*/ 0x6500e8a0, 0xa0000008, 0x671c64e3, 0xf0106b00,
/*0600*/ 0xf010d870, 0x1800c894, 0x650003ac, 0xf0106a01,
/*0610*/ 0x6463d850, 0x6500e8a0, 0xf01067bc, 0xec11ad74,
/*0620*/ 0xee3167c3, 0xec4e32c2, 0x3688b705, 0x9c40e6f1,
/*0630*/ 0xeb4e3360, 0xcd74f010, 0x6500e8a0, 0xa0000008,
/*0640*/ 0x672464f4, 0x2507450f, 0x1800a180, 0x400f03c6,
/*0650*/ 0x4121ea0f, 0x64742af9, 0x6500e8a0, 0xf010675c,
/*0660*/ 0xe8a0aa54,
/*0664*/ 0xa0000c29, 0xa0000c4d, 0xa0000c59, 0xa0000c1b,
/*0674*/ 0xa0000c33, 0xa0000c3b, 0xa0000c79, 0xa0000c47,
/*0684*/ 0xa0000c87, 0xa0000c69, 0xa0000cad, 0xa0000cb1,
/*0694*/ 0xa0000c97,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

/*
* Programming executive for PIC32MX3/4/5/6/7 series.
* Created by hex-to-c.py script from RIPE_06_000201.hex.
*/
const unsigned pic32_pemx3[] =
{
/*0000*/ 0x3c1ca000, 0x279c7ff0, 0x3c1da000, 0x37bd08fc,
/*0010*/ 0x3c08a000, 0x250810f0, 0x01000008, 0x00000000,
/*0020*/ 0x3c06bf88, 0x90c86160, 0x3c05bf88, 0x35070040,
/*0030*/ 0xa0c76160, 0x90a46140, 0x2402ffbf, 0x00821824,
/*0040*/ 0xa0a36140, 0x03e00008, 0x00000000, 0x3c06bf88,
/*0050*/ 0x90c86160, 0x2405ffbf, 0x01053824, 0xa0c76160,
/*0060*/ 0x3c03bf88, 0x90646140, 0x00851024, 0xa0626140,
/*0070*/ 0x03e00008, 0x00000000, 0x3c06bf88, 0x90c86161,
/*0080*/ 0x3c05bf88, 0x35070001, 0xa0c76161, 0x90a46141,
/*0090*/ 0x2402fffe, 0x00821824, 0xa0a36141, 0x03e00008,
/*00a0*/ 0x00000000, 0x3c06bf88, 0x90c86161, 0x2405fffe,
/*00b0*/ 0x01053824, 0xa0c76161, 0x3c03bf88, 0x90646141,
/*00c0*/ 0x00851024, 0xa0626141, 0x03e00008, 0x00000000,
/*00d0*/ 0x00052882, 0x10a0001b, 0x00003821, 0x3c061fc0,
/*00e0*/ 0x3c03bfc0, 0x3c027fff, 0x34c92ffc, 0x34682ffc,
/*00f0*/ 0x344bffff, 0x10000006, 0x240affff, 0x8c990000,
/*0100*/ 0x172b000e, 0x00000000, 0x10c0000e, 0x24840004,
/*0110*/ 0x0089c026, 0x00887826, 0x2f0d0001, 0x2dee0001,
/*0120*/ 0x24e70001, 0x01ae6025, 0x1580fff4, 0x00e5302b,
/*0130*/ 0x8c820000, 0x104afff4, 0x00000000, 0x03e00008,
/*0140*/ 0x24020001, 0x03e00008, 0x00001021, 0x3c04ff20,
/*0150*/ 0x8c830000, 0x2c620002, 0x10400003, 0x24040001,
/*0160*/ 0xaf838014, 0x00002021, 0x03e00008, 0x00801021,
/*0170*/ 0x10a00007, 0x3c02ff20, 0x3443000c, 0x8c860000,
/*0180*/ 0x24a5ffff, 0xac660000, 0x14a0fffc, 0x24840004,
/*0190*/ 0x03e00008, 0x00000000, 0x3c083fff, 0x3507ffff,
/*01a0*/ 0x00e4182b, 0x3c02a000, 0x00821025, 0x10600003,
/*01b0*/ 0x00003821, 0x3c09c000, 0x00891021, 0x00402021,
/*01c0*/ 0x10a00007, 0x24a3ffff, 0x2405ffff, 0x908a0000,
/*01d0*/ 0x2463ffff, 0x00ea3821, 0x1465fffc, 0x24840001,
/*01e0*/ 0x00001021, 0x03e00008, 0xacc70000, 0x08000540,
/*01f0*/ 0x00000000, 0x27bdffd0, 0xafb50024, 0xafb40020,
/*0200*/ 0xafb20018, 0xafbf002c, 0xafb60028, 0xafb3001c,
/*0210*/ 0xafb10014, 0xafb00010, 0x00a0a021, 0x00809021,
/*0220*/ 0x10a00024, 0x3c15ff20, 0x3c021fff, 0x3456ffff,
/*0230*/ 0x2a830081, 0x24130080, 0x0283980b, 0x0013282a,
/*0240*/ 0x10a00008, 0x3c06a000, 0x24c40210, 0x02601821,
/*0250*/ 0x8ea70000, 0x2463ffff, 0xac870000, 0x1460fffc,
/*0260*/ 0x24840004, 0x24040080, 0x5264001d, 0x3c05a000,
/*0270*/ 0x10a0000d, 0x00008821, 0x3c09a000, 0x25300210,
/*0280*/ 0x8e050000, 0x02402021, 0x0c000540, 0x26310001,
/*0290*/ 0x26100004, 0x0233182a, 0x14400007, 0x26520004,
/*02a0*/ 0x5460fff8, 0x8e050000, 0x0293a023, 0x1680ffe1,
/*02b0*/ 0x2a830081, 0x00001021, 0x8fbf002c, 0x8fb60028,
/*02c0*/ 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
/*02d0*/ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0030,
/*02e0*/ 0x24a30210, 0x04600003, 0x02c32824, 0x3c084000,
/*02f0*/ 0x00682821, 0x0c000538, 0x02402021, 0x1440ffee,
/*0300*/ 0x0293a023, 0x1680ffca, 0x26520200, 0x1000ffea,
/*0310*/ 0x00001021, 0x3c02a000, 0x24470210, 0x3c06ff20,
/*0320*/ 0x00e02821, 0x2403007f, 0x8cc80000, 0x2463ffff,
/*0330*/ 0xaca80000, 0x0461fffc, 0x24a50004, 0x3c064000,
/*0340*/ 0x00e01821, 0x04e10004, 0x00e62821, 0x3c051fff,
/*0350*/ 0x34a7ffff, 0x00672824, 0x08000538, 0x00000000,
/*0360*/ 0x27bdffe0, 0xafb20018, 0xafb10014, 0xafb00010,
/*0370*/ 0xafbf001c, 0x00a09021, 0x00808021, 0x14a00007,
/*0380*/ 0x00008821, 0x8fbf001c, 0x8fb20018, 0x8fb10014,
/*0390*/ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x02002021,
/*03a0*/ 0x0c000532, 0x26310001, 0x26101000, 0x1040fff5,
/*03b0*/ 0x0232182b, 0x1460fffa, 0x02002021, 0x8fbf001c,
/*03c0*/ 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
/*03d0*/ 0x27bd0020, 0x08000530, 0x00000000, 0x8f828014,
/*03e0*/ 0x27bdffb8, 0xafb7003c, 0xafb60038, 0xafb00020,
/*03f0*/ 0xafbf0040, 0xafb50034, 0xafb40030, 0xafb3002c,
/*0400*/ 0xafb20028, 0xafb10024, 0x00808021, 0x00a0b821,
/*0410*/ 0x00c0b021, 0xa3a00018, 0x10400041, 0xa3a00019,
/*0420*/ 0x00058a02, 0x3c050001, 0x240a0f00, 0x3c0bbf88,
/*0430*/ 0x3c09bf88, 0x340884cf, 0x3c06bf88, 0x34a41021,
/*0440*/ 0x3c03bf88, 0xad6a3034, 0xad2a3038, 0xacc83040,
/*0450*/ 0xac643050, 0x1a200016, 0x32e600ff, 0x3c073fff,
/*0460*/ 0x34f5ffff, 0x3c14a000, 0x3c13c000, 0x24120003,
/*0470*/ 0x02b0682b, 0x02146025, 0x02132821, 0x24070002,
/*0480*/ 0x018d280a, 0x02c02021, 0x24060100, 0x0c0005b8,
/*0490*/ 0xafb20010, 0x00403821, 0x2631ffff, 0x1440003b,
/*04a0*/ 0x26100100, 0x1e20fff3, 0x02b0682b, 0x32e600ff,
/*04b0*/ 0x10c0000e, 0x3c123fff, 0x3651ffff, 0x3c0fa000,
/*04c0*/ 0x0230702b, 0x11c00003, 0x020f2825, 0x3c13c000,
/*04d0*/ 0x02132821, 0x24070002, 0x02c02021, 0x24100003,
/*04e0*/ 0x0c0005b8, 0xafb00010, 0x00403821, 0x10e00033,
/*04f0*/ 0x24020001, 0x8fbf0040, 0x8fb7003c, 0x8fb60038,
/*0500*/ 0x8fb50034, 0x8fb40030, 0x8fb3002c, 0x8fb20028,
/*0510*/ 0x8fb10024, 0x8fb00020, 0x03e00008, 0x27bd0048,
/*0520*/ 0x0c00058a, 0x3404ffff, 0x3c1f3fff, 0x37f9ffff,
/*0530*/ 0x3c18a000, 0x0330a82b, 0x12a00003, 0x02182025,
/*0540*/ 0x3c02c000, 0x02022021, 0x0c0005a1, 0x02e02821,
/*0550*/ 0x0c0005b6, 0x00000000, 0xaec20000, 0x8fbf0040,
/*0560*/ 0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030,
/*0570*/ 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
/*0580*/ 0x00001021, 0x03e00008, 0x27bd0048, 0x8fbf0040,
/*0590*/ 0x8fb7003c, 0x8fb60038, 0x8fb50034, 0x8fb40030,
/*05a0*/ 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
/*05b0*/ 0x24020001, 0x03e00008, 0x27bd0048, 0x02c02021,
/*05c0*/ 0x27a50018, 0x24140003, 0x24060002, 0x24070002,
/*05d0*/ 0x0c0005b8, 0xafb40010, 0x8fbf0040, 0x8fb7003c,
/*05e0*/ 0x8fb60038, 0x8fb50034, 0x8fb40030, 0x8fb3002c,
/*05f0*/ 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x0002102b,
/*0600*/ 0x03e00008, 0x27bd0048, 0x27bdffc8, 0xafb7002c,
/*0610*/ 0xafb50024, 0xafb3001c, 0xafb20018, 0xafb10014,
/*0620*/ 0xafb00010, 0xafbf0034, 0xafbe0030, 0xafb60028,
/*0630*/ 0xafb40020, 0x00a08821, 0x00809021, 0x0000a821,
/*0640*/ 0x24170001, 0x3c10ff20, 0x10a00039, 0x00009821,
/*0650*/ 0x3c02a000, 0x3c031fff, 0x24560210, 0x347effff,
/*0660*/ 0x02c02021, 0x2403007f, 0x8e050000, 0x2463ffff,
/*0670*/ 0xac850000, 0x0461fffc, 0x24840004, 0x12e00046,
/*0680*/ 0x00000000, 0x0000b821, 0x2644fe00, 0x0095980b,
/*0690*/ 0x56600009, 0x2631ff80, 0x3c084000, 0x03d63024,
/*06a0*/ 0x01162821, 0x2ac70000, 0x00c7280b, 0x0c000548,
/*06b0*/ 0x02402021, 0x2631ff80, 0x2a290080, 0x1520001a,
/*06c0*/ 0x26520200, 0x3c0ba000, 0x256a1948, 0x8d540000,
/*06d0*/ 0x2403007f, 0x02802021, 0x8e0c0000, 0x2463ffff,
/*06e0*/ 0xac8c0000, 0x0461fffc, 0x24840004, 0x0c000562,
/*06f0*/ 0x00000000, 0x264dfe00, 0x01a2980b, 0x16600008,
/*0700*/ 0x0040a821, 0x3c184000, 0x2a8f0000, 0x03d47024,
/*0710*/ 0x03142821, 0x01cf280b, 0x0c000548, 0x02402021,
/*0720*/ 0x2631ff80, 0x26520200, 0x1620ffce, 0x02c02021,
/*0730*/ 0x0c000562, 0x0013a02b, 0x0002882b, 0x02348025,
/*0740*/ 0x12000019, 0x3c17ff20, 0x3c16ff20, 0x36c4000c,
/*0750*/ 0x24150002, 0xac950000, 0x52600022, 0x2653fe00,
/*0760*/ 0xac930000, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c,
/*0770*/ 0x8fb60028, 0x8fb50024, 0x8fb40020, 0x8fb3001c,
/*0780*/ 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00001021,
/*0790*/ 0x03e00008, 0x27bd0038, 0x0c000562, 0x00000000,
/*07a0*/ 0x1000ffb9, 0x0040a821, 0x36f2000c, 0xae400000,
/*07b0*/ 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028,
/*07c0*/ 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
/*07d0*/ 0x8fb10014, 0x8fb00010, 0x00001021, 0x03e00008,
/*07e0*/ 0x27bd0038, 0xac930000, 0x1000ffdf, 0x8fbf0034,
/*07f0*/ 0x27bdffc0, 0x3c02bf88, 0x24040fc3, 0xafbf0038,
/*0800*/ 0xafb10034, 0xafb00030, 0xac443030, 0x8c433030,
/*0810*/ 0x106400c5, 0x24050001, 0xaf808014, 0x3c09bf80,
/*0820*/ 0x3528f220, 0x8d070000, 0x3c06a000, 0x7cf13b00,
/*0830*/ 0x24d01908, 0x3c0dff20, 0x8dac0000, 0x240b0001,
/*0840*/ 0x000c3402, 0x3185ffff, 0x2cca0010, 0xaf8b8010,
/*0850*/ 0xafa60010, 0x11400006, 0xafa50014, 0x0006c080,
/*0860*/ 0x03107821, 0x8dee0000, 0x01c00008, 0x00000000,
/*0870*/ 0x24050003, 0x2402000f, 0x30a4ffff, 0x10c2002a,
/*0880*/ 0x3c03000f, 0x24040007, 0x10c40094, 0x2408000a,
/*0890*/ 0x10c8009a, 0x3c0c000a, 0x240d0002, 0x10cdffe5,
/*08a0*/ 0x0006cc00, 0x37230002, 0x3c1fff20, 0x0065c80b,
/*08b0*/ 0x37e6000c, 0xacd90000, 0x8fa30010, 0x2ca40001,
/*08c0*/ 0x38780001, 0x2f0f0001, 0x01e47024, 0x15c00091,
/*08d0*/ 0x38650008, 0x2ca70001, 0x00e41024, 0x10400005,
/*08e0*/ 0x386a000c, 0x8fa20028, 0xacc20000, 0x1000ffd2,
/*08f0*/ 0x3c0dff20, 0x2d490001, 0x01244024, 0x5100ffce,
/*0900*/ 0x3c0dff20, 0x8fa2002c, 0xacc20000, 0x1000ffca,
/*0910*/ 0x3c0dff20, 0x8f858014, 0x2402000f, 0x30a4ffff,
/*0920*/ 0x14c2ffd8, 0x3c03000f, 0x3c05ff20, 0x00833825,
/*0930*/ 0x34a6000c, 0xacc70000, 0x1000ffbf, 0x3c0dff20,
/*0940*/ 0xafa0002c, 0x3c03ff20, 0x8c640000, 0x27a6002c,
/*0950*/ 0xafa40018, 0x8c7f0000, 0x03e02821, 0xafbf0014,
/*0960*/ 0x0c0002a6, 0x00000000, 0x8fa60010, 0x1000ffc1,
/*0970*/ 0x00402821, 0x0c000293, 0x00000000, 0x8fa60010,
/*0980*/ 0x1000ffbc, 0x00402821, 0x1000ffba, 0x00002821,
/*0990*/ 0x3c0dff20, 0x8da40000, 0xafa40018, 0x8dac0000,
/*09a0*/ 0x000c5882, 0x01602821, 0x0c0002bd, 0xafab0014,
/*09b0*/ 0x8fa60010, 0x1000ffaf, 0x00402821, 0xafa00028,
/*09c0*/ 0x3c19ff20, 0x8f240000, 0x27a60028, 0xafa40018,
/*09d0*/ 0x8f380000, 0x03002821, 0x0c000337, 0xafb80014,
/*09e0*/ 0x8fa60010, 0x1000ffa3, 0x00402821, 0x1000ffa1,
/*09f0*/ 0x24050201, 0x3c0fff20, 0x8de40000, 0xafa40018,
/*0a00*/ 0x8dee0000, 0x01c02821, 0x0c000274, 0xafae0014,
/*0a10*/ 0x8fa60010, 0x1000ff97, 0x00402821, 0x3c02ff20,
/*0a20*/ 0x8c460000, 0x00c02021, 0x0c000318, 0xafa60018,
/*0a30*/ 0x8fa60010, 0x1000ff8f, 0x00402821, 0x0c000335,
/*0a40*/ 0x00000000, 0x8fa60010, 0x1000ff8a, 0x00402821,
/*0a50*/ 0x3c1fff20, 0x8fe40000, 0xafa40018, 0x8ff90000,
/*0a60*/ 0x03202821, 0x0c0002bb, 0xafb9001c, 0x8fa60010,
/*0a70*/ 0x1000ff80, 0x00402821, 0x3c0aff20, 0x8d440000,
/*0a80*/ 0xafa40018, 0x8d490000, 0x00094082, 0x01002821,
/*0a90*/ 0x0c0003c2, 0xafa80014, 0x8fa60010, 0x1000ff75,
/*0aa0*/ 0x00402821, 0x3c05ff20, 0x8ca70000, 0x24050002,
/*0ab0*/ 0x0007280b, 0x1000ff6f, 0xafa70018, 0x3c04ff20,
/*0ac0*/ 0x8c830000, 0x00602021, 0x0c000305, 0xafa30018,
/*0ad0*/ 0x8fa60010, 0x1000ff67, 0x00402821, 0x30a4ffff,
/*0ae0*/ 0x3c030007, 0x3c05ff20, 0x00833825, 0x34a6000c,
/*0af0*/ 0xacc70000, 0x1000ff50, 0x3c0dff20, 0x3c0bff20,
/*0b00*/ 0x022c5025, 0x3569000c, 0xad2a0000, 0x1000ff4a,
/*0b10*/ 0x3c0dff20, 0x8fa40018, 0x0c00029c, 0x8fa50014,
/*0b20*/ 0x1000ff45, 0x3c0dff20, 0x1000ff3c, 0xaf858014,
/*0b30*/ 0x03e00008, 0x00001021, 0x34844000, 0x3c05bf81,
/*0b40*/ 0xaca4f400, 0x40034800, 0x40074800, 0x00e33023,
/*0b50*/ 0x2cc200f0, 0x1440fffc, 0x00000000, 0x3c08bf80,
/*0b60*/ 0x3508f400, 0x3c09aa99, 0x35296655, 0x3c0a5566,
/*0b70*/ 0x354a99aa, 0x3c0b0000, 0x356b8000, 0xad090010,
/*0b80*/ 0xad0a0010, 0xad0b0008, 0x8ca8f400, 0x31038000,
/*0b90*/ 0x1460fffd, 0x00000000, 0x00000000, 0x00000000,
/*0ba0*/ 0x00000000, 0x00000000, 0x240b4000, 0x3c0abf81,
/*0bb0*/ 0xad4bf404, 0x8ca9f400, 0x03e00008, 0x31222000,
/*0bc0*/ 0x0800050e, 0x2404000e, 0x00801821, 0x3c02bf81,
/*0bd0*/ 0x24040004, 0xac43f420, 0x0800050e, 0x00000000,
/*0be0*/ 0x00803021, 0x3c02bf81, 0x3c03bf81, 0x24040003,
/*0bf0*/ 0xac46f420, 0xac65f440, 0x0800050e, 0x00000000,
/*0c00*/ 0x00803021, 0x3c02bf81, 0x3c03bf81, 0x24040001,
/*0c10*/ 0xac46f420, 0xac65f430, 0x0800050e, 0x00000000,
/*0c20*/ 0x3c06bf81, 0xacc4f420, 0x3c03bf81, 0x24044003,
/*0c30*/ 0x3c02bf81, 0xac65f440, 0xac44f400, 0x40034800,
/*0c40*/ 0x40084800, 0x01033823, 0x2ce500f0, 0x14a0fffc,
/*0c50*/ 0x00000000, 0x3c08bf80, 0x3508f400, 0x3c09aa99,
/*0c60*/ 0x35296655, 0x3c0a5566, 0x354a99aa, 0x3c0b0000,
/*0c70*/ 0x356b8000, 0xad090010, 0xad0a0010, 0xad0b0008,
/*0c80*/ 0x03e00008, 0x00001021, 0x3c04bf81, 0x8c83f400,
/*0c90*/ 0x30628000, 0x1440fffd, 0x00000000, 0x00000000,
/*0ca0*/ 0x00000000, 0x00000000, 0x00000000, 0x24074000,
/*0cb0*/ 0x3c06bf81, 0xacc7f404, 0x8c85f400, 0x03e00008,
/*0cc0*/ 0x30a22000, 0x3c02a000, 0x24490210, 0x00004021,
/*0cd0*/ 0x00082200, 0x3083ffff, 0x00002821, 0x24060007,
/*0ce0*/ 0x00056040, 0x00a35826, 0x39871021, 0x7c0b5620,
/*0cf0*/ 0x05400002, 0x30e5ffff, 0x3185ffff, 0x00036840,
/*0d00*/ 0x24c6ffff, 0x04c1fff6, 0x31a3ffff, 0x25080001,
/*0d10*/ 0x29030100, 0xad250000, 0x1460ffed, 0x25290004,
/*0d20*/ 0x03e00008, 0x00000000, 0x27bdffe8, 0xafbf0010,
/*0d30*/ 0xa784801c, 0x0c000571, 0xaf808018, 0x8fbf0010,
/*0d40*/ 0x24020001, 0x27bd0018, 0x03e00008, 0xaf828018,
/*0d50*/ 0x9786801c, 0x308b00ff, 0x7ccc3a00, 0x016c5026,
/*0d60*/ 0x3c09a000, 0x000a3880, 0x25280210, 0x00e82021,
/*0d70*/ 0x8c850000, 0x00061200, 0x00451826, 0x03e00008,
/*0d80*/ 0xa783801c, 0x27bdffe0, 0xafb10014, 0xafb00010,
/*0d90*/ 0xafbf001c, 0xafb20018, 0x00808821, 0x10a00008,
/*0da0*/ 0x24b0ffff, 0x2412ffff, 0x92240000, 0x2610ffff,
/*0db0*/ 0x0c000594, 0x26310001, 0x5612fffc, 0x92240000,
/*0dc0*/ 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
/*0dd0*/ 0x03e00008, 0x27bd0020, 0x03e00008, 0x9782801c,
/*0de0*/ 0x0007c040, 0x3c08a000, 0x03077821, 0x8d0a194c,
/*0df0*/ 0x000f7180, 0x01ca4021, 0x27bdffe8, 0x00e04821,
/*0e00*/ 0x3c0abf88, 0x24071000, 0x240d0080, 0x240c0040,
/*0e10*/ 0x3c0bbf88, 0x34038000, 0x3c02bf88, 0xad4d3034,
/*0e20*/ 0xafbf0010, 0xad0c0018, 0xad673004, 0xac433008,
/*0e30*/ 0x00803821, 0x91190000, 0x7f2401c0, 0x1480fffd,
/*0e40*/ 0x8fae0028, 0x3c02bf88, 0x352b00c0, 0x240d0038,
/*0e50*/ 0x240cffff, 0x24030003, 0x3c1f4000, 0xad0e0000,
/*0e60*/ 0xad0d0014, 0xad0c0024, 0xad433034, 0xac4b3038,
/*0e70*/ 0x04a10004, 0x00bf1021, 0x3c0f1fff, 0x35eaffff,
/*0e80*/ 0x00aa1024, 0x3c054000, 0xad020030, 0x04e10004,
/*0e90*/ 0x00e51021, 0x3c041fff, 0x3498ffff, 0x00f81024,
/*0ea0*/ 0xad020040, 0xad060090, 0x8d070090, 0x01202021,
/*0eb0*/ 0xad070060, 0x8d060060, 0x24050002, 0xad060050,
/*0ec0*/ 0x0c0005f5, 0x00003021, 0x8fbf0010, 0x03e00008,
/*0ed0*/ 0x27bd0018, 0x00045040, 0x3c08a000, 0x01444821,
/*0ee0*/ 0x8d04194c, 0x00093980, 0x00e44821, 0x24030080,
/*0ef0*/ 0x240200ff, 0xad220024, 0x00007821, 0xad230008,
/*0f00*/ 0x0006502b, 0xad230018, 0x10a00031, 0x00000000,
/*0f10*/ 0x240b0001, 0x10ab0013, 0x24030001, 0x8d2c0050,
/*0f20*/ 0x1580002d, 0x24070100, 0x8d2d0060, 0x11a00002,
/*0f30*/ 0x24030100, 0x8d230060, 0x8d2e0090, 0x11c00002,
/*0f40*/ 0x24040100, 0x8d240090, 0x00e3102b, 0x00e2180a,
/*0f50*/ 0x0064c821, 0x2738ffff, 0x0304001b, 0x008001f4,
/*0f60*/ 0x00001812, 0x2463ffff, 0x240e0001, 0x240d0004,
/*0f70*/ 0x240c0080, 0x240bffff, 0x8d240020, 0x30980003,
/*0f80*/ 0x7c880080, 0x17000017, 0x7c8700c0, 0x14e00010,
/*0f90*/ 0x00000000, 0x11000008, 0x00000000, 0x10ae000c,
/*0fa0*/ 0x00000000, 0x50600015, 0x240f0003, 0xad2d0024,
/*0fb0*/ 0x2463ffff, 0xad2c0018, 0x1140ffef, 0x00000000,
/*0fc0*/ 0x24c6ffff, 0x14cbffec, 0x00000000, 0x240f0005,
/*0fd0*/ 0x03e00008, 0x01e01021, 0x8d270050, 0x1000ffd2,
/*0fe0*/ 0x00000000, 0x7c850000, 0x10a0fff9, 0x240f0002,
/*0ff0*/ 0x240f0001, 0x03e00008, 0x01e01021, 0x03e00008,
/*1000*/ 0x01e01021,
/*1004*/ 0x0201cdab, 0xa00013bc, 0xa00013a4, 0xa0001378,
/*1014*/ 0xa0001350, 0xa000133c, 0xa000131c, 0xa00012f4,
/*1024*/ 0xa00012ec, 0xa00012bc, 0xa0001290, 0xa0001288,
/*1034*/ 0xa0001274, 0xa0001240, 0xa0001170, 0xa0001170,
/*1044*/ 0xa0001214,
/*1048*/ 0xa0000010,
/*104c*/ 0xbf883060,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};

/*
* Programming executive for PIC32MZ series.
* Created by hex-to-c.py script from RIPE_15_000502.hex.
*/
const unsigned pic32_pemz[] =
{
/*0000*/ 0x3c1ca000, 0x279c7ff0, 0x3c1da000, 0x37bd08fc,
/*0010*/ 0x3c08a000, 0x25080fd0, 0x01000008, 0x00000000,
/*0020*/ 0x27bdffe8, 0xafbf0014, 0x0c0004d8, 0x00000000,
/*0030*/ 0x8fbf0014, 0x03e00008, 0x27bd0018, 0x27bdffd8,
/*0040*/ 0xafbf0024, 0x3c02ff20, 0x8c430000, 0xafa30010,
/*0050*/ 0x8c430000, 0xafa30014, 0x8c430000, 0xafa30018,
/*0060*/ 0x8c420000, 0xafa2001c, 0x0c0004e3, 0x27a50010,
/*0070*/ 0x8fbf0024, 0x03e00008, 0x27bd0028, 0x27bdffe8,
/*0080*/ 0xafbf0014, 0x3c02a000, 0x24422000, 0x00402821,
/*0090*/ 0x24470800, 0x3c06ff20, 0x8cc30000, 0xac430000,
/*00a0*/ 0x24420004, 0x5447fffd, 0x8cc30000, 0x3c02a000,
/*00b0*/ 0x24422000, 0x04400005, 0x7ca5e000, 0x3c024000,
/*00c0*/ 0x3c05a000, 0x24a52000, 0x00a22821, 0x0c0004f8,
/*00d0*/ 0x00000000, 0x8fbf0014, 0x03e00008, 0x27bd0018,
/*00e0*/ 0x27bdffc8, 0xafbf0034, 0xafb70030, 0xafb6002c,
/*00f0*/ 0xafb50028, 0xafb40024, 0xafb30020, 0xafb2001c,
/*0100*/ 0xafb10018, 0xafb00014, 0x00a0a021, 0x10a00032,
/*0110*/ 0x00001021, 0x00808021, 0x3c15a000, 0x26b52000,
/*0120*/ 0x3c164000, 0x02b6b021, 0x7eb7e000, 0x2a930201,
/*0130*/ 0x24020200, 0x0293100b, 0x1840000a, 0x00409821,
/*0140*/ 0x02a01021, 0x00132880, 0x02a52821, 0x3c04ff20,
/*0150*/ 0x8c830000, 0xac430000, 0x24420004, 0x1445fffc,
/*0160*/ 0x00000000, 0x24020200, 0x52620005, 0x2aa50000,
/*0170*/ 0x5e60000c, 0x02a08821, 0x080002b3, 0x0293a023,
/*0180*/ 0x02e01021, 0x02c5100a, 0x00402821, 0x0c0004f8,
/*0190*/ 0x02002021, 0x14400010, 0x26100800, 0x080002b3,
/*01a0*/ 0x0293a023, 0x00009021, 0x02002021, 0x0c0004d8,
/*01b0*/ 0x8e250000, 0x14400008, 0x26520001, 0x26100004,
/*01c0*/ 0x1653fff9, 0x26310004, 0x0293a023, 0x1680ffd8,
/*01d0*/ 0x2a930201, 0x00001021, 0x8fbf0034, 0x8fb70030,
/*01e0*/ 0x8fb6002c, 0x8fb50028, 0x8fb40024, 0x8fb30020,
/*01f0*/ 0x8fb2001c, 0x8fb10018, 0x8fb00014, 0x03e00008,
/*0200*/ 0x27bd0038, 0x27bdffe0, 0xafbf001c, 0xafb20018,
/*0210*/ 0xafb10014, 0x10a0000a, 0xafb00010, 0x00a09021,
/*0220*/ 0x00808821, 0x00008021, 0x0c000503, 0x02202021,
/*0230*/ 0x10400003, 0x26100001, 0x1612fffb, 0x26314000,
/*0240*/ 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
/*0250*/ 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0014,
/*0260*/ 0x0c00050c, 0x00000000, 0x8fbf0014, 0x03e00008,
/*0270*/ 0x27bd0018, 0x00052882, 0x10a00010, 0x00001021,
/*0280*/ 0x8c860000, 0x2403ffff, 0x14c3000c, 0x24020001,
/*0290*/ 0x00001021, 0x080002ea, 0x2406ffff, 0x8c830000,
/*02a0*/ 0x54660006, 0x24020001, 0x24420001, 0x1445fffb,
/*02b0*/ 0x24840004, 0x03e00008, 0x00001021, 0x03e00008,
/*02c0*/ 0x00000000, 0x10a00007, 0x00001021, 0x3c06ff20,
/*02d0*/ 0x8c830000, 0xacc3000c, 0x24420001, 0x1445fffc,
/*02e0*/ 0x24840004, 0x03e00008, 0x00000000, 0x27bdffb8,
/*02f0*/ 0xafbf0044, 0xafb70040, 0xafb6003c, 0xafb50038,
/*0300*/ 0xafb40034, 0xafb30030, 0xafb2002c, 0xafb10028,
/*0310*/ 0xafb00024, 0x00808021, 0x00a0b821, 0xa3a00018,
/*0320*/ 0xa3a00019, 0x8f828010, 0x10400036, 0x00c09021,
/*0330*/ 0x3c040001, 0x24841021, 0x24050010, 0x0c000588,
/*0340*/ 0x340684cf, 0x00178a02, 0x1a200014, 0x32e600ff,
/*0350*/ 0x3c134000, 0x3c14c000, 0x3c15a000, 0x24160003,
/*0360*/ 0x0213282b, 0x02151025, 0x02141821, 0x0065100a,
/*0370*/ 0x00402821, 0xafb60010, 0x02402021, 0x24060100,
/*0380*/ 0x0c00061a, 0x24070002, 0x1440002f, 0x2631ffff,
/*0390*/ 0x1620fff3, 0x26100100, 0x32e600ff, 0x10c00011,
/*03a0*/ 0x24020003, 0x3c024000, 0x0202102b, 0x50400004,
/*03b0*/ 0x3c05c000, 0x3c05a000, 0x08000331, 0x02052825,
/*03c0*/ 0x02052821, 0x24020003, 0xafa20010, 0x02402021,
/*03d0*/ 0x0c00061a, 0x24070002, 0x1440001c, 0x24030001,
/*03e0*/ 0x24020003, 0xafa20010, 0x02402021, 0x27a50018,
/*03f0*/ 0x24060002, 0x0c00061a, 0x24070002, 0x08000353,
/*0400*/ 0x0002182b, 0x0c00057e, 0x3404ffff, 0x3c024000,
/*0410*/ 0x0202102b, 0x50400004, 0x3c04c000, 0x3c04a000,
/*0420*/ 0x0800034b, 0x02042025, 0x02042021, 0x0c000552,
/*0430*/ 0x02e02821, 0x0c000543, 0x00000000, 0xae420000,
/*0440*/ 0x08000353, 0x00001821, 0x24030001, 0x00601021,
/*0450*/ 0x8fbf0044, 0x8fb70040, 0x8fb6003c, 0x8fb50038,
/*0460*/ 0x8fb40034, 0x8fb30030, 0x8fb2002c, 0x8fb10028,
/*0470*/ 0x8fb00024, 0x03e00008, 0x27bd0048, 0x3c024000,
/*0480*/ 0x0082102b, 0x10400004, 0x3c02c000, 0x3c02a000,
/*0490*/ 0x08000367, 0x00822025, 0x00822021, 0x10a00007,
/*04a0*/ 0x00001821, 0x00801021, 0x00852821, 0x90470000,
/*04b0*/ 0x24420001, 0x1445fffd, 0x00671821, 0xacc30000,
/*04c0*/ 0x03e00008, 0x00001021, 0x27bdffc8, 0xafbf0034,
/*04d0*/ 0xafbe0030, 0xafb7002c, 0xafb60028, 0xafb50024,
/*04e0*/ 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014,
/*04f0*/ 0xafb00010, 0x00809021, 0x00a08021, 0x14a00039,
/*0500*/ 0x00008821, 0x080003c6, 0x00000000, 0x8c830000,
/*0510*/ 0xac430000, 0x24420004, 0x1445fffc, 0x00000000,
/*0520*/ 0x14c00005, 0x2642f800, 0x0c000533, 0x00000000,
/*0530*/ 0x0040a021, 0x2642f800, 0x0054880b, 0x56200008,
/*0540*/ 0x2610fe00, 0x7eb5e000, 0x2a650000, 0x03c5a80a,
/*0550*/ 0x02a02821, 0x0c000513, 0x02402021, 0x2610fe00,
/*0560*/ 0x2a020200, 0x1440001a, 0x26550800, 0x02c01021,
/*0570*/ 0x02c0b821, 0x26c50800, 0x3c04ff20, 0x8c830000,
/*0580*/ 0xac430000, 0x24420004, 0x1445fffc, 0x00000000,
/*0590*/ 0x0c000533, 0x00000000, 0x0242880b, 0x16200009,
/*05a0*/ 0x0040a021, 0x7ef7e000, 0x3c034000, 0x02c31021,
/*05b0*/ 0x2ac50000, 0x0045b80a, 0x02e02821, 0x0c000513,
/*05c0*/ 0x02a02021, 0x2610fe00, 0x080003b5, 0x26b20800,
/*05d0*/ 0x02a09021, 0x12000010, 0x00003021, 0x080003c2,
/*05e0*/ 0x02601021, 0x24060001, 0x0000a021, 0x3c13a000,
/*05f0*/ 0x26732000, 0x3c024000, 0x0262f021, 0x3c16a000,
/*0600*/ 0x26d62800, 0x02601021, 0x0260a821, 0x26650800,
/*0610*/ 0x08000383, 0x3c04ff20, 0x0c000533, 0x00000000,
/*0620*/ 0x14400005, 0x24030002, 0x1620001d, 0x3c02ff20,
/*0630*/ 0x080003da, 0x00000000, 0x3c02ff20, 0xac43000c,
/*0640*/ 0x12200005, 0x2652f800, 0x3c02ff20, 0xac51000c,
/*0650*/ 0x080003dc, 0x00001021, 0x3c02ff20, 0xac52000c,
/*0660*/ 0x080003dc, 0x00001021, 0xac40000c, 0x00001021,
/*0670*/ 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028,
/*0680*/ 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018,
/*0690*/ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0038,
/*06a0*/ 0xac43000c, 0x080003d3, 0x3c02ff20, 0x3c02ff20,
/*06b0*/ 0x8c430000, 0x2c640002, 0x10800003, 0x24020001,
/*06c0*/ 0xaf838010, 0x00001021, 0x03e00008, 0x00000000,
/*06d0*/ 0x27bdffd0, 0xafbf002c, 0xafb40028, 0xafb30024,
/*06e0*/ 0xafb20020, 0xafb1001c, 0xafb00018, 0x3c03bf81,
/*06f0*/ 0x24020fc3, 0xac621030, 0x8c631030, 0x54620003,
/*0700*/ 0xaf808010, 0x24020001, 0xaf828010, 0x3c02bf80,
/*0710*/ 0x8c540020, 0x3c13a000, 0x26731054, 0x7e943b00,
/*0720*/ 0x3c02000a, 0x0282a025, 0x3c02ff20, 0x8c510000,
/*0730*/ 0x00118402, 0x2e02000e, 0x1040006c, 0x3231ffff,
/*0740*/ 0x00101080, 0x02621021, 0x8c420000, 0x00400008,
/*0750*/ 0x00000000, 0xa00010c0, 0xa0001104, 0xa0001124,
/*0760*/ 0xa000108c, 0xa00010d8, 0xa00010e8, 0xa000116c,
/*0770*/ 0xa0001200, 0xa000118c, 0xa0001148, 0xa00012bc,
/*0780*/ 0xa00011dc, 0xa00011b4, 0xa00010a8, 0x3c02ff20,
/*0790*/ 0x8c520000, 0x8c450000, 0x0c000248, 0x02402021,
/*07a0*/ 0x08000488, 0x2403000a, 0x3c02ff20, 0x8c520000,
/*07b0*/ 0x0c00024f, 0x02402021, 0x08000488, 0x2403000a,
/*07c0*/ 0x3c02ff20, 0x8c520000, 0x0c00025f, 0x02402021,
/*07d0*/ 0x08000488, 0x2403000a, 0x0c0002d6, 0x00000000,
/*07e0*/ 0x08000488, 0x2403000a, 0x3c02ff20, 0x8c520000,
/*07f0*/ 0x02402021, 0x0c0002c1, 0x02202821, 0x08000488,
/*0800*/ 0x2403000a, 0x3c02ff20, 0x8c420000, 0x00409021,
/*0810*/ 0x0042900a, 0x24030002, 0x0002180b, 0x08000487,
/*0820*/ 0x00601021, 0x3c02ff20, 0x8c520000, 0x8c510000,
/*0830*/ 0x00118882, 0x02402021, 0x0c000372, 0x02202821,
/*0840*/ 0x08000488, 0x2403000a, 0x3c02ff20, 0x8c520000,
/*0850*/ 0x8c510000, 0x00118882, 0x02402021, 0x0c000278,
/*0860*/ 0x02202821, 0x08000488, 0x2403000a, 0x3c02ff20,
/*0870*/ 0x8c520000, 0x8c510000, 0x02402021, 0x0c0002dd,
/*0880*/ 0x02202821, 0x08000488, 0x2403000a, 0xafa00010,
/*0890*/ 0x3c02ff20, 0x8c520000, 0x8c510000, 0x02402021,
/*08a0*/ 0x02202821, 0x0c0002fb, 0x27a60010, 0x08000488,
/*08b0*/ 0x2403000a, 0xafa00014, 0x3c02ff20, 0x8c520000,
/*08c0*/ 0x8c510000, 0x02402021, 0x02202821, 0x0c00035f,
/*08d0*/ 0x27a60014, 0x08000488, 0x2403000a, 0x0c0003eb,
/*08e0*/ 0x00000000, 0x08000488, 0x2403000a, 0x24020007,
/*08f0*/ 0x12020004, 0x24030003, 0x08000487, 0x24020003,
/*0900*/ 0x24030502, 0x3c020007, 0x00621825, 0x3c02ff20,
/*0910*/ 0xac43000c, 0x0800040b, 0x3c02ff20, 0x2403000a,
/*0920*/ 0x16030005, 0x24030002, 0x3c02ff20, 0xac54000c,
/*0930*/ 0x0800040b, 0x3c02ff20, 0x1203ff7b, 0x00101c00,
/*0940*/ 0x24040002, 0x0002200a, 0x00832025, 0x3c03ff20,
/*0950*/ 0xac64000c, 0x24030001, 0x16030008, 0x24030008,
/*0960*/ 0x5440ff72, 0x3c02ff20, 0x02402021, 0x0c0002f1,
/*0970*/ 0x02202821, 0x0800040b, 0x3c02ff20, 0x16030007,
/*0980*/ 0x2403000c, 0x1440ff69, 0x3c02ff20, 0x8fa30010,
/*0990*/ 0xac43000c, 0x0800040b, 0x3c02ff20, 0x5603ff63,
/*09a0*/ 0x3c02ff20, 0x1440ff61, 0x3c02ff20, 0x8fa30014,
/*09b0*/ 0xac43000c, 0x0800040b, 0x3c02ff20, 0x08000487,
/*09c0*/ 0x00001021, 0x3c02bf80, 0xac440600, 0x34844000,
/*09d0*/ 0xac440600, 0x3c08bf80, 0x35080600, 0x3c09aa99,
/*09e0*/ 0x35296655, 0x3c0a5566, 0x354a99aa, 0x3c0b0000,
/*09f0*/ 0x356b8000, 0x3c0c0000, 0x358c8080, 0xad090010,
/*0a00*/ 0xad0a0010, 0xad0c0090, 0x00000000, 0xad090010,
/*0a10*/ 0xad0a0010, 0xad0b0008, 0x00401821, 0x8c620600,
/*0a20*/ 0x30428000, 0x1440fffd, 0x00000000, 0x00000000,
/*0a30*/ 0x00000000, 0x00000000, 0x00000000, 0x24034000,
/*0a40*/ 0x3c02bf80, 0xac430604, 0x3c02bf80, 0x8c420600,
/*0a50*/ 0x03e00008, 0x30422000, 0x03e00008, 0x00001021,
/*0a60*/ 0x27bdffe8, 0xafbf0014, 0x3c02bf80, 0xac440620,
/*0a70*/ 0x3c02bf80, 0xac450630, 0x0c0004b1, 0x24040001,
/*0a80*/ 0x8fbf0014, 0x03e00008, 0x27bd0018, 0x27bdffe8,
/*0a90*/ 0xafbf0014, 0x3c02bf80, 0xac440620, 0x8ca30000,
/*0aa0*/ 0x3c02bf80, 0xac430630, 0x8ca30004, 0x3c02bf80,
/*0ab0*/ 0xac430640, 0x8ca30008, 0x3c02bf80, 0xac430650,
/*0ac0*/ 0x8ca3000c, 0x3c02bf80, 0xac430660, 0x0c0004b1,
/*0ad0*/ 0x24040002, 0x8fbf0014, 0x03e00008, 0x27bd0018,
/*0ae0*/ 0x27bdffe8, 0xafbf0014, 0x3c02bf80, 0xac440620,
/*0af0*/ 0x3c02bf80, 0xac450670, 0x0c0004b1, 0x24040003,
/*0b00*/ 0x8fbf0014, 0x03e00008, 0x27bd0018, 0x27bdffe8,
/*0b10*/ 0xafbf0014, 0x3c02bf80, 0xac440620, 0x0c0004b1,
/*0b20*/ 0x24040004, 0x8fbf0014, 0x03e00008, 0x27bd0018,
/*0b30*/ 0x27bdffe8, 0xafbf0014, 0x0c0004b1, 0x2404000e,
/*0b40*/ 0x8fbf0014, 0x03e00008, 0x27bd0018, 0x3c02bf80,
/*0b50*/ 0xac440620, 0x3c02bf80, 0xac450670, 0x3c02bf80,
/*0b60*/ 0x24030003, 0xac430600, 0x24034003, 0xac430600,
/*0b70*/ 0x3c08bf80, 0x35080600, 0x3c09aa99, 0x35296655,
/*0b80*/ 0x3c0a5566, 0x354a99aa, 0x3c0b0000, 0x356b8000,
/*0b90*/ 0x3c0c0000, 0x358c8080, 0xad090010, 0xad0a0010,
/*0ba0*/ 0xad0c0090, 0x00000000, 0xad090010, 0xad0a0010,
/*0bb0*/ 0xad0b0008, 0x00000000, 0x00000000, 0x00000000,
/*0bc0*/ 0x00000000, 0x03e00008, 0x00001021, 0x3c03bf80,
/*0bd0*/ 0x8c620600, 0x30428000, 0x1440fffd, 0x00000000,
/*0be0*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
/*0bf0*/ 0x24034000, 0x3c02bf80, 0xac430604, 0x3c02bf80,
/*0c00*/ 0x8c420600, 0x03e00008, 0x30422000, 0x03e00008,
/*0c10*/ 0x97828014, 0x308400ff, 0x97828014, 0x00021a02,
/*0c20*/ 0x00831826, 0x00031880, 0x3c05a000, 0x24a52000,
/*0c30*/ 0x00651821, 0x8c630000, 0x00021200, 0x00621026,
/*0c40*/ 0x03e00008, 0xa7828014, 0x27bdffe0, 0xafbf001c,
/*0c50*/ 0xafb10018, 0xafb00014, 0x10a00007, 0x00808021,
/*0c60*/ 0x00858821, 0x92040000, 0x0c000545, 0x26100001,
/*0c70*/ 0x5611fffd, 0x92040000, 0x8fbf001c, 0x8fb10018,
/*0c80*/ 0x8fb00014, 0x03e00008, 0x27bd0020, 0x3c07a000,
/*0c90*/ 0x24e72000, 0x00003021, 0x24080100, 0x00062200,
/*0ca0*/ 0x3084ffff, 0x24030008, 0x00001021, 0x00822826,
/*0cb0*/ 0x7c052e20, 0x04a10004, 0x00021040, 0x38421021,
/*0cc0*/ 0x08000573, 0x3042ffff, 0x3042ffff, 0x2463ffff,
/*0cd0*/ 0x10600003, 0x00042040, 0x0800056b, 0x3084ffff,
/*0ce0*/ 0xace20000, 0x24c60001, 0x14c8ffec, 0x24e70004,
/*0cf0*/ 0x03e00008, 0x00000000, 0x27bdffe8, 0xafbf0014,
/*0d00*/ 0xaf808018, 0x0c000563, 0xa7848014, 0x24020001,
/*0d10*/ 0xaf828018, 0x8fbf0014, 0x03e00008, 0x27bd0018,
/*0d20*/ 0x24031f00, 0x3c02bf81, 0xac431034, 0x24a5ffff,
/*0d30*/ 0x00052a00, 0x3c02bf81, 0xac451038, 0x3c02bf81,
/*0d40*/ 0xac461040, 0x3c02bf81, 0xac441050, 0x03e00008,
/*0d50*/ 0x00000000, 0x24020040, 0xac820018, 0x24031000,
/*0d60*/ 0x3c02bf81, 0xac431004, 0x34038000, 0x3c02bf81,
/*0d70*/ 0xac431008, 0x8c820000, 0x30420080, 0x1440fffd,
/*0d80*/ 0x00000000, 0x03e00008, 0x00000000, 0x04830003,
/*0d90*/ 0x3c024000, 0x03e00008, 0x7c82e000, 0x03e00008,
/*0da0*/ 0x00821021, 0x03e00008, 0x3c020001, 0x27bdffd0,
/*0db0*/ 0xafbf002c, 0xafb50028, 0xafb40024, 0xafb30020,
/*0dc0*/ 0xafb2001c, 0xafb10018, 0xafb00014, 0x00a09821,
/*0dd0*/ 0x00c09021, 0x3c11bf81, 0x26311060, 0x240200c0,
/*0de0*/ 0x70821802, 0x00718821, 0x240200ff, 0xae220024,
/*0df0*/ 0x24020080, 0xae220008, 0xae220018, 0x10a00051,
/*0e00*/ 0x00001021, 0x24030001, 0x10a30022, 0x24070001,
/*0e10*/ 0x8e220050, 0x10400004, 0x00000000, 0x8e350050,
/*0e20*/ 0x080005cd, 0x00000000, 0x0c0005a9, 0x00000000,
/*0e30*/ 0x0040a821, 0x8e220060, 0x10400004, 0x00000000,
/*0e40*/ 0x8e340060, 0x080005d6, 0x00000000, 0x0c0005a9,
/*0e50*/ 0x00000000, 0x0040a021, 0x8e220090, 0x10400004,
/*0e60*/ 0x00000000, 0x8e220090, 0x080005df, 0x0295382b,
/*0e70*/ 0x0c0005a9, 0x00000000, 0x0295382b, 0x0287a80a,
/*0e80*/ 0x26a7ffff, 0x00e23821, 0x00e2001b, 0x004001f4,
/*0e90*/ 0x00003812, 0x24e7ffff, 0x02403021, 0x24080001,
/*0ea0*/ 0x240a0004, 0x24090080, 0x8e250020, 0x8e240020,
/*0eb0*/ 0x7c840040, 0x8e220020, 0x7c4200c0, 0x8e230020,
/*0ec0*/ 0x7c630080, 0x7cb00004, 0x7c900844, 0x7c701084,
/*0ed0*/ 0x7c5018c4, 0x32020003, 0x50400006, 0x32020008,
/*0ee0*/ 0x32030001, 0x24040001, 0x24020002, 0x08000611,
/*0ef0*/ 0x0083100b, 0x14400010, 0x32030004, 0x10600008,
/*0f00*/ 0x00000000, 0x5268000f, 0x00001021, 0x10e0000d,
/*0f10*/ 0x24020003, 0xae2a0024, 0xae290018, 0x24e7ffff,
/*0f20*/ 0x1240ffe1, 0x00000000, 0x10c00005, 0x24c6ffff,
/*0f30*/ 0x080005ea, 0x00000000, 0x08000611, 0x00001021,
/*0f40*/ 0x24020005, 0x8fbf002c, 0x8fb50028, 0x8fb40024,
/*0f50*/ 0x8fb30020, 0x8fb2001c, 0x8fb10018, 0x8fb00014,
/*0f60*/ 0x03e00008, 0x27bd0030, 0x27bdffd0, 0xafbf002c,
/*0f70*/ 0xafb50028, 0xafb40024, 0xafb30020, 0xafb2001c,
/*0f80*/ 0xafb10018, 0xafb00014, 0x00808821, 0x00a0a021,
/*0f90*/ 0x00c0a821, 0x00e09021, 0x3c10bf81, 0x26101060,
/*0fa0*/ 0x240200c0, 0x70e21802, 0x00708021, 0x3c13bf81,
/*0fb0*/ 0x24020080, 0xae621034, 0x0c000595, 0x02002021,
/*0fc0*/ 0x8e020000, 0x8fa30040, 0x7c620804, 0xae020000,
/*0fd0*/ 0x24020038, 0xae020014, 0x2402ffff, 0xae020024,
/*0fe0*/ 0x24020007, 0xae621034, 0x364300c0, 0x3c02bf81,
/*0ff0*/ 0xac431038, 0x0c0005a3, 0x02802021, 0xae020030,
/*1000*/ 0x0c0005a3, 0x02202021, 0xae020040, 0xae150090,
/*1010*/ 0x8e020090, 0xae020060, 0x8e020060, 0xae020050,
/*1020*/ 0x02402021, 0x24050002, 0x0c0005ab, 0x00003021,
/*1030*/ 0x8fbf002c, 0x8fb50028, 0x8fb40024, 0x8fb30020,
/*1040*/ 0x8fb2001c, 0x8fb10018, 0x8fb00014, 0x03e00008,
/*1050*/ 0x27bd0030,
/*1054*/ 0x0502cdab, 0xbf811060,
/*105c*/ 0xa0002000, 0x00001000, 0x00000000, 0x00000000,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};


pic32prog-201612.zip > pickit2.h

/*
* Microchip PICkit2 USB adapter.
* Low-level interface.
*
* Copyright (C) 2011-2013 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/

#ifndef _PICKIT2_H
#define _PICKIT2_H

/*
* PICkit2 Commands.
*/
#define CMD_NO_OPERATION 0x5A // Do nothing
#define CMD_GET_VERSION 0x76 // {major} {minor} {dot}
// Get firmware version
#define CMD_BOOT_MODE 0x42 // Enter Bootloader mode
#define CMD_SET_VDD 0xA0 // {CCPL} {CCPH} {VDDLim}
#define CMD_SET_VPP 0xA1 // {CCPR2L} {VPPADC} {VPPLim}
#define CMD_READ_STATUS 0xA2 // {StsL} {StsH}
#define CMD_READ_VOLTAGES 0xA3 // {VddL} {VddH} {VppL} {VppH}
#define CMD_DOWNLOAD_SCRIPT 0xA4 // {Script#} {ScriptLengthN} {Script1} {Script2} ... {ScriptN}
// Store a script in the Script Buffer
#define CMD_RUN_SCRIPT 0xA5 // {Script#} {iterations}
// Run a script from the script buffer
#define CMD_EXECUTE_SCRIPT 0xA6 // {ScriptLengthN} {Script1} {Script2} ... {ScriptN}
// Immediately execute the included script
#define CMD_CLEAR_DOWNLOAD_BUFFER 0xA7 // Empty the download buffer
#define CMD_DOWNLOAD_DATA 0xA8 // {DataLength} {Data1} {Data2} ... {DataN}
// Add data to download buffer
#define CMD_CLEAR_UPLOAD_BUFFER 0xA9 // Empty the upload buffer
#define CMD_UPLOAD_DATA 0xAA // {DataLengthN} {data1} {data2} ... {dataN}
// Read data from upload buffer
#define CMD_CLEAR_SCRIPT_BUFFER 0xAB
#define CMD_UPLOAD_DATA_NOLEN 0xAC // {Data1} {Data2} ... {DataN}
// Read data from upload buffer
#define CMD_END_OF_BUFFER 0xAD // Skip the rest of commands
#define CMD_RESET 0xAE // Reset
#define CMD_SCRIPT_BUFFER_CSUM 0xAF // {LenSumL} {LenSumH} {BufSumL} {BufSumH}
// Calculate checksums of the Script Buffer
#define CMD_SET_VOLTAGE_CAL 0xB0 // {adc_calfactorL} {adc_calfactorH} {vdd_offset} {calfactor}
#define CMD_WRITE_INTERNAL_EEPROM 0xB1 // {address} {datalength} {data1} {data2} ... {dataN}
// Write data to PIC18F2550 EEPROM
#define CMD_READ_INTERNAL_EEPROM 0xB2 // {address} {datalength}
// {data1} {data2} ... {dataN}
// Read bytes from PIC18F2550 EEPROM
#define CMD_ENTER_UART_MODE 0xB3
#define CMD_EXIT_UART_MODE 0xB4 // Exits the firmware from UART Mode
#define CMD_ENTER_LEARN_MODE 0xB5 // {0x50} {0x4B} {0x32} {EEsize}
// Puts the firmware in PK2GO Learn Mode
#define CMD_EXIT_LEARN_MODE 0xB6 // Ignore
#define CMD_ENABLE_PK2GO_MODE 0xB7 // {0x50} {0x4B} {0x32} {EEsize}
// Puts the firmware in PK2GO Mode
#define CMD_LOGIC_ANALYZER_GO 0xB8 // {EdgeRising} {TrigMask} {TrigStates} {EdgeMask} {TrigCount} {PostTrigCountL} {PostTrigCountH} {SampleRateFactor}
// {TrigLocL} {TrigLocH}
#define CMD_COPY_RAM_UPLOAD 0xB9 // {StartAddrL} {StartAddrH}

/*
* PICkit3 Commands.
*/
#define CMD_GETVERSIONS_MPLAB 0x41 // Get firmware version

/*
* Status bits.
*/
#define STATUS_VDD_GND_ON 0x0001 // Vdd GND On
#define STATUS_VDD_ON 0x0002 // Vdd On
#define STATUS_VPP_GND_ON 0x0004 // Vpp GND On
#define STATUS_VPP_ON 0x0008 // Vpp On
#define STATUS_VDD_ERROR 0x0010 // Vdd Error
#define STATUS_VPP_ERROR 0x0020 // Vpp Error
#define STATUS_BUTTON_PRESSED 0x0040 // Button Pressed
#define STATUS_RESET 0x0100 // Reset
#define STATUS_UART_MODE 0x0200 // UART Mode
#define STATUS_ICD_TIMEOUT 0x0400 // ICD TimeOut
#define STATUS_UPLOAD_FULL 0x0800 // Upload Full
#define STATUS_DOWNLOAD_EMPTY 0x1000 // Download Empty
#define STATUS_EMPTY_SCRIPT 0x2000 // Empty Script
#define STATUS_SCRIPT_BUF_OVFL 0x4000 // Script Buffer Overflow
#define STATUS_DOWNLOAD_OVFL 0x8000 // Download Overflow

/*
* Script instructions.
*/
#define SCRIPT_JT2_PE_PROG_RESP 0xB3 // +
#define SCRIPT_JT2_WAIT_PE_RESP 0xB4 // +
#define SCRIPT_JT2_GET_PE_RESP 0xB5 // +
#define SCRIPT_JT2_XFERINST_BUF 0xB6 //
#define SCRIPT_JT2_XFRFASTDAT_BUF 0xB7 // +
#define SCRIPT_JT2_XFRFASTDAT_LIT 0xB8 // + 4
#define SCRIPT_JT2_XFERDATA32_LIT 0xB9 // + 4
#define SCRIPT_JT2_XFERDATA8_LIT 0xBA // + 1
#define SCRIPT_JT2_SENDCMD 0xBB // + 1
#define SCRIPT_JT2_SETMODE 0xBC // + 2
#define SCRIPT_UNIO_TX_RX 0xBD //
#define SCRIPT_UNIO_TX 0xBE //
#define SCRIPT_MEASURE_PULSE 0xBF //
#define SCRIPT_ICDSLAVE_TX_BUF_BL 0xC0 //
#define SCRIPT_ICDSLAVE_TX_LIT_BL 0xC1 //
#define SCRIPT_ICDSLAVE_RX_BL 0xC2 //
#define SCRIPT_SPI_RDWR_BYTE_BUF 0xC3 //
#define SCRIPT_SPI_RDWR_BYTE_LIT 0xC4 //
#define SCRIPT_SPI_RD_BYTE_BUF 0xC5 //
#define SCRIPT_SPI_WR_BYTE_BUF 0xC6 //
#define SCRIPT_SPI_WR_BYTE_LIT 0xC7 //
#define SCRIPT_I2C_RD_BYTE_NACK 0xC8 //
#define SCRIPT_I2C_RD_BYTE_ACK 0xC9 //
#define SCRIPT_I2C_WR_BYTE_BUF 0xCA //
#define SCRIPT_I2C_WR_BYTE_LIT 0xCB //
#define SCRIPT_I2C_STOP 0xCC //
#define SCRIPT_I2C_START 0xCD //
#define SCRIPT_AUX_STATE_BUFFER 0xCE //
#define SCRIPT_SET_AUX 0xCF //
#define SCRIPT_WRITE_BITS_BUF_HLD 0xD0 //
#define SCRIPT_WRITE_BITS_LIT_HLD 0xD1 //
#define SCRIPT_CONST_WRITE_DL 0xD2 //
#define SCRIPT_WRITE_BUFBYTE_W 0xD3 //
#define SCRIPT_WRITE_BUFWORD_W 0xD4 //
#define SCRIPT_RD2_BITS_BUFFER 0xD5 //
#define SCRIPT_RD2_BYTE_BUFFER 0xD6 //
#define SCRIPT_VISI24 0xD7 //
#define SCRIPT_NOP24 0xD8 //
#define SCRIPT_COREINST24 0xD9 //
#define SCRIPT_COREINST18 0xDA //
#define SCRIPT_POP_DOWNLOAD 0xDB //
#define SCRIPT_ICSP_STATES_BUFFER 0xDC //
#define SCRIPT_LOOPBUFFER 0xDD //
#define SCRIPT_ICDSLAVE_TX_BUF 0xDE //
#define SCRIPT_ICDSLAVE_TX_LIT 0xDF //
#define SCRIPT_ICDSLAVE_RX 0xE0 //
#define SCRIPT_POKE_SFR 0xE1 //
#define SCRIPT_PEEK_SFR 0xE2 //
#define SCRIPT_EXIT_SCRIPT 0xE3 //
#define SCRIPT_GOTO_INDEX 0xE4 //
#define SCRIPT_IF_GT_GOTO 0xE5 //
#define SCRIPT_IF_EQ_GOTO 0xE6 //
#define SCRIPT_DELAY_SHORT 0xE7 // + 1 increments of 42.7us
#define SCRIPT_DELAY_LONG 0xE8 // + 1 increments of 5.46ms
#define SCRIPT_LOOP 0xE9 // + 2
#define SCRIPT_SET_ICSP_SPEED 0xEA // + 1
#define SCRIPT_READ_BITS 0xEB //
#define SCRIPT_READ_BITS_BUFFER 0xEC //
#define SCRIPT_WRITE_BITS_BUFFER 0xED //
#define SCRIPT_WRITE_BITS_LITERAL 0xEE //
#define SCRIPT_READ_BYTE 0xEF //
#define SCRIPT_READ_BYTE_BUFFER 0xF0 //
#define SCRIPT_WRITE_BYTE_BUFFER 0xF1 //
#define SCRIPT_WRITE_BYTE_LITERAL 0xF2 // + 1
#define SCRIPT_SET_ICSP_PINS 0xF3 // + 1
#define SCRIPT_BUSY_LED_OFF 0xF4 // +
#define SCRIPT_BUSY_LED_ON 0xF5 // +
#define SCRIPT_MCLR_GND_OFF 0xF6 // +
#define SCRIPT_MCLR_GND_ON 0xF7 // +
#define SCRIPT_VPP_PWM_OFF 0xF8 // +
#define SCRIPT_VPP_PWM_ON 0xF9 // +
#define SCRIPT_VPP_OFF 0xFA // +
#define SCRIPT_VPP_ON 0xFB // +
#define SCRIPT_VDD_GND_OFF 0xFC // +
#define SCRIPT_VDD_GND_ON 0xFD // +
#define SCRIPT_VDD_OFF 0xFE // +
#define SCRIPT_VDD_ON 0xFF // +

#endif


pic32prog-201612.zip > adapter-hidboot.c

/*
* Interface to PIC32 Microchip USB HID bootloader (old).
*
* Copyright (C) 2011-2013 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include & lt; stdlib.h & gt;
#include & lt; unistd.h & gt;
#include & lt; fcntl.h & gt;
#include & lt; string.h & gt;
#include & lt; errno.h & gt;

#include " adapter.h "
#include " hidapi.h "
#include " pic32.h "

/* Bootloader commands */
#define CMD_QUERY_DEVICE 0x02
#define CMD_UNLOCK_CONFIG 0x03
#define CMD_ERASE_DEVICE 0x04
#define CMD_PROGRAM_DEVICE 0x05
#define CMD_PROGRAM_COMPLETE 0x06
#define CMD_GET_DATA 0x07
#define CMD_RESET_DEVICE 0x08

typedef struct {
/* Common part */
adapter_t adapter;

/* Device handle for libusb. */
hid_device *hiddev;

unsigned char reply [64];
int reply_len;

} hidboot_adapter_t;

/*
* Identifiers of USB adapter.
*/
#define MICROCHIP_VID 0x04d8
#define BOOTLOADER_PID 0x003c /* Microchip HID bootloader */
#define MAXIMITE_PID 0xfa8d /* Maximite bootloader */

#define OLIMEX_VID 0x15ba
#define DUINOMITE_PID 0x0032 /* Olimex Duinomite bootloader */

/*
* Send a request to the device.
* Store the reply into the a- & gt; reply[] array.
*/
static void hidboot_command(hidboot_adapter_t *a, unsigned char cmd,
unsigned char *data, unsigned nbytes)
{
unsigned char buf [64];
unsigned k;

memset(buf, 0, sizeof(buf));
buf[0] = cmd;
if (nbytes & gt; 0)
memcpy(buf+1, data, nbytes);

if (debug_level & gt; 0) {
fprintf(stderr, " ---Send " );
for (k=0; k & lt; =nbytes; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , buf[k]);
}
fprintf(stderr, " \n " );
}
hid_write(a- & gt; hiddev, buf, 64);

if (cmd != CMD_QUERY_DEVICE & & cmd != CMD_GET_DATA) {
/* No reply expected. */
return;
}

memset(a- & gt; reply, 0, sizeof(a- & gt; reply));
a- & gt; reply_len = hid_read_timeout(a- & gt; hiddev, a- & gt; reply, 64, 4000);
if (a- & gt; reply_len == 0) {
fprintf(stderr, " Timed out.\n " );
exit(-1);
}
if (a- & gt; reply_len != 64) {
fprintf(stderr, " hidboot: error %d receiving packet\n " , a- & gt; reply_len);
exit(-1);
}
if (debug_level & gt; 0) {
fprintf(stderr, " ---Recv " );
for (k=0; k & lt; a- & gt; reply_len; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , a- & gt; reply[k]);
}
fprintf(stderr, " \n " );
}
}

static void hidboot_close(adapter_t *adapter, int power_on)
{
hidboot_adapter_t *a = (hidboot_adapter_t*) adapter;

/* Jump to application. */
if (power_on)
hidboot_command(a, CMD_RESET_DEVICE, 0, 0);
free(a);
}

/*
* Return the Device Identification code
*/
static unsigned hidboot_get_idcode(adapter_t *adapter)
{
return 0xDEAFB00B;
}

/*
* Read a configuration word from memory.
*/
static unsigned hidboot_read_word(adapter_t *adapter, unsigned addr)
{
/* TODO */
return 0;
}

/*
* Write a configuration word to flash memory.
*/
static void hidboot_program_word(adapter_t *adapter,
unsigned addr, unsigned word)
{
/* TODO */
if (debug_level & gt; 0)
fprintf(stderr, " hidboot: program word at %08x: %08x\n " , addr, word);
}

/*
* Read a block of memory.
*/
static void hidboot_read_data(adapter_t *adapter,
unsigned addr, unsigned nwords, unsigned *data)
{
hidboot_adapter_t *a = (hidboot_adapter_t*) adapter;
unsigned char request [64];
unsigned nbytes;

for (; ; nwords-=14) {
/* 14 words = 56 bytes per packet. */
nbytes = nwords & gt; 14 ? 14*4 : nwords*4;

*(unsigned*) & request[0] = addr;
request[4] = nbytes;

hidboot_command(a, CMD_GET_DATA, request, 5);

/* Data is right aligned. */
memcpy(data, a- & gt; reply + 64 - nbytes, nbytes);

if (nwords & lt; = 14)
break;
data += 14;
addr += 14*4;
}
}

static void program_flash(hidboot_adapter_t *a,
unsigned addr, unsigned *data, unsigned nwords)
{
unsigned char request[64];
unsigned nbytes;

//fprintf(stderr, " hidboot: program %d bytes at %08x: %08x-%08x-...-%08x\n " ,
// nbytes, addr, data[0], data[1], data[nwords-1]);

nbytes = nwords * 4;
if (addr & lt; a- & gt; adapter.user_start ||
addr + nbytes & gt; = a- & gt; adapter.user_start + a- & gt; adapter.user_nbytes)
{
fprintf(stderr, " address %08x out of program area\n " , addr);
return;
}

memset(request, 0, sizeof(request));
*(unsigned*) & request[0] = addr;
request[4] = nbytes;
request[5] = 0;
request[6] = 0;

/* Data is right aligned. */
memcpy(request + 63 - nbytes, data, nbytes);

hidboot_command(a, CMD_PROGRAM_DEVICE, request, 63);
}

/*
* Flash write, 1-kbyte blocks.
*/
static void hidboot_program_block(adapter_t *adapter,
unsigned addr, unsigned *data)
{
hidboot_adapter_t *a = (hidboot_adapter_t*) adapter;
int nwords;

for (nwords=256; nwords & gt; 0; nwords-=14) {
/* 14 words = 56 bytes per packet. */
program_flash(a, addr, data, nwords & gt; 14 ? 14 : nwords);
data += 14;
addr += 14*4;
}
hidboot_command(a, CMD_PROGRAM_COMPLETE, 0, 0);
}

/*
* Erase all flash memory.
*/
static void hidboot_erase_chip(adapter_t *adapter)
{
hidboot_adapter_t *a = (hidboot_adapter_t*) adapter;

//fprintf(stderr, " hidboot: erase chip\n " );
hidboot_command(a, CMD_ERASE_DEVICE, 0, 0);

/* To wait when erase finished, query a reply. */
hidboot_command(a, CMD_QUERY_DEVICE, 0, 0);
}

/*
* Initialize adapter hidboot.
* Return a pointer to a data structure, allocated dynamically.
* When adapter not found, return 0.
*/
adapter_t *adapter_open_hidboot(int vid, int pid, const char *serial)
{
hidboot_adapter_t *a;
hid_device *hiddev;

if (vid) {
wchar_t buf[256];
if (serial)
mbstowcs(buf, serial, 256);
hiddev = hid_open(vid, pid, serial ? buf : 0);
} else {
hiddev = hid_open(MICROCHIP_VID, BOOTLOADER_PID, 0);
if (! hiddev)
hiddev = hid_open(MICROCHIP_VID, MAXIMITE_PID, 0);
if (! hiddev)
hiddev = hid_open(OLIMEX_VID, DUINOMITE_PID, 0);
}
if (! hiddev) {
if (vid)
fprintf(stderr, " HID bootloader not found: vid=%04x, pid=%04x, serial=%s\n " ,
vid, pid, serial ? : " (none) " );
return 0;
}
a = calloc(1, sizeof(*a));
if (! a) {
fprintf(stderr, " Out of memory\n " );
return 0;
}
a- & gt; hiddev = hiddev;

/* Read version of adapter. */
hidboot_command(a, CMD_QUERY_DEVICE, 0, 0);
if (a- & gt; reply[0] != CMD_QUERY_DEVICE ||
a- & gt; reply[1] != 56 || /* HID packet data size */
a- & gt; reply[2] != 3 || /* PIC32 device family */
a- & gt; reply[3] != 1) /* program memory type */
return 0;

a- & gt; adapter.user_start = *(unsigned*) & a- & gt; reply[4] & 0x1fffffff;
a- & gt; adapter.user_nbytes = *(unsigned*) & a- & gt; reply[8] & 0x0fffffff;
printf( " Adapter: HID Bootloader\n " );
printf( " Program area: %08x-%08x\n " , a- & gt; adapter.user_start,
a- & gt; adapter.user_start + a- & gt; adapter.user_nbytes - 1);

a- & gt; adapter.block_override = 0;
a- & gt; adapter.flags = (AD_PROBE | AD_ERASE | AD_READ | AD_WRITE);

/* User functions. */
a- & gt; adapter.close = hidboot_close;
a- & gt; adapter.get_idcode = hidboot_get_idcode;
a- & gt; adapter.read_word = hidboot_read_word;
a- & gt; adapter.read_data = hidboot_read_data;
a- & gt; adapter.erase_chip = hidboot_erase_chip;
a- & gt; adapter.program_block = hidboot_program_block;
a- & gt; adapter.program_word = hidboot_program_word;
return & a- & gt; adapter;
}


pic32prog-201612.zip > README.txt

This directory contains a pic32prog binary for Mac OS X.


pic32prog-201612.zip > adapter-an1388.c

/*
* Interface to PIC32 Microchip AN1388 USB bootloader (new).
*
* Copyright (C) 2011-2013 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include & lt; stdlib.h & gt;
#include & lt; unistd.h & gt;
#include & lt; fcntl.h & gt;
#include & lt; string.h & gt;
#include & lt; errno.h & gt;

#include " adapter.h "
#include " hidapi.h "
#include " pic32.h "

#define FRAME_SOH 0x01
#define FRAME_EOT 0x04
#define FRAME_DLE 0x10

#define CMD_READ_VERSION 0x01
#define CMD_ERASE_FLASH 0x02
#define CMD_PROGRAM_FLASH 0x03
#define CMD_READ_CRC 0x04
#define CMD_JUMP_APP 0x05

typedef struct {
/* Common part */
adapter_t adapter;

/* Device handle for libusb. */
hid_device *hiddev;

unsigned char reply [64];
int reply_len;

} an1388_adapter_t;

/*
* Identifiers of USB adapter.
*/
#define MICROCHIP_VID 0x04d8
#define BOOTLOADER_PID 0x003c /* Microchip AN1388 Bootloader */

/*
* Calculate checksum.
*/
static unsigned calculate_crc(unsigned crc, unsigned char *data, unsigned nbytes)
{
static const unsigned short crc_table [16] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};
unsigned i;

while (nbytes--) {
i = (crc & gt; & gt; 12) ^ (*data & gt; & gt; 4);
crc = crc_table[i & 0x0F] ^ (crc & lt; & lt; 4);
i = (crc & gt; & gt; 12) ^ (*data & gt; & gt; 0);
crc = crc_table[i & 0x0F] ^ (crc & lt; & lt; 4);
data++;
}
return crc & 0xffff;
}

static void an1388_send(hid_device *hiddev, unsigned char *buf, unsigned nbytes)
{
if (debug_level & gt; 0) {
int k;
fprintf(stderr, " ---Send " );
for (k=0; k & lt; nbytes; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , buf[k]);
}
fprintf(stderr, " \n " );
}
hid_write(hiddev, buf, 64);
}

static int an1388_recv(hid_device *hiddev, unsigned char *buf)
{
int n;

n = hid_read(hiddev, buf, 64);
if (n & lt; = 0) {
fprintf(stderr, " hidboot: error %d receiving packet\n " , n);
exit(-1);
}
if (debug_level & gt; 0) {
int k;
fprintf(stderr, " ---Recv " );
for (k=0; k & lt; n; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , buf[k]);
}
fprintf(stderr, " \n " );
}
return n;
}

static inline unsigned add_byte(unsigned char c,
unsigned char *buf, unsigned indx)
{
if (c == FRAME_EOT || c == FRAME_SOH || c == FRAME_DLE)
buf[indx++] = FRAME_DLE;
buf[indx++] = c;
return indx;
}

/*
* Send a request to the device.
* Store the reply into the a- & gt; reply[] array.
*/
static void an1388_command(an1388_adapter_t *a, unsigned char cmd,
unsigned char *data, unsigned data_len)
{
unsigned char buf [64];
unsigned i, n, c, crc;

if (debug_level & gt; 0) {
int k;
fprintf(stderr, " ---Cmd%d " , cmd);
for (k=0; k & lt; data_len; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , data[k]);
}
fprintf(stderr, " \n " );
}
memset(buf, FRAME_EOT, sizeof(buf));
n = 0;
buf[n++] = FRAME_SOH;

n = add_byte(cmd, buf, n);
crc = calculate_crc(0, & cmd, 1);

if (data_len & gt; 0) {
for (i=0; i & lt; data_len; ++i)
n = add_byte(data[i], buf, n);
crc = calculate_crc(crc, data, data_len);
}
n = add_byte(crc, buf, n);
n = add_byte(crc & gt; & gt; 8, buf, n);

buf[n++] = FRAME_EOT;
an1388_send(a- & gt; hiddev, buf, n);

if (cmd == CMD_JUMP_APP) {
/* No reply expected. */
return;
}
n = an1388_recv(a- & gt; hiddev, buf);
c = 0;
for (i=0; i & lt; n; ++i) {
switch (buf[i]) {
default:
a- & gt; reply[c++] = buf[i];
continue;
case FRAME_DLE:
a- & gt; reply[c++] = buf[++i];
continue;
case FRAME_SOH:
c = 0;
continue;
case FRAME_EOT:
a- & gt; reply_len = 0;
if (c & gt; 2) {
unsigned crc = a- & gt; reply[c-2] | (a- & gt; reply[c-1] & lt; & lt; 8);
if (crc == calculate_crc(0, a- & gt; reply, c-2))
a- & gt; reply_len = c - 2;
}
if (a- & gt; reply_len & gt; 0 & & debug_level & gt; 0) {
int k;
fprintf(stderr, " --- & gt; & gt; & gt; & gt; " );
for (k=0; k & lt; a- & gt; reply_len; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , a- & gt; reply[k]);
}
fprintf(stderr, " \n " );
}
return;
}
}
}

static void an1388_close(adapter_t *adapter, int power_on)
{
an1388_adapter_t *a = (an1388_adapter_t*) adapter;

/* Jump to application. */
an1388_command(a, CMD_JUMP_APP, 0, 0);
free(a);
}

/*
* Return the Device Identification code
*/
static unsigned an1388_get_idcode(adapter_t *adapter)
{
return 0xDEAFB00B;
}

/*
* Read a configuration word from memory.
*/
static unsigned an1388_read_word(adapter_t *adapter, unsigned addr)
{
/* Not supported by booloader. */
return 0;
}

/*
* Write a configuration word to flash memory.
*/
static void an1388_program_word(adapter_t *adapter,
unsigned addr, unsigned word)
{
/* Not supported by booloader. */
if (debug_level & gt; 0)
fprintf(stderr, " hidboot: program word at %08x: %08x\n " , addr, word);
}

/*
* Verify a block of memory.
*/
static void an1388_verify_data(adapter_t *adapter,
unsigned addr, unsigned nwords, unsigned *data)
{
an1388_adapter_t *a = (an1388_adapter_t*) adapter;
unsigned char request [8];
unsigned data_crc, flash_crc, nbytes = nwords * 4;

//fprintf(stderr, " hidboot: verify %d bytes at %08x\n " , nbytes, addr);
request[0] = addr;
request[1] = addr & gt; & gt; 8;
request[2] = addr & gt; & gt; 16;
request[3] = (addr & gt; & gt; 24) + 0x80;
request[4] = nbytes;
request[5] = nbytes & gt; & gt; 8;
request[6] = nbytes & gt; & gt; 16;
request[7] = nbytes & gt; & gt; 24;
an1388_command(a, CMD_READ_CRC, request, 8);
if (a- & gt; reply_len != 3 || a- & gt; reply[0] != CMD_READ_CRC) {
fprintf(stderr, " hidboot: cannot read crc at %08x\n " , addr);
exit(-1);
}
flash_crc = a- & gt; reply[1] | a- & gt; reply[2] & lt; & lt; 8;

data_crc = calculate_crc(0, (unsigned char*) data, nbytes);
if (flash_crc != data_crc) {
fprintf(stderr, " hidboot: checksum failed at %08x: sum=%04x, expected=%04x\n " ,
addr, flash_crc, data_crc);
//exit(-1);
}
}

static void set_flash_address(an1388_adapter_t *a, unsigned addr)
{
unsigned char request[7];
unsigned sum, i;

request[0] = 2;
request[1] = 0;
request[2] = 0;
request[3] = 4; /* Type: linear address record */
request[4] = addr & gt; & gt; 24;
request[5] = addr & gt; & gt; 16;

/* Compute checksum. */
sum = 0;
for (i=0; i & lt; 6; i++)
sum += request[i];
request[6] = -sum;

an1388_command(a, CMD_PROGRAM_FLASH, request, 7);
if (a- & gt; reply_len != 1 || a- & gt; reply[0] != CMD_PROGRAM_FLASH) {
fprintf(stderr, " hidboot: error setting flash address at %08x\n " , addr);
exit(-1);
}
}

static void program_flash(an1388_adapter_t *a,
unsigned addr, unsigned char *data, unsigned nbytes)
{
unsigned char request[64];
unsigned sum, empty, i;

/* Skip empty blocks. */
empty = 1;
for (i=0; i & lt; nbytes; i++) {
if (data[i] != 0xff) {
empty = 0;
break;
}
}
if (empty)
return;
//fprintf(stderr, " hidboot: program %d bytes at %08x: %02x-%02x-...-%02x\n " ,
// nbytes, addr, data[0], data[1], data[31]);

request[0] = nbytes;
request[1] = addr & gt; & gt; 8;
request[2] = addr;
request[3] = 0; /* Type: data record */
memcpy(request+4, data, nbytes);

/* Compute checksum. */
sum = 0;
empty = 1;
for (i=0; i & lt; nbytes+4; i++) {
sum += request[i];
}
request[nbytes+4] = -sum;

an1388_command(a, CMD_PROGRAM_FLASH, request, nbytes + 5);
if (a- & gt; reply_len != 1 || a- & gt; reply[0] != CMD_PROGRAM_FLASH) {
fprintf(stderr, " hidboot: error programming flash at %08x\n " , addr);
exit(-1);
}
}

/*
* Flash write, 1-kbyte blocks.
*/
static void an1388_program_block(adapter_t *adapter,
unsigned addr, unsigned *data)
{
an1388_adapter_t *a = (an1388_adapter_t*) adapter;
unsigned i;

set_flash_address(a, addr);
for (i=0; i & lt; 256; i+=8) {
/* 8 words per cycle. */
program_flash(a, addr, (unsigned char*) data, 32);
data += 8;
addr += 32;
}
}

/*
* Erase all flash memory.
*/
static void an1388_erase_chip(adapter_t *adapter)
{
an1388_adapter_t *a = (an1388_adapter_t*) adapter;

//fprintf(stderr, " hidboot: erase chip\n " );
an1388_command(a, CMD_ERASE_FLASH, 0, 0);
if (a- & gt; reply_len != 1 || a- & gt; reply[0] != CMD_ERASE_FLASH) {
fprintf(stderr, " hidboot: Erase failed\n " );
exit(-1);
}
}

/*
* Initialize adapter hidboot.
* Return a pointer to a data structure, allocated dynamically.
* When adapter not found, return 0.
*/
adapter_t *adapter_open_an1388(int vid, int pid, const char *serial)
{
an1388_adapter_t *a;
hid_device *hiddev;

if (vid) {
wchar_t buf[256];
if (serial)
mbstowcs(buf, serial, 256);
hiddev = hid_open(vid, pid, serial ? buf : 0);
} else
hiddev = hid_open(MICROCHIP_VID, BOOTLOADER_PID, 0);

if (! hiddev) {
if (vid)
fprintf(stderr, " AN1388 bootloader not found: vid=%04x, pid=%04x, serial=%s\n " ,
vid, pid, serial ? : " (none) " );
return 0;
}
a = calloc(1, sizeof(*a));
if (! a) {
fprintf(stderr, " Out of memory\n " );
return 0;
}
a- & gt; hiddev = hiddev;

/* Read version of adapter. */
an1388_command(a, CMD_READ_VERSION, 0, 0);
printf( " Adapter: AN1388 Bootloader Version %d.%d\n " ,
a- & gt; reply[1], a- & gt; reply[2]);

a- & gt; adapter.user_start = 0x1d000000;
a- & gt; adapter.user_nbytes = 512 * 1024;
printf( " Program area: %08x-%08x\n " , a- & gt; adapter.user_start,
a- & gt; adapter.user_start + a- & gt; adapter.user_nbytes - 1);
a- & gt; adapter.block_override = 0;
a- & gt; adapter.flags = (AD_PROBE | AD_ERASE | AD_READ | AD_WRITE);

/* User functions. */
a- & gt; adapter.close = an1388_close;
a- & gt; adapter.get_idcode = an1388_get_idcode;
a- & gt; adapter.read_word = an1388_read_word;
a- & gt; adapter.verify_data = an1388_verify_data;
a- & gt; adapter.erase_chip = an1388_erase_chip;
a- & gt; adapter.program_block = an1388_program_block;
a- & gt; adapter.program_word = an1388_program_word;
return & a- & gt; adapter;
}


pic32prog-201612.zip > pic32prog.c

/*
* Flash memory programmer for Microchip PIC32 microcontrollers.
*
* Copyright (C) 2011-2014 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include & lt; stdlib.h & gt;
#include & lt; string.h & gt;
#include & lt; unistd.h & gt;
#include & lt; ctype.h & gt;
#include & lt; signal.h & gt;
#include & lt; getopt.h & gt;
#include & lt; sys/time.h & gt;
#include & lt; sys/stat.h & gt;
#include & lt; time.h & gt;
#include & lt; libgen.h & gt;
#include & lt; locale.h & gt;

#include " target.h "
#include " serial.h "
#include " localize.h "
#include " adapter.h "

#ifndef VERSION
#define VERSION " 2.0. " GITCOUNT
#endif
#define MINBLOCKSZ 128
#define FLASHV_BASE 0x9d000000
#define BOOTV_BASE 0x9fc00000
#define FLASHP_BASE 0x1d000000
#define BOOTP_BASE 0x1fc00000
#define FLASH_BYTES (2048 * 1024)
#define BOOT_BYTES (80 * 1024)

/* Macros for converting between hex and binary. */
#define NIBBLE(x) (isdigit(x) ? (x)-'0' : tolower(x)+10-'a')
#define HEX(buffer) ((NIBBLE((buffer)[0]) & lt; & lt; 4) + NIBBLE((buffer)[1]))

/* Data to write */
unsigned char boot_data [BOOT_BYTES];
unsigned char flash_data [FLASH_BYTES];
unsigned char boot_dirty [BOOT_BYTES / MINBLOCKSZ];
unsigned char flash_dirty [FLASH_BYTES / MINBLOCKSZ];
unsigned blocksz; /* Size of flash memory block */
unsigned boot_used;
unsigned flash_used;
unsigned boot_bytes;
unsigned flash_bytes;
unsigned devcfg_offset; /* Offset of devcfg registers in boot data */
int total_bytes;

#define devcfg3 (*(unsigned*) & boot_data [devcfg_offset])
#define devcfg2 (*(unsigned*) & boot_data [devcfg_offset + 4])
#define devcfg1 (*(unsigned*) & boot_data [devcfg_offset + 8])
#define devcfg0 (*(unsigned*) & boot_data [devcfg_offset + 12])

unsigned progress_count;
int verify_only;
int erase_only = 0;
int skip_verify = 0;
int debug_level;
int power_on;
target_t *target;
const char *target_port; /* Optional name of target serial or USB port */
int target_speed = 115200; /* Baud rate for serial port */
int alternate_speed = 115200; /* Alternate speed for serial port */
char *progname;
const char *copyright;

void *fix_time()
{
static struct timeval t0;

gettimeofday( & t0, 0);
return & t0;
}

unsigned mseconds_elapsed(void *arg)
{
struct timeval t1, *t0 = arg;
unsigned mseconds;

gettimeofday( & t1, 0);
mseconds = (t1.tv_sec - t0- & gt; tv_sec) * 1000 +
(t1.tv_usec - t0- & gt; tv_usec) / 1000;
if (mseconds & lt; 1)
mseconds = 1;
return mseconds;
}

void store_data(unsigned address, unsigned byte)
{
unsigned offset;

if (address & gt; = BOOTV_BASE & & address & lt; BOOTV_BASE + BOOT_BYTES) {
/* Boot code, virtual. */
offset = address - BOOTV_BASE;
boot_data [offset] = byte;
boot_used = 1;

} else if (address & gt; = BOOTP_BASE & & address & lt; BOOTP_BASE + BOOT_BYTES) {
/* Boot code, physical. */
offset = address - BOOTP_BASE;
boot_data [offset] = byte;
boot_used = 1;

} else if (address & gt; = FLASHV_BASE & & address & lt; FLASHV_BASE + FLASH_BYTES) {
/* Main flash memory, virtual. */
offset = address - FLASHV_BASE;
flash_data [offset] = byte;
flash_used = 1;

} else if (address & gt; = FLASHP_BASE & & address & lt; FLASHP_BASE + FLASH_BYTES) {
/* Main flash memory, physical. */
offset = address - FLASHP_BASE;
flash_data [offset] = byte;
flash_used = 1;
} else {
/* Ignore incorrect data. */
//fprintf(stderr, _( " %08X: address out of flash memory\n " ), address);
return;
}
total_bytes++;
}

/*
* Read the S record file.
*/
int read_srec(char *filename)
{
FILE *fd;
unsigned char buf [256];
unsigned char *data;
unsigned address;
int bytes;

fd = fopen(filename, " r " );
if (! fd) {
perror(filename);
exit(1);
}
while (fgets((char*) buf, sizeof(buf), fd)) {
if (buf[0] == '\n')
continue;
if (buf[0] != 'S') {
fclose(fd);
return 0;
}
if (buf[1] == '7' || buf[1] == '8' || buf[1] == '9')
break;

/* Starting an S-record. */
if (! isxdigit(buf[2]) || ! isxdigit(buf[3])) {
fprintf(stderr, _( " %s: bad SREC record: %s\n " ), filename, buf);
exit(1);
}
bytes = HEX(buf + 2);

/* Ignore the checksum byte. */
--bytes;

address = 0;
data = buf + 4;
switch (buf[1]) {
case '3':
address = HEX(data);
data += 2;
--bytes;
/* Fall through. */
case '2':
address = (address & lt; & lt; 8) | HEX(data);
data += 2;
--bytes;
/* Fall through. */
case '1':
address = (address & lt; & lt; 8) | HEX(data);
data += 2;
address = (address & lt; & lt; 8) | HEX(data);
data += 2;
bytes -= 2;

while (bytes-- & gt; 0) {
store_data(address++, HEX(data));
data += 2;
}
break;
}
}
fclose(fd);
return 1;
}

/*
* Read HEX file.
*/
int read_hex(char *filename)
{
FILE *fd;
unsigned char buf [256], data[16], record_type, sum;
unsigned address, high;
int bytes, i;

fd = fopen(filename, " r " );
if (! fd) {
perror(filename);
exit(1);
}
high = 0;
while (fgets((char*) buf, sizeof(buf), fd)) {
if (buf[0] == '\n')
continue;
if (buf[0] != ':') {
fclose(fd);
return 0;
}
if (! isxdigit(buf[1]) || ! isxdigit(buf[2]) ||
! isxdigit(buf[3]) || ! isxdigit(buf[4]) ||
! isxdigit(buf[5]) || ! isxdigit(buf[6]) ||
! isxdigit(buf[7]) || ! isxdigit(buf[8])) {
fprintf(stderr, _( " %s: bad HEX record: %s\n " ), filename, buf);
exit(1);
}
record_type = HEX(buf+7);
if (record_type == 1) {
/* End of file. */
break;
}
if (record_type == 5) {
/* Start address, ignore. */
continue;
}

bytes = HEX(buf+1);
if (strlen((char*) buf) & lt; bytes * 2 + 11) {
fprintf(stderr, _( " %s: too short hex line\n " ), filename);
exit(1);
}
address = high & lt; & lt; 16 | HEX(buf+3) & lt; & lt; 8 | HEX(buf+5);

sum = 0;
for (i=0; i & lt; bytes; ++i) {
data [i] = HEX(buf+9 + i + i);
sum += data [i];
}
sum += record_type + bytes + (address & 0xff) + (address & gt; & gt; 8 & 0xff);
if (sum != (unsigned char) - HEX(buf+9 + bytes + bytes)) {
fprintf(stderr, _( " %s: bad HEX checksum\n " ), filename);
exit(1);
}

if (record_type == 4) {
/* Extended address. */
if (bytes != 2) {
fprintf(stderr, _( " %s: invalid HEX linear address record length\n " ),
filename);
exit(1);
}
high = data[0] & lt; & lt; 8 | data[1];
continue;
}
if (record_type != 0) {
fprintf(stderr, _( " %s: unknown HEX record type: %d\n " ),
filename, record_type);
exit(1);
}
//printf( " %08x: %u bytes\n " , address, bytes);
for (i=0; i & lt; bytes; i++) {
store_data(address++, data [i]);
}
}
fclose(fd);
return 1;
}

void print_symbols(char symbol, int cnt)
{
while (cnt-- & gt; 0)
putchar(symbol);
}

void progress(unsigned step)
{
++progress_count;
if (progress_count % step == 0) {
putchar('#');
fflush(stdout);
}
}

void quit(void)
{
if (target != 0) {
target_close(target, power_on);
free(target);
target = 0;
}
}

void interrupted(int signum)
{
fprintf(stderr, _( " \nInterrupted.\n " ));
quit();
_exit(-1);
}

/*
* Check that the boot block, containing devcfg registers,
* has some useful data.
*/
static int is_flash_block_dirty(unsigned offset)
{
int i;

for (i=0; i & lt; blocksz; i++, offset++) {
if (flash_data [offset] != 0xff)
return 1;
}
return 0;
}

/*
* Check that the boot block, containing devcfg registers,
* has some other data.
*/
static int is_boot_block_dirty(unsigned offset)
{
int i;

for (i=0; i & lt; blocksz; i++, offset++) {
/* Skip devcfg registers. */
if (offset & gt; = devcfg_offset & & offset & lt; devcfg_offset+16)
continue;
if (boot_data [offset] != 0xff)
return 1;
}
return 0;
}

void do_probe()
{
/* Open and detect the device. */
atexit(quit);
target = target_open(target_port, target_speed);
if (! target) {
fprintf(stderr, _( " Error detecting device -- check cable!\n " ));
exit(1);
}

if ((target- & gt; adapter- & gt; flags & AD_PROBE) == 0) {
fprintf(stderr, _( " Error: Target probe not supported.\n " ));
exit(1);
}

boot_bytes = target_boot_bytes(target);
printf(_( " Processor: %s (id %08X)\n " ), target_cpu_name(target),
target_idcode(target));
printf(_( " Flash memory: %d kbytes\n " ), target_flash_bytes(target) / 1024);
if (boot_bytes & gt; 0)
printf(_( " Boot memory: %d kbytes\n " ), boot_bytes / 1024);
target_print_devcfg(target);
}

/*
* Write flash memory.
*/
void program_block(target_t *mc, unsigned addr)
{
unsigned char *data;
unsigned offset;

if (addr & gt; = BOOTV_BASE & & addr & lt; BOOTV_BASE + boot_bytes) {
data = boot_data;
offset = addr - BOOTV_BASE;
} else if (addr & gt; = BOOTP_BASE & & addr & lt; BOOTP_BASE + boot_bytes) {
data = boot_data;
offset = addr - BOOTP_BASE;
} else if (addr & gt; = FLASHV_BASE & & addr & lt; FLASHV_BASE + flash_bytes) {
data = flash_data;
offset = addr - FLASHV_BASE;
} else {
data = flash_data;
offset = addr - FLASHP_BASE;
}
target_program_block(mc, addr, blocksz/4, (unsigned*) (data + offset));
}

int verify_block(target_t *mc, unsigned addr)
{
unsigned char *data;
unsigned offset;

if (addr & gt; = BOOTV_BASE & & addr & lt; BOOTV_BASE + boot_bytes) {
data = boot_data;
offset = addr - BOOTV_BASE;
} else if (addr & gt; = BOOTP_BASE & & addr & lt; BOOTP_BASE + boot_bytes) {
data = boot_data;
offset = addr - BOOTP_BASE;
} else if (addr & gt; = FLASHV_BASE & & addr & lt; FLASHV_BASE + flash_bytes) {
data = flash_data;
offset = addr - FLASHV_BASE;
} else {
data = flash_data;
offset = addr - FLASHP_BASE;
}
target_verify_block(mc, addr, blocksz/4, (unsigned*) (data + offset));
return 1;
}

void do_erase()
{
atexit(quit);
target = target_open(target_port, target_speed);
if (! target) {
fprintf(stderr, _( " Error detecting device -- check cable!\n " ));
exit(1);
}

if ((target- & gt; adapter- & gt; flags & AD_ERASE) == 0) {
fprintf(stderr, _( " Error: Target erase not supported.\n " ));
exit(1);
}

target_erase(target);
}

void do_program(char *filename)
{
unsigned addr;
int progress_len, progress_step, boot_progress_len;
void *t0;

/* Open and detect the device. */
atexit(quit);
target = target_open(target_port, target_speed);
if (! target) {
fprintf(stderr, _( " Error detecting device -- check cable!\n " ));
exit(1);
}

if ((target- & gt; adapter- & gt; flags & AD_WRITE) == 0) {
fprintf(stderr, _( " Error: Target write not supported.\n " ));
exit(1);
}

flash_bytes = target_flash_bytes(target);
boot_bytes = target_boot_bytes(target);
if (target- & gt; adapter- & gt; block_override != 0) {
blocksz = target- & gt; adapter- & gt; block_override;
} else {
blocksz = target_block_size(target);
}
devcfg_offset = target_devcfg_offset(target);
printf(_( " Processor: %s\n " ), target_cpu_name(target));
printf(_( " Flash memory: %d kbytes\n " ), flash_bytes / 1024);
if (boot_bytes & gt; 0)
printf(_( " Boot memory: %d kbytes\n " ), boot_bytes / 1024);
printf(_( " Data: %d bytes\n " ), total_bytes);

/* Verify DEVCFGx values. */
if (boot_used) {
if (devcfg0 == 0xffffffff) {
fprintf(stderr, _( " DEVCFG values are missing -- check your HEX file!\n " ));
exit(1);
}
if (devcfg_offset == 0xffc0) {
/* For MZ family, clear bits DEVSIGN0[31] and ADEVSIGN0[31]. */
boot_data[0xFFEF] & = 0x7f;
boot_data[0xFF6F] & = 0x7f;
}
}

if (! verify_only) {
/* Erase flash. */
target_erase(target);
}
target_use_executive(target);

/* Compute dirty bits for every block. */
if (flash_used) {
for (addr=0; addr & lt; flash_bytes; addr+=blocksz) {
flash_dirty [addr / blocksz] = is_flash_block_dirty(addr);
}
}
if (boot_used) {
for (addr=0; addr & lt; boot_bytes; addr+=blocksz) {
boot_dirty [addr / blocksz] = is_boot_block_dirty(addr);
}
}

/* Compute length of progress indicator for flash memory. */
for (progress_step=1; ; progress_step & lt; & lt; =1) {
progress_len = 0;
for (addr=0; addr & lt; flash_bytes; addr+=blocksz) {
if (flash_dirty [addr / blocksz])
progress_len++;
}
if (progress_len / progress_step & lt; 64) {
progress_len /= progress_step;
if (progress_len & lt; 1)
progress_len = 1;
break;
}
}

/* Compute length of progress indicator for boot memory. */
boot_progress_len = 1;
for (addr=0; addr & lt; boot_bytes; addr+=blocksz) {
if (boot_dirty [addr / blocksz])
boot_progress_len++;
}

progress_count = 0;
t0 = fix_time();
if (! verify_only) {
if (flash_used) {
printf(_( " Program flash: " ));
print_symbols('.', progress_len);
print_symbols('\b', progress_len);
fflush(stdout);
for (addr=0; addr & lt; flash_bytes; addr+=blocksz) {
if (flash_dirty [addr / blocksz]) {
program_block(target, addr + FLASHV_BASE);
progress(progress_step);
}
}
printf(_( " # done\n " ));
}
if (boot_used) {
printf(_( " Program boot: " ));
print_symbols('.', boot_progress_len);
print_symbols('\b', boot_progress_len);
fflush(stdout);
for (addr=0; addr & lt; boot_bytes; addr+=blocksz) {
if (boot_dirty [addr / blocksz]) {
program_block(target, addr + BOOTV_BASE);
progress(1);
}
}
printf(_( " # done \n " ));
if (! boot_dirty [devcfg_offset / blocksz]) {
/* Write chip configuration. */
target_program_devcfg(target,
devcfg0, devcfg1, devcfg2, devcfg3);
boot_dirty [devcfg_offset / blocksz] = 1;
}
}
}
if (flash_used & & !skip_verify) {
printf(_( " Verify flash: " ));
print_symbols('.', progress_len);
print_symbols('\b', progress_len);
fflush(stdout);
for (addr=0; addr & lt; flash_bytes; addr+=blocksz) {
if (flash_dirty [addr / blocksz]) {
progress(progress_step);
if (! verify_block(target, addr + FLASHV_BASE))
exit(0);
}
}
printf(_( " done\n " ));
}
if (boot_used & & !skip_verify) {
printf(_( " Verify boot: " ));
print_symbols('.', boot_progress_len);
print_symbols('\b', boot_progress_len);
fflush(stdout);
for (addr=0; addr & lt; boot_bytes; addr+=blocksz) {
if (boot_dirty [addr / blocksz]) {
progress(1);
if (! verify_block(target, addr + BOOTV_BASE))
exit(0);
}
}
printf(_( " done \n " ));
}
if (boot_used || flash_used)
printf(_( " Program rate: %ld bytes per second\n " ),
total_bytes * 1000L / mseconds_elapsed(t0));
}

void do_read(char *filename, unsigned base, unsigned nbytes)
{
FILE *fd;
unsigned len, addr, data [256], progress_step;
void *t0;

fd = fopen(filename, " wb " );
if (! fd) {
perror(filename);
exit(1);
}
printf(_( " Memory: total %d bytes\n " ), nbytes);

/* Use 1kbyte blocks. */
blocksz = 1024;

/* Open and detect the device. */
atexit(quit);
target = target_open(target_port, target_speed);
if (! target) {
fprintf(stderr, _( " Error detecting device -- check cable!\n " ));
exit(1);
}

if ((target- & gt; adapter- & gt; flags & AD_READ) == 0) {
fprintf(stderr, _( " Error: Target read not supported.\n " ));
exit(1);
}

target_use_executive(target);
for (progress_step=1; ; progress_step & lt; & lt; =1) {
len = 1 + nbytes / progress_step / blocksz;
if (len & lt; 64)
break;
}
printf( " Read: " );
print_symbols('.', len);
print_symbols('\b', len);
fflush(stdout);

progress_count = 0;
t0 = fix_time();
for (addr=base; addr-base & lt; nbytes; addr+=blocksz) {
progress(progress_step);
target_read_block(target, addr, blocksz/4, data);
if (fwrite(data, 1, blocksz, fd) != blocksz) {
fprintf(stderr, " %s: write error!\n " , filename);
exit(1);
}
}
printf(_( " # done\n " ));
printf(_( " Rate: %ld bytes per second\n " ),
nbytes * 1000L / mseconds_elapsed(t0));
fclose(fd);
}

/*
* Print copying part of license
*/
static void gpl_show_copying(void)
{
printf( " %s.\n\n " , copyright);
printf( " This program is free software; you can redistribute it and/or modify\n " );
printf( " it under the terms of the GNU General Public License as published by\n " );
printf( " the Free Software Foundation; either version 2 of the License, or\n " );
printf( " (at your option) any later version.\n " );
printf( " \n " );
printf( " This program is distributed in the hope that it will be useful,\n " );
printf( " but WITHOUT ANY WARRANTY; without even the implied warranty of\n " );
printf( " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n " );
printf( " GNU General Public License for more details.\n " );
printf( " \n " );
}

/*
* Print NO WARRANTY part of license
*/
static void gpl_show_warranty(void)
{
printf( " %s.\n\n " , copyright);
printf( " BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n " );
printf( " FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n " );
printf( " OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n " );
printf( " PROVIDE THE PROGRAM \ " AS IS\ " WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n " );
printf( " OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n " );
printf( " MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n " );
printf( " TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n " );
printf( " PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n " );
printf( " REPAIR OR CORRECTION.\n " );
printf( " \n " );
printf( " IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n " );
printf( " WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n " );
printf( " REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n " );
printf( " INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n " );
printf( " OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n " );
printf( " TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n " );
printf( " YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n " );
printf( " PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n " );
printf( " POSSIBILITY OF SUCH DAMAGES.\n " );
printf( " \n " );
}

int main(int argc, char **argv)
{
int ch, read_mode = 0;
unsigned base, nbytes;
static const struct option long_options[] = {
{ " help " , 0, 0, 'h' },
{ " warranty " , 0, 0, 'W' },
{ " copying " , 0, 0, 'C' },
{ " version " , 0, 0, 'V' },
{ " skip-verify " , 0, 0, 'S' },
{ NULL, 0, 0, 0 },
};

/* Set locale and message catalogs. */
setlocale(LC_ALL, " " );
#if defined(__CYGWIN32__) || defined(MINGW32)
/* Files with localized messages should be placed in
* the current directory or in c:/Program Files/pic32prog. */
if (access( " ./ru/LC_MESSAGES/pic32prog.mo " , R_OK) == 0)
bindtextdomain( " pic32prog " , " . " );
else
bindtextdomain( " pic32prog " , " c:/Program Files/pic32prog " );
#else
bindtextdomain( " pic32prog " , " /usr/local/share/locale " );
#endif
textdomain( " pic32prog " );

setvbuf(stdout, (char *)NULL, _IOLBF, 0);
setvbuf(stderr, (char *)NULL, _IOLBF, 0);
printf(_( " Programmer for Microchip PIC32 microcontrollers, Version %s\n " ), VERSION);
progname = argv[0];
copyright = _( " Copyright: (C) 2011-2015 Serge Vakulenko " );
signal(SIGINT, interrupted);
#ifdef __linux__
signal(SIGHUP, interrupted);
#endif
signal(SIGTERM, interrupted);

while ((ch = getopt_long(argc, argv, " vDhrpeCVWSd:b:B: " ,
long_options, 0)) != -1) {
switch (ch) {
case 'v':
++verify_only;
continue;
case 'D':
++debug_level;
continue;
case 'r':
++read_mode;
continue;
case 'p':
++power_on;
continue;
case 'e':
++erase_only;
continue;
case 'd':
target_port = optarg;
continue;
case 'b':
target_speed = strtoul(optarg, 0, 0);
if (strncasecmp( " ascii: " , target_port, 6) != 0) // *** HORRIBLE HACK!! ***
if (! serial_speed_valid(target_speed))
return 0;
// If the alternate hasn't changed from default then keep
// it the same as the master speed
if (alternate_speed == 115200) {
alternate_speed = target_speed;
}
continue;
case 'B':
alternate_speed = strtoul(optarg, 0, 0);
if (! serial_speed_valid(alternate_speed)) {
printf( " Debug: %d\n " , alternate_speed);
return 0;
}
continue;
case 'h':
break;
case 'V':
/* Version already printed above. */
return 0;
case 'C':
gpl_show_copying();
return 0;
case 'W':
gpl_show_warranty();
return 0;
case 'S':
++skip_verify;
continue;
}
usage:
printf( " %s.\n\n " , copyright);
printf( " PIC32prog comes with ABSOLUTELY NO WARRANTY; for details\n " );
printf( " use `--warranty' option. This is Open Source software. You are\n " );
printf( " welcome to redistribute it under certain conditions. Use the\n " );
printf( " '--copying' option for details.\n\n " );
printf( " Probe:\n " );
printf( " pic32prog\n " );
printf( " \nWrite flash memory:\n " );
printf( " pic32prog [-v] file.srec\n " );
printf( " pic32prog [-v] file.hex\n " );
printf( " \nRead memory:\n " );
printf( " pic32prog -r file.bin address length\n " );
printf( " \nArgs:\n " );
printf( " file.srec Code file in SREC format\n " );
printf( " file.hex Code file in Intel HEX format\n " );
printf( " file.bin Code file in binary format\n " );
printf( " -v Verify only\n " );
printf( " -r Read mode\n " );
printf( " -d device Use specified serial or USB device\n " );
printf( " -b baudrate Serial speed, default 115200\n " );
printf( " -B alt_baud Request an alternative baud rate\n " );
printf( " -e Erase chip\n " );
printf( " -p Leave board powered on\n " );
printf( " -D Debug mode\n " );
printf( " -h, --help Print this help message\n " );
printf( " -V, --version Print version\n " );
printf( " -C, --copying Print copying information\n " );
printf( " -W, --warranty Print warranty information\n " );
printf( " -S, --skip-verify Skip the write verification step\n " );
printf( " \n " );
return 0;
}
printf( " %s\n " , copyright);
argc -= optind;
argv += optind;

memset(boot_data, ~0, BOOT_BYTES);
memset(flash_data, ~0, FLASH_BYTES);

switch (argc) {
case 0:
if (erase_only & gt; 0) {
do_erase();
} else {
do_probe();
}
break;
case 1:
if (! read_srec(argv[0]) & &
! read_hex(argv[0])) {
fprintf(stderr, _( " %s: bad file format\n " ), argv[0]);
exit(1);
}
do_program(argv[0]);
break;
case 3:
if (! read_mode)
goto usage;
base = strtoul(argv[1], 0, 0);
nbytes = strtoul(argv[2], 0, 0);
do_read(argv[0], base, nbytes);
break;
default:
goto usage;
}
quit();
return 0;
}


pic32prog-201612.zip > family-mx3.c

/*
* Routines specific for PIC32 MX3/4/5/6/7 family.
*
* Copyright (C) 2013 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include " pic32.h "

/*
* Print configuration for MX3/4/5/6/7 family.
*/
void print_mx3(unsigned cfg0, unsigned cfg1, unsigned cfg2, unsigned cfg3)
{
/*--------------------------------------
* Configuration register 0
*/
printf( " DEVCFG0 = %08x\n " , cfg0);
if ((~cfg0 & MX3_CFG0_DEBUG_MASK) == MX3_CFG0_DEBUG_ENABLED)
printf( " %u Debugger enabled\n " ,
cfg0 & MX3_CFG0_DEBUG_MASK);
else
printf( " %u Debugger disabled\n " ,
cfg0 & MX3_CFG0_DEBUG_MASK);

if (~cfg0 & MX3_CFG0_JTAG_DISABLE)
printf( " %u JTAG disabled\n " ,
cfg0 & MX3_CFG0_JTAG_DISABLE);

switch (~cfg0 & MX3_CFG0_ICESEL_MASK) {
case MX3_CFG0_ICESEL_PAIR1:
printf( " %02x Use PGC1/PGD1\n " , cfg0 & MX3_CFG0_ICESEL_MASK);
break;
case MX3_CFG0_ICESEL_PAIR2:
printf( " %02x Use PGC2/PGD2\n " , cfg0 & MX3_CFG0_ICESEL_MASK);
break;
case MX3_CFG0_ICESEL_PAIR3:
printf( " %02x Use PGC3/PGD3\n " , cfg0 & MX3_CFG0_ICESEL_MASK);
break;
case MX3_CFG0_ICESEL_PAIR4:
printf( " %02x Use PGC4/PGD4\n " , cfg0 & MX3_CFG0_ICESEL_MASK);
break;
}

if (~cfg0 & MX3_CFG0_PWP_MASK)
printf( " %05x Program flash write protect\n " ,
cfg0 & MX3_CFG0_PWP_MASK);

if (~cfg0 & MX3_CFG0_BWP)
printf( " Boot flash write protect\n " );
if (~cfg0 & MX3_CFG0_CP)
printf( " Code protect\n " );

/*--------------------------------------
* Configuration register 1
*/
printf( " DEVCFG1 = %08x\n " , cfg1);
switch (cfg1 & MX3_CFG1_FNOSC_MASK) {
case MX3_CFG1_FNOSC_FRC:
printf( " %u Fast RC oscillator\n " , MX3_CFG1_FNOSC_FRC);
break;
case MX3_CFG1_FNOSC_FRCDIVPLL:
printf( " %u Fast RC oscillator with divide-by-N and PLL\n " , MX3_CFG1_FNOSC_FRCDIVPLL);
break;
case MX3_CFG1_FNOSC_PRI:
printf( " %u Primary oscillator\n " , MX3_CFG1_FNOSC_PRI);
break;
case MX3_CFG1_FNOSC_PRIPLL:
printf( " %u Primary oscillator with PLL\n " , MX3_CFG1_FNOSC_PRIPLL);
break;
case MX3_CFG1_FNOSC_SEC:
printf( " %u Secondary oscillator\n " , MX3_CFG1_FNOSC_SEC);
break;
case MX3_CFG1_FNOSC_LPRC:
printf( " %u Low-power RC oscillator\n " , MX3_CFG1_FNOSC_LPRC);
break;
case MX3_CFG1_FNOSC_FRCDIV16:
printf( " %u Fast RC oscillator with divide-by-16\n " , MX3_CFG1_FNOSC_FRCDIV16);
break;
case MX3_CFG1_FNOSC_FRCDIV:
printf( " %u Fast RC oscillator with divide-by-N\n " , MX3_CFG1_FNOSC_FRCDIV);
break;
default:
printf( " %u UNKNOWN\n " , cfg1 & MX3_CFG1_FNOSC_MASK);
break;
}
if (cfg1 & MX3_CFG1_FSOSCEN)
printf( " %u Secondary oscillator enabled\n " ,
MX3_CFG1_FSOSCEN & gt; & gt; 4);
if (cfg1 & MX3_CFG1_IESO)
printf( " %u Internal-external switch over enabled\n " ,
MX3_CFG1_IESO & gt; & gt; 4);

switch (cfg1 & MX3_CFG1_POSCMOD_MASK) {
case MX3_CFG1_POSCMOD_EXT:
printf( " %u Primary oscillator: External\n " , MX3_CFG1_POSCMOD_EXT & gt; & gt; 8);
break;
case MX3_CFG1_POSCMOD_XT:
printf( " %u Primary oscillator: XT\n " , MX3_CFG1_POSCMOD_XT & gt; & gt; 8);
break;
case MX3_CFG1_POSCMOD_HS:
printf( " %u Primary oscillator: HS\n " , MX3_CFG1_POSCMOD_HS & gt; & gt; 8);
break;
case MX3_CFG1_POSCMOD_DISABLE:
printf( " %u Primary oscillator: disabled\n " , MX3_CFG1_POSCMOD_DISABLE & gt; & gt; 8);
break;
}
if (cfg1 & MX3_CFG1_CLKO_DISABLE)
printf( " %u CLKO output disabled\n " ,
MX3_CFG1_CLKO_DISABLE & gt; & gt; 8);

switch (cfg1 & MX3_CFG1_FPBDIV_MASK) {
case MX3_CFG1_FPBDIV_1:
printf( " %u Peripheral bus clock: SYSCLK / 1\n " , MX3_CFG1_FPBDIV_1 & gt; & gt; 12);
break;
case MX3_CFG1_FPBDIV_2:
printf( " %u Peripheral bus clock: SYSCLK / 2\n " , MX3_CFG1_FPBDIV_2 & gt; & gt; 12);
break;
case MX3_CFG1_FPBDIV_4:
printf( " %u Peripheral bus clock: SYSCLK / 4\n " , MX3_CFG1_FPBDIV_4 & gt; & gt; 12);
break;
case MX3_CFG1_FPBDIV_8:
printf( " %u Peripheral bus clock: SYSCLK / 8\n " , MX3_CFG1_FPBDIV_8 & gt; & gt; 12);
break;
}
if (cfg1 & MX3_CFG1_FCKM_DISABLE)
printf( " %u Fail-safe clock monitor disable\n " ,
MX3_CFG1_FCKM_DISABLE & gt; & gt; 12);
if (cfg1 & MX3_CFG1_FCKS_DISABLE)
printf( " %u Clock switching disable\n " ,
MX3_CFG1_FCKS_DISABLE & gt; & gt; 12);

switch (cfg1 & MX3_CFG1_WDTPS_MASK) {
case MX3_CFG1_WDTPS_1:
printf( " %2x Watchdog postscale: 1/1\n " , MX3_CFG1_WDTPS_1 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_2:
printf( " %2x Watchdog postscale: 1/2\n " , MX3_CFG1_WDTPS_2 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_4:
printf( " %2x Watchdog postscale: 1/4\n " , MX3_CFG1_WDTPS_4 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_8:
printf( " %2x Watchdog postscale: 1/8\n " , MX3_CFG1_WDTPS_8 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_16:
printf( " %2x Watchdog postscale: 1/16\n " , MX3_CFG1_WDTPS_16 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_32:
printf( " %2x Watchdog postscale: 1/32\n " , MX3_CFG1_WDTPS_32 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_64:
printf( " %2x Watchdog postscale: 1/64\n " , MX3_CFG1_WDTPS_64 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_128:
printf( " %2x Watchdog postscale: 1/128\n " , MX3_CFG1_WDTPS_128 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_256:
printf( " %2x Watchdog postscale: 1/256\n " , MX3_CFG1_WDTPS_256 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_512:
printf( " %2x Watchdog postscale: 1/512\n " , MX3_CFG1_WDTPS_512 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_1024:
printf( " %2x Watchdog postscale: 1/1024\n " , MX3_CFG1_WDTPS_1024 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_2048:
printf ( " %2x Watchdog postscale: 1/2048\n " , MX3_CFG1_WDTPS_2048 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_4096:
printf ( " %2x Watchdog postscale: 1/4096\n " , MX3_CFG1_WDTPS_4096 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_8192:
printf( " %2x Watchdog postscale: 1/8192\n " , MX3_CFG1_WDTPS_8192 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_16384:
printf( " %2x Watchdog postscale: 1/16384\n " , MX3_CFG1_WDTPS_16384 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_32768:
printf( " %2x Watchdog postscale: 1/32768\n " , MX3_CFG1_WDTPS_32768 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_65536:
printf( " %2x Watchdog postscale: 1/65536\n " , MX3_CFG1_WDTPS_65536 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_131072:
printf( " %2x Watchdog postscale: 1/131072\n " , MX3_CFG1_WDTPS_131072 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_262144:
printf( " %2x Watchdog postscale: 1/262144\n " , MX3_CFG1_WDTPS_262144 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_524288:
printf( " %2x Watchdog postscale: 1/524288\n " , MX3_CFG1_WDTPS_524288 & gt; & gt; 16);
break;
case MX3_CFG1_WDTPS_1048576:
printf( " %2x Watchdog postscale: 1/1048576\n " , MX3_CFG1_WDTPS_1048576 & gt; & gt; 16);
break;
}
if (cfg1 & MX3_CFG1_FWDTEN)
printf( " %u Watchdog enable\n " ,
MX3_CFG1_FWDTEN & gt; & gt; 20);

/*--------------------------------------
* Configuration register 2
*/
printf( " DEVCFG2 = %08x\n " , cfg2);
switch (cfg2 & MX3_CFG2_FPLLIDIV_MASK) {
case MX3_CFG2_FPLLIDIV_1:
printf( " %u PLL divider: 1/1\n " , MX3_CFG2_FPLLIDIV_1);
break;
case MX3_CFG2_FPLLIDIV_2:
printf( " %u PLL divider: 1/2\n " , MX3_CFG2_FPLLIDIV_2);
break;
case MX3_CFG2_FPLLIDIV_3:
printf( " %u PLL divider: 1/3\n " , MX3_CFG2_FPLLIDIV_3);
break;
case MX3_CFG2_FPLLIDIV_4:
printf( " %u PLL divider: 1/4\n " , MX3_CFG2_FPLLIDIV_4);
break;
case MX3_CFG2_FPLLIDIV_5:
printf( " %u PLL divider: 1/5\n " , MX3_CFG2_FPLLIDIV_5);
break;
case MX3_CFG2_FPLLIDIV_6:
printf( " %u PLL divider: 1/6\n " , MX3_CFG2_FPLLIDIV_6);
break;
case MX3_CFG2_FPLLIDIV_10:
printf( " %u PLL divider: 1/10\n " , MX3_CFG2_FPLLIDIV_10);
break;
case MX3_CFG2_FPLLIDIV_12:
printf( " %u PLL divider: 1/12\n " , MX3_CFG2_FPLLIDIV_12);
break;
}
switch (cfg2 & MX3_CFG2_FPLLMUL_MASK) {
case MX3_CFG2_FPLLMUL_15:
printf( " %u PLL multiplier: 15x\n " , MX3_CFG2_FPLLMUL_15 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_16:
printf( " %u PLL multiplier: 16x\n " , MX3_CFG2_FPLLMUL_16 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_17:
printf( " %u PLL multiplier: 17x\n " , MX3_CFG2_FPLLMUL_17 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_18:
printf( " %u PLL multiplier: 18x\n " , MX3_CFG2_FPLLMUL_18 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_19:
printf( " %u PLL multiplier: 19x\n " , MX3_CFG2_FPLLMUL_19 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_20:
printf( " %u PLL multiplier: 20x\n " , MX3_CFG2_FPLLMUL_20 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_21:
printf( " %u PLL multiplier: 21x\n " , MX3_CFG2_FPLLMUL_21 & gt; & gt; 4);
break;
case MX3_CFG2_FPLLMUL_24:
printf( " %u PLL multiplier: 24x\n " , MX3_CFG2_FPLLMUL_24 & gt; & gt; 4);
break;
}
switch (cfg2 & MX3_CFG2_UPLLIDIV_MASK) {
case MX3_CFG2_UPLLIDIV_1:
printf( " %u USB PLL divider: 1/1\n " , MX3_CFG2_UPLLIDIV_1 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_2:
printf( " %u USB PLL divider: 1/2\n " , MX3_CFG2_UPLLIDIV_2 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_3:
printf( " %u USB PLL divider: 1/3\n " , MX3_CFG2_UPLLIDIV_3 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_4:
printf( " %u USB PLL divider: 1/4\n " , MX3_CFG2_UPLLIDIV_4 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_5:
printf( " %u USB PLL divider: 1/5\n " , MX3_CFG2_UPLLIDIV_5 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_6:
printf( " %u USB PLL divider: 1/6\n " , MX3_CFG2_UPLLIDIV_6 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_10:
printf( " %u USB PLL divider: 1/10\n " , MX3_CFG2_UPLLIDIV_10 & gt; & gt; 8);
break;
case MX3_CFG2_UPLLIDIV_12:
printf( " %u USB PLL divider: 1/12\n " , MX3_CFG2_UPLLIDIV_12 & gt; & gt; 8);
break;
}
if (cfg2 & MX3_CFG2_UPLL_DISABLE)
printf( " %u Disable USB PLL\n " ,
MX3_CFG2_UPLL_DISABLE & gt; & gt; 12);
else
printf( " Enable USB PLL\n " );

switch (cfg2 & MX3_CFG2_FPLLODIV_MASK) {
case MX3_CFG2_FPLLODIV_1:
printf( " %u PLL postscaler: 1/1\n " , MX3_CFG2_FPLLODIV_1 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_2:
printf( " %u PLL postscaler: 1/2\n " , MX3_CFG2_FPLLODIV_2 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_4:
printf( " %u PLL postscaler: 1/4\n " , MX3_CFG2_FPLLODIV_4 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_8:
printf( " %u PLL postscaler: 1/8\n " , MX3_CFG2_FPLLODIV_8 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_16:
printf( " %u PLL postscaler: 1/16\n " , MX3_CFG2_FPLLODIV_16 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_32:
printf( " %u PLL postscaler: 1/32\n " , MX3_CFG2_FPLLODIV_32 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_64:
printf( " %u PLL postscaler: 1/64\n " , MX3_CFG2_FPLLODIV_64 & gt; & gt; 16);
break;
case MX3_CFG2_FPLLODIV_256:
printf( " %u PLL postscaler: 1/128\n " , MX3_CFG2_FPLLODIV_256 & gt; & gt; 16);
break;
}

/*--------------------------------------
* Configuration register 3
*/
printf( " DEVCFG3 = %08x\n " , cfg3);
if (~cfg3 & MX3_CFG3_USERID_MASK)
printf( " %04x User-defined ID\n " ,
cfg3 & MX3_CFG3_USERID_MASK);

switch (cfg3 & MX3_CFG3_FSRSSEL_MASK) {
case MX3_CFG3_FSRSSEL_ALL:
printf( " %u All irqs assigned to shadow set\n " , MX3_CFG3_FSRSSEL_ALL & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_1:
printf( " %u Assign irq priority 1 to shadow set\n " , MX3_CFG3_FSRSSEL_1 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_2:
printf( " %u Assign irq priority 2 to shadow set\n " , MX3_CFG3_FSRSSEL_2 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_3:
printf( " %u Assign irq priority 3 to shadow set\n " , MX3_CFG3_FSRSSEL_3 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_4:
printf( " %u Assign irq priority 4 to shadow set\n " , MX3_CFG3_FSRSSEL_4 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_5:
printf( " %u Assign irq priority 5 to shadow set\n " , MX3_CFG3_FSRSSEL_5 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_6:
printf( " %u Assign irq priority 6 to shadow set\n " , MX3_CFG3_FSRSSEL_6 & gt; & gt; 16);
break;
case MX3_CFG3_FSRSSEL_7:
printf( " %u Assign irq priority 7 to shadow set\n " , MX3_CFG3_FSRSSEL_7 & gt; & gt; 16);
break;
}
if (cfg3 & MX3_CFG3_FMIIEN)
printf( " %u Ethernet MII enabled\n " ,
MX3_CFG3_FMIIEN & gt; & gt; 24);
else
printf( " Ethernet RMII enabled\n " );

if (cfg3 & MX3_CFG3_FETHIO)
printf( " %u Default Ethernet i/o pins\n " ,
MX3_CFG3_FETHIO & gt; & gt; 24);
else
printf( " Alternate Ethernet i/o pins\n " );

if (cfg3 & MX3_CFG3_FCANIO)
printf( " %u Default CAN i/o pins\n " ,
MX3_CFG3_FCANIO & gt; & gt; 24);
else
printf( " Alternate CAN i/o pins\n " );

if (cfg3 & MX3_CFG3_FUSBIDIO)
printf( " %u USBID pin: controlled by USB\n " ,
MX3_CFG3_FUSBIDIO & gt; & gt; 28);
else
printf( " USBID pin: controlled by port\n " );

if (cfg3 & MX3_CFG3_FVBUSONIO)
printf( " %u VBuson pin: controlled by USB\n " ,
MX3_CFG3_FVBUSONIO & gt; & gt; 28);
else
printf( " VBuson pin: controlled by port\n " );
}


pic32prog-201612.zip > adapter-uhb.c

/*
* Interface to mikroE USB HID Bootloader (UHB).
*
* Copyright (C) 2014 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include & lt; stdlib.h & gt;
#include & lt; unistd.h & gt;
#include & lt; fcntl.h & gt;
#include & lt; string.h & gt;
#include & lt; errno.h & gt;

#include " adapter.h "
#include " hidapi.h "
#include " pic32.h "

/* Bootloader commands */
#define CMD_NON 0 /* 'Idle' */
#define CMD_SYNC 1 /* Synchronize with PC tool */
#define CMD_INFO 2 /* Send bootloader info record */
#define CMD_BOOT 3 /* Go to bootloader mode */
#define CMD_REBOOT 4 /* Restart MCU */
#define CMD_WRITE 11 /* Write to MCU flash */
#define CMD_ERASE 21 /* Erase MCU flash */

#define STX 15 /* Start of TeXt */

typedef struct {
/* Common part */
adapter_t adapter;

/* Device handle for libusb. */
hid_device *hiddev;

unsigned flash_size;
unsigned erase_size;
unsigned write_size;
unsigned version;
unsigned boot_start;
unsigned boot_erased;
char name [32];

unsigned char reply [64];

} uhb_adapter_t;

/*
* Identifiers of USB adapter.
*/
#define MIKROE_VID 0x1234
#define MIKROEBOOT_PID 0x0001 /* MikroElektronika HID bootloader */

/*
* Send a request to the device.
* Store the reply into the a- & gt; reply[] array.
*/
static void uhb_command(uhb_adapter_t *a, unsigned char cmd,
unsigned addr, unsigned count, unsigned char *data, unsigned data_bytes)
{
unsigned char buf [64];
unsigned k, nbytes = 2;
int reply_len;

/* Send command packet. */
memset(buf, 0, sizeof(buf));
buf[0] = STX;
buf[1] = cmd;
if (cmd == CMD_WRITE || cmd == CMD_ERASE) {
/*
* Write and Erase command format:
*
* & lt; STX & gt; & lt; CMD & gt; & lt; Address[0..3] & gt; & lt; Count[0..1] & gt;
* |- 1 -|- 1 -|------ 4 ------|----- 2 -----|
*/
buf[2] = addr;
buf[3] = addr & gt; & gt; 8;
buf[4] = addr & gt; & gt; 16;
buf[5] = addr & gt; & gt; 24;
buf[6] = count;
buf[7] = count & gt; & gt; 8;
nbytes += 6;
}

if (debug_level & gt; 0) {
fprintf(stderr, " ---Send " );
for (k=0; k & lt; nbytes; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , buf[k]);
}
fprintf(stderr, " \n " );
}
hid_write(a- & gt; hiddev, buf, 64);

if (cmd == CMD_REBOOT) {
/* No reply expected. */
return;
}

if (cmd == CMD_WRITE) {
/* Send data. */
for (; data_bytes & gt; 0; data_bytes-=64) {
if (debug_level & gt; 0) {
fprintf(stderr, " --- " );
for (k=0; k & lt; 64; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , data[k]);
}
fprintf(stderr, " \n " );
}
hid_write(a- & gt; hiddev, data, 64);
data += 64;
}
}

/* Get reply. */
memset(a- & gt; reply, 0, sizeof(a- & gt; reply));
reply_len = hid_read_timeout(a- & gt; hiddev, a- & gt; reply, 64, 500);
if (reply_len == 0) {
fprintf(stderr, " Timed out.\n " );
exit(-1);
}
if (reply_len != 64) {
fprintf(stderr, " uhb: error %d receiving packet\n " , reply_len);
exit(-1);
}
if (debug_level & gt; 0) {
fprintf(stderr, " ---Recv " );
for (k=0; k & lt; 2; ++k) {
if (k != 0 & & (k & 15) == 0)
fprintf(stderr, " \n " );
fprintf(stderr, " %02x " , a- & gt; reply[k]);
}
fprintf(stderr, " \n " );
}
}

static void uhb_close(adapter_t *adapter, int power_on)
{
uhb_adapter_t *a = (uhb_adapter_t*) adapter;

/* Jump to application. */
uhb_command(a, CMD_REBOOT, 0, 0, 0, 0);
free(a);
}

/*
* Return the Device Identification code
*/
static unsigned uhb_get_idcode(adapter_t *adapter)
{
return 0xDEAFB00B;
}

/*
* Read a configuration word from memory.
*/
static unsigned uhb_read_word(adapter_t *adapter, unsigned addr)
{
/* Not supported by UHB bootloader. */
return 0;
}

/*
* Write a configuration word to flash memory.
*/
static void uhb_program_word(adapter_t *adapter,
unsigned addr, unsigned word)
{
/* Not supported by UHB bootloader. */
if (debug_level & gt; 0)
fprintf(stderr, " uhb: program word at %08x: %08x\n " , addr, word);
}

/*
* Verify a block of memory (1024 bytes).
*/
static void uhb_verify_data(adapter_t *adapter,
unsigned addr, unsigned nwords, unsigned *data)
{
/* Not supported by UHB bootloader. */
}

/*
* Flash write, 1-kbyte blocks.
*/
static void uhb_program_block(adapter_t *adapter,
unsigned addr, unsigned *data)
{
uhb_adapter_t *a = (uhb_adapter_t*) adapter;

if (debug_level & gt; 0)
fprintf(stderr, " uhb: program 1024 bytes at %08x: %08x-%08x-...-%08x\n " ,
addr, data[0], data[1], data[255]);

if (! (addr & gt; = a- & gt; adapter.user_start & &
addr + 1024 & lt; = a- & gt; adapter.user_start + a- & gt; adapter.user_nbytes) & &
! (addr & gt; = 0x1fc00000 & &
addr + 1024 & lt; = 0x1fc00000 + 8*1024)) {
fprintf(stderr, " address %08x out of program area\n " , addr);
return;
}

if (addr & gt; = 0x1fc00000 & &
addr + 1024 & lt; = 0x1fc00000 + 8*1024 & &
! a- & gt; boot_erased)
{
/* Erase boot area. */
unsigned nblocks = 8*1024 / a- & gt; erase_size;
unsigned ba = 0x1fc00000;
for (; nblocks-- & gt; 0; addr += a- & gt; erase_size) {
if (debug_level & gt; 0)
fprintf(stderr, " *** uhb: erase boot block %08x\n " , ba);

/* Erase one block. */
uhb_command(a, CMD_ERASE, ba, 1, 0, 0);
}
a- & gt; boot_erased = 1;
}

uhb_command(a, CMD_WRITE, addr, 1024, (unsigned char*)data, 1024);
}

/*
* Erase all flash memory.
*/
static void uhb_erase_chip(adapter_t *adapter)
{
uhb_adapter_t *a = (uhb_adapter_t*) adapter;
int nblocks;
unsigned addr;

/* Erase user flash memory. */
nblocks = a- & gt; adapter.user_nbytes / a- & gt; erase_size;
for (addr = a- & gt; adapter.user_start; nblocks-- & gt; 0; addr += a- & gt; erase_size) {
if (debug_level & gt; 0)
fprintf(stderr, " *** uhb: erase flash block %08x\n " , addr);

/* Erase one block. */
uhb_command(a, CMD_ERASE, addr, 1, 0, 0);
}
}

/*
* Initialize adapter uhb.
* Return a pointer to a data structure, allocated dynamically.
* When adapter not found, return 0.
*/
adapter_t *adapter_open_uhb(int vid, int pid, const char *serial)
{
uhb_adapter_t *a;
hid_device *hiddev;

if (vid) {
wchar_t buf[256];
if (serial)
mbstowcs(buf, serial, 256);
hiddev = hid_open(vid, pid, serial ? buf : 0);
} else
hiddev = hid_open(MIKROE_VID, MIKROEBOOT_PID, 0);

if (! hiddev) {
if (vid)
fprintf(stderr, " UHB bootloader not found: vid=%04x, pid=%04x, serial=%s\n " ,
vid, pid, serial ? : " (none) " );
return 0;
}
a = calloc(1, sizeof(*a));
if (! a) {
fprintf(stderr, " Out of memory\n " );
return 0;
}
a- & gt; hiddev = hiddev;

/* Read version of adapter. */
uhb_command(a, CMD_INFO, 0, 0, 0, 0);
if (a- & gt; reply[0] != 56 || /* Info packet size */
a- & gt; reply[1] != 1 || /* Tag: MCU type */
a- & gt; reply[2] != 20 || /* PIC32 family */
a- & gt; reply[4] != 8 || /* Tag: flash size */
a- & gt; reply[12] != 3 || /* Tag: erase block size */
a- & gt; reply[16] != 4 || /* Tag: write block size */
a- & gt; reply[20] != 5 || /* Tag: version of bootloader */
a- & gt; reply[24] != 6 || /* Tag: bootloader start address */
a- & gt; reply[32] != 7) /* Tag: board name */
return 0;

a- & gt; flash_size = a- & gt; reply[8] | (a- & gt; reply[9] & lt; & lt; 8) |
(a- & gt; reply[10] & lt; & lt; 16) | (a- & gt; reply[11] & lt; & lt; 24);
a- & gt; erase_size = a- & gt; reply[14] | (a- & gt; reply[15] & lt; & lt; 8);
a- & gt; write_size = a- & gt; reply[18] | (a- & gt; reply[19] & lt; & lt; 8);
a- & gt; version = a- & gt; reply[22] | (a- & gt; reply[23] & lt; & lt; 8);
a- & gt; boot_start = a- & gt; reply[28] | (a- & gt; reply[29] & lt; & lt; 8) |
(a- & gt; reply[30] & lt; & lt; 16) | (a- & gt; reply[31] & lt; & lt; 24);
memcpy(a- & gt; name, & a- & gt; reply[33], 31);

a- & gt; adapter.user_start = 0x1d000000;
a- & gt; adapter.user_nbytes = a- & gt; boot_start & 0x00ffffff;
a- & gt; adapter.boot_nbytes = 12*1024 - a- & gt; erase_size;
printf( " Adapter: UHB Bootloader '%s', Version %x.%02x\n " ,
a- & gt; name, a- & gt; version & gt; & gt; 8, a- & gt; version & 0xff);
printf( " Program area: %08x-%08x, %08x-%08x\n " , a- & gt; adapter.user_start,
a- & gt; adapter.user_start + a- & gt; adapter.user_nbytes - 1,
0x1fc00000, 0x1fc00000+ a- & gt; adapter.boot_nbytes - 1);

if (debug_level & gt; 0) {
printf( " Flash size: %u bytes\n " , a- & gt; flash_size);
printf( " Write block: %u bytes\n " , a- & gt; write_size);
printf( " Erase block: %u bytes\n " , a- & gt; erase_size);
printf( " Boot start: %08x\n " , a- & gt; boot_start);
}

/* Enter Bootloader mode. */
uhb_command(a, CMD_BOOT, 0, 0, 0, 0);
if (a- & gt; reply[0] != STX || a- & gt; reply[1] != CMD_BOOT) {
fprintf(stderr, " uhb: Cannot enter bootloader mode.\n " );
return 0;
}

a- & gt; adapter.block_override = 0;
a- & gt; adapter.flags = (AD_PROBE | AD_ERASE | AD_READ | AD_WRITE);

/* User functions. */
a- & gt; adapter.close = uhb_close;
a- & gt; adapter.get_idcode = uhb_get_idcode;
a- & gt; adapter.read_word = uhb_read_word;
a- & gt; adapter.verify_data = uhb_verify_data;
a- & gt; adapter.erase_chip = uhb_erase_chip;
a- & gt; adapter.program_block = uhb_program_block;
a- & gt; adapter.program_word = uhb_program_word;
return & a- & gt; adapter;
}


pic32prog-201612.zip > serial.h

/*
* Interface to serial port.
*
* Copyright (C) 2015 Serge Vakulenko
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/

#ifndef _SERIAL_H
#define _SERIAL_H

/*
* Open the serial port with the specified baud rate and
* receive timeout (in milliseconds).
* Return -1 on error.
*/
int serial_open(const char *devname, int baud_rate);

/*
* Change the serial baud rate
* Return -1 on error.
*/
int serial_baud(int baud_rate);

/*
* Close the serial port.
*/
void serial_close(void);

/*
* Send data to device.
* Return number of bytes, or -1 on error.
*/
int serial_write(unsigned char *data, int len);

/*
* Receive data from device.
* Return number of bytes, or -1 on error.
*/
int serial_read(unsigned char *data, int len, int timeout_msec);

/*
* Check whether the given speed in bits per second
* is supported by the system.
* Return 0 when not supported.
*/
int serial_speed_valid(int bps);

#endif


pic32prog-201612.zip > adapter-bitbang.c

// last edited: Sunday, 30 August, 2015 (release 3)

/*
* Interface to PIC32 ICSP port using bitbang adapter.
* Copyright (C) 2014 Serge Vakulenko
*
* Additions for talking to ascii ICSP programmer Copyright (C) 2015 Robert Rozee
*
* This file is part of PIC32PROG project, which is distributed
* under the terms of the GNU General Public License (GPL).
* See the accompanying file " COPYING " for more details.
*/
#include & lt; stdio.h & gt;
#include & lt; stdlib.h & gt;
#include & lt; unistd.h & gt;
#include & lt; string.h & gt;
#include & lt; sys/time.h & gt;
#include " adapter.h "
#include " pic32.h "
#include " serial.h "

typedef struct {
adapter_t adapter; /* Common part */

int BitsToRead; // number of 'bits' waiting in Rx buffer
int CharToRead; // number of characters the bits are encoded into
int PendingHandshake; // indicates a return handshake is expected

unsigned TotalCodeChrsSent; // count of total # of code characters sent out
unsigned TotalCodeChrsRecv; // count of total # of code characters received
unsigned TotalBitPairsSent; // count of total # of TDI and TMS pairs sent
unsigned TotalBitsReceived; // count of total # of TDO bits recieved
unsigned MaxBufferedWrites; // max continuous characters written before read
unsigned RunningWriteCount; // running count of characters written, reset by read
unsigned WriteCount; // number of calls to serial_write
unsigned Read1Count; // number of calls to serial_read (data)
unsigned Read2Count; // number of calls to serial_read (handshakes)
unsigned FDataCount; // number of calls to xfer_fastdata
unsigned DelayCount[4]; // number of calls to delay10mS (erase, xfer inst, PE resp, other)
struct timeval T1, T2; // record start and finishing timestamps

unsigned use_executive;
unsigned serial_execution_mode;
} bitbang_adapter_t;

static int DBG1 = 0; // add format characters to command strings, print out
static int DBG2 = 0; // print messages at entry to main routines
static int DBG3 = 0; // print our row program parameters
static int CFG1 = 2; // 1/2 configure for 64/1024 byte buffer in programming adapter
static int CFG2 = 1; // 1/2 config to retrieve PrAcc and alert if (PrAcc != 1)
// (note: option 2 doubles programming time)
static int CFG3 = 1; // 0 = uncompressed stream (use only 'd','e','f','g'
// 1 = use 4-bit packing (on data only) 'i'-'x','I'-'X','a','z','A'
static int CFG4 = 1; // decompression method in serial read (normally set to match CFG3)
static int MAXW = 440; // maximum continuous write before sync: 900 + 50 & lt; 1024, 440 + 30 & lt; 512

/*
* Calculate checksum.
*/
static unsigned calculate_crc(unsigned crc, unsigned char *data, unsigned nbytes)
{
static const unsigned short crc_table [16] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
};
unsigned i;

while (nbytes--) {
i = (crc & gt; & gt; 12) ^ (*data & gt; & gt; 4);
crc = crc_table[i & 0x0F] ^ (crc & lt; & lt; 4);
i = (crc & gt; & gt; 12) ^ (*data & gt; & gt; 0);
crc = crc_table[i & 0x0F] ^ (crc & lt; & lt; 4);
data++;
}
return crc & 0xffff;
}

/*
* Sends a command ('8')to the programmer telling it to insert
* a 10mS delay in the datastream being sent to the target. This
* is the only reliable way to create a delay at the target.
* (by RR)
*/
static void bitbang_delay10mS(bitbang_adapter_t *a, int caller)
{
unsigned char ch;

ch = '8';
serial_write( & ch, 1);
a- & gt; WriteCount++;
a- & gt; DelayCount[caller]++;
}

/*
* Current version of bitbang_send, sends a string of data out to the target encoded
* as ASCII characters to be interpreted by an intellenent ICSP programmer.
*
* NOTE: this version of pic32prog implements the 2-wire communications mode via the
* ICSP port. This means we need to encode TDI, TMS, and read_flag into one character,
* sending all three out at once to an Arduino NANO acting as an intelligent programmer.
* If read_flag is set, then the programmer needs to respond with a series of characters
* indicating the values of TDO that the target responds with.
*
* Below is the currently implemented command set:
*
* 'd' : TDI = 0, TMS = 0, read_flag = 0 0x64
* 'e' : TDI = 0, TMS = 1, read_flag = 0
* 'f' : TDI = 1, TMS = 0, read_flag = 0
* 'g' : TDI = 1, TMS = 1, read_flag = 0
*
* 'a' : data header
* 'z' : data footer
* 'i'..'x' : 4 TDI bits encoded, TMS = 0, read_flag = 0
*
* 'D' : TDI = 0, TMS = 0, read_flag = 1 0x44
* 'E' : TDI = 0, TMS = 1, read_flag = 1
* 'F' : TDI = 1, TMS = 0, read_flag = 1
* 'G' : TDI = 1, TMS = 1, read_flag = 1
*
* 'A' : data header with read_flag = 1 on last bit
* 'I'..'X' : 4 TDI bits encoded, TMS = 0, read_flag = 1
*
* '.' : no operation, used for formatting
* ' & gt; ' : request sync response - ' & lt; '
*
* '0' : clock out a 0 on PGD pin
* '1' : clock out a 1 on PGD pin
* '2' : set MCLR low
* '3' : set MCLR high
* '4' : turn target power off
* '5' : turn target power on
* '8' : insert 10mS delay
* '?' : return ID string, " ascii JTAG XN "
*
* if the request is 'D'..'G', then respond with '0'/'1' to indicate TDO = 0/1
* if the request is 'I'..'X', then respond with 'I'..'X' encoding 4 TDO bits
*
* (by RR)
*/
static void bitbang_send(bitbang_adapter_t *a,
unsigned tms_nbits, unsigned tms,
unsigned tdi_nbits, unsigned long long tdi, int read_flag)
{
//
// TMS is a command of 0 to 14 bits length, sent LSB first. TDI = 0 throughout.
//
// if nTDI & lt; & gt; 0 then send TMS = 1-0-0 (TDI = 0).
//
// Next we send out the TDI bits (up to 64, LSB first), with TMS=0 for n-1 bits;
// the last TDI bit should be accompanied with TMS = 1.
//
// if nTDI & lt; & gt; 0 then send TMS = 1-0 (TDI = 0).
//
// NOTE: if read_flag == 1, then read TDO on last TMS bit and each of n-1 TDI bits.
// if read_flag == 2, only read TDO on the last TMS bit (to just get PrAcc)
//

unsigned char buffer[110]; // @@@@@@@@@@ BUFFERED WRITES VERSION @@@@@@@@@@
int index = 0; // index of next slot to use in buffer
int pairs = 0; // count of number of TDI/TMS pairs
int count = 0; // count of the number of symbols used
int i, n;
unsigned char ch;

if (a- & gt; BitsToRead != 0)
fprintf(stderr, " WARNING - write while pending read (in send)\n " );
if (read_flag & & (tdi_nbits == 0))
fprintf(stderr, " WARNING - request to read 0 bits (in send)\n " );

for (i = tms_nbits; i & gt; 0; i--) { // for each of the n bits...
ch = (tms & 1) + 'd'; // d, e, f, g
buffer [index++] = ch; // append to buffer
tms & gt; & gt; = 1; // shift TMS right one bit
}
count += tms_nbits;
pairs += tms_nbits;

if (DBG1 & & (tms_nbits != 0))
buffer[index++] = '.'; // spacer, ignored by programmer

if (tdi_nbits != 0) { // 1-0-0 if nTDI & lt; & gt; 0
if (CFG3) { // use compression: edd - & gt; a, edD - & gt; A
buffer[index++] = (read_flag ? 'A' : 'a');
count++;
}
else { // compression flag turned off
ch = 1 + 'd';
buffer[index++] = ch;
ch = 0 + 'd';
buffer[index++] = ch;
ch = 0 + (read_flag ? 'D' : 'd');
buffer[index++] = ch;
count += 3;
}
pairs += 3;
if (DBG1)
buffer[index++] = '.'; // spacer, ignored by programmer
}

long long Xtdi = tdi;
a- & gt; CharToRead = (read_flag == 2 ? 1 : 0);
a- & gt; BitsToRead = (read_flag == 2 ? 1 : 0);

i = tdi_nbits;
if (CFG3) { // while we can, package up lots of 4 TDI bits
for (; i & gt; 4; i -= 4) { // make sure the last bit is NOT packaged
ch = (read_flag == 1 ? 'I' : 'i') + (tdi & 0xF);
buffer[index++] = ch;
tdi & gt; & gt; = 4;
count++;
if (read_flag == 1) a- & gt; CharToRead++;
}
}
for (; i & gt; 0; i--) { // (send all/remaining bits as singles)
ch = ((tdi & 1) & lt; & lt; 1) + (i == 1) + // TMS=0 for n-1 bits, then 1 on last bit
((read_flag == 1 & & i != 1) ? // 0 = no read, 1 = normal read, 2 = oPrAcc read
'D' : 'd'); // UC = read, LC = none, no read on last bit
buffer[index++] = ch; // append to buffer
tdi & gt; & gt; = 1; // shift TDI right one bit
count++;
if (read_flag == 1) a- & gt; CharToRead++;
}
pairs += tdi_nbits;
if (read_flag == 1) a- & gt; BitsToRead = tdi_nbits;


if (tdi_nbits != 0) { // 1-0 if nTDI & lt; & gt; 0
if (DBG1)
buffer[index++] = '.'; // spacer, ignored by programmer

if (CFG3) {
buffer[index++] ='z'; // use compression: ed - & gt; z
count++;
}
else { // compression flag turned off
ch = 1 + 'd';
buffer[index++] = ch;
ch = 0 + 'd';
buffer[index++] = ch;
count += 2;
}
pairs += 2;
}

//
// Control handshaking for ICSP programmers
//

if (a- & gt; PendingHandshake)
{
//////// this code is also duplicated in bitbang_send ////////
if (a- & gt; RunningWriteCount & gt; a- & gt; MaxBufferedWrites)
a- & gt; MaxBufferedWrites = a- & gt; RunningWriteCount;
a- & gt; RunningWriteCount = 0;
//////////////////////////////////////////////////////////////

a- & gt; PendingHandshake = 0;

n = serial_read( & ch, 1, 250);
a- & gt; Read2Count++;

if (n != 1 || ch != ' & lt; ')
fprintf(stderr, " WARNING - handshake read error (in send)\n " );
}

//
// the below block is to implement handshake on
// EVERY write that does not have (read_flag != 0)
//
if (CFG1 == 1 & & !read_flag)
{
buffer[index++] = ' & gt; ';
a- & gt; PendingHandshake = 1;
}

//
// this block is to implement handshake on every 900/440 (MAXW) characters
// NOTE: assumes the Rx buffer in the programmer is 1024/512 bytes long
// **************

if (CFG1 == 2 & & !read_flag & & (a- & gt; RunningWriteCount + index) & gt; MAXW) // 900 + 50 & lt; 1024
{ // 440 + 30 & lt; 512
buffer[index++] = ' & gt; ';
a- & gt; PendingHandshake = 1;
}

//
// end of handshaking code
//

buffer[index] = 0; // append trailing zero so can print as a string

a- & gt; RunningWriteCount += index; // number of characters being written
a- & gt; TotalBitPairsSent += pairs; // number of TDI/TMS pairs encoded
a- & gt; TotalCodeChrsSent += count; // number of symbols used to send pairs

if (DBG1) {
unsigned L4 = Xtdi & gt; & gt; 48;
unsigned L3 = (Xtdi & gt; & gt; 32) & 0xFFFF;
unsigned L2 = (Xtdi & gt; & gt; 16) & 0xFFFF;
unsigned L1 = Xtdi & 0xFFFF;
printf( " n=%i, & lt; %s & gt; read=%i TDI: %04x %04x %04x %04x\n " ,
index, buffer, read_flag, L4, L3, L2, L1);
}

serial_write(buffer, index);
a- & gt; WriteCount++;
}

/*
* (by RR)
*/
static unsigned long long bitbang_recv(bitbang_adapter_t *a)
{
unsigned char buffer[70];
unsigned long long word;
int n, i;

//////// this code is also duplicated in bitbang_send ////////
if (a- & gt; RunningWriteCount & gt; a- & gt; MaxBufferedWrites)
a- & gt; MaxBufferedWrites = a- & gt; RunningWriteCount;
a- & gt; RunningWriteCount = 0;
//////////////////////////////////////////////////////////////

if (a- & gt; PendingHandshake)
fprintf(stderr, " WARNING - handshake pending error (in recv)\n " );

int expected = (CFG4 ? a- & gt; CharToRead : a- & gt; BitsToRead);

n = serial_read(buffer, expected, 250);
a- & gt; TotalCodeChrsRecv += n;
a- & gt; Read1Count++;
buffer[n] = 0; // append trailing zero so can print as a string

if (n != expected)
fprintf(stderr,
" WARNING - fewer characters read (%i) than expected (%i) (in recv)\n " ,
n, expected);

word = 0;

for (i = n-1; i & gt; =0; i--) {

if ((buffer[i] & gt; = 'I') & & (buffer[i] & lt; = 'X'))
word = (word & lt; & lt; 4) | (buffer[i] - 'I');
else {
switch (buffer[i]) {
case ('0'):
word = (word & lt; & lt; 1) | 0;
break;
case ('1'):
word = (word & lt; & lt; 1) | 1;
break;
default:
fprintf(stderr,
" WARNING - unexpected character (0x%02x) returned (in recv)\n " ,
buffer[i]);
} // switch
} // if ... else
} // for loop

if (DBG1) {
unsigned L4 = word & gt; & gt; 48;
unsigned L3 = (word & gt; & gt; 32) & 0xFFFF;
unsigned L2 = (word & gt; & gt; 16) & 0xFFFF;
unsigned L1 = word & 0xFFFF;
printf( " TDO = %04x %04x %04x %04x (%i bits) & lt; %s & gt; \n " ,
L4, L3, L2, L1, a- & gt; BitsToRead, buffer);
}

a- & gt; TotalBitsReceived += a- & gt; BitsToRead;
a- & gt; BitsToRead = 0;
return word;
}

/*
* this routine performs the functions:
* (1) power up the target, then send out the ICSP signature to enable ICSP programming mode;
* (0) power down the target in an orderly fashion.
* (by RR)
*/
static void bitbang_ICSP_enable(bitbang_adapter_t *a, int ICSP_EN)
{
if (ICSP_EN)
{
// 50mS delay after powerup, pulse MCLR high, send signature, set MCLR high, 10mS delay
unsigned char buffer[64] = " 5.88888.32.8.0100.1101.0100.0011.0100.1000.0101.0000.8.3.8...... " ;
// 0000000001111111111222222222233333333334444444444555555555566666
// 1234567890123456789012345678901234567890123456789012345678901234

serial_write(buffer, 64);
usleep(150000); // 150mS delay to allow the above to percolate through the system
}
else
{
// 50mS delay then cut power
unsigned char buffer[16] = " 88888.4......... " ;
// 0000000001111111
// 1234567890123456

serial_write(buffer, 16);

// 100mS delay to allow the above to percolate through the system
usleep(100000);
}
}

static void bitbang_close(adapter_t *adapter, int power_on)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;

usleep(100000);

/* Clear EJTAGBOOT mode. */
bitbang_send(a, 1, 1, 5, TAP_SW_ETAP, 0); /* Send command. */
bitbang_send(a, 6, 31, 0, 0, 0); /* TMS 1-1-1-1-1-0 */
// (force the Chip TAP controller into Run Test/Idle state)

//
// not entirely sure the above sequence is correct.
// see pg 29 of microchip programming docs
//

bitbang_ICSP_enable(a, 0);
gettimeofday( & a- & gt; T2, 0);

printf( " \n " );
printf( " total TDI/TMS pairs sent = %i pairs\n " , a- & gt; TotalBitPairsSent);
printf( " total TDO bits received = %i bits\n " , a- & gt; TotalBitsReceived);

printf( " total ascii codes sent = %i\n " , a- & gt; TotalCodeChrsSent);
printf( " total ascii codes recv = %i\n " , a- & gt; TotalCodeChrsRecv);
printf( " maximum continuous write = %i chars\n " , a- & gt; MaxBufferedWrites);

printf( " O/S serial writes = %i\n " , a- & gt; WriteCount);
printf( " O/S serial reads (data) = %i\n " , a- & gt; Read1Count);
printf( " O/S serial reads (sync) = %i\n " , a- & gt; Read2Count);
printf( " XferFastData count = %i\n " , a- & gt; FDataCount);
printf( " 10mS delays (E/X/R) = %i/%i/%i\n " , a- & gt; DelayCount[0],
a- & gt; DelayCount[1],
a- & gt; DelayCount[2]);
printf( " elapsed programming time = %lum %02lus\n " , (a- & gt; T2.tv_sec - a- & gt; T1.tv_sec) / 60,
(a- & gt; T2.tv_sec - a- & gt; T1.tv_sec) % 60);

serial_close(); // at this point we are exiting application???
// free(a); // suspect this line was causing XP CRASHES
// - shouldn't be needed anyway
}

/*
* Read the Device Identification code
*/
static unsigned bitbang_get_idcode(adapter_t *adapter)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;
unsigned idcode;

if (DBG2)
fprintf(stderr, " get_idcode\n " );

/* Reset the JTAG TAP controller: TMS 1-1-1-1-1-0.
* After reset, the IDCODE register is always selected.
* Read out 32 bits of data. */
bitbang_send(a, 6, 31, 32, 0, 1);
idcode = bitbang_recv(a);
return idcode;
}

/*
* Put device in serial execution mode. This is an alternative version
* taken directly from the microchip application note. The original
* version threw up a status error and then did an exit(-1), but
* when the exit was commented out still seemed to function.
* SEE: " PIC32 Flash Programming Specification 60001145N.pdf "
* (by RR)
*/
static void serial_execution(bitbang_adapter_t *a)
{
if (DBG2)
fprintf(stderr, " serial_execution\n " );

if (a- & gt; serial_execution_mode)
return;
a- & gt; serial_execution_mode = 1;

/* Enter serial execution. */
if (debug_level & gt; 0)
fprintf(stderr, " enter serial execution\n " );

bitbang_send(a, 1, 1, 5, TAP_SW_MTAP, 0); /* Send command. */ // 1.
bitbang_send(a, 1, 1, 5, MTAP_COMMAND, 0); /* Send command. */ // 2.
bitbang_send(a, 0, 0, 8, MCHP_STATUS, 1); /* Xfer data. */ // 3.
unsigned status = bitbang_recv(a);
if (debug_level & gt; 0)
fprintf(stderr, " status %04x\n " , status);
if ((status & MCHP_STATUS_CPS) == 0) {
fprintf(stderr, " invalid status = %04x (code protection)\n " , status); // 4.
exit(-1);
}

bitbang_send(a, 0, 0, 8, MCHP_ASSERT_RST, 0); /* Xfer data. */ // 5.

bitbang_send(a, 1, 1, 5, TAP_SW_ETAP, 0); /* Send command. */ // 6.
bitbang_send(a, 1, 1, 5, ETAP_EJTAGBOOT, 0); /* Send command. */ // 7.


bitbang_send(a, 1, 1, 5, TAP_SW_MTAP, 0); /* Send command. */ // 8.
bitbang_send(a, 1, 1, 5, MTAP_COMMAND, 0); /* Send command. */ // 9.
bitbang_send(a, 0, 0, 8, MCHP_DEASSERT_RST, 0); /* Xfer data. */ // 10.

if (memcmp(a- & gt; adapter.family_name, " mz " , 2) != 0) // not needed for MZ processors
bitbang_send(a, 0, 0, 8, MCHP_FLASH_ENABLE, 0); /* Xfer data. */ // 11.

bitbang_send(a, 1, 1, 5, TAP_SW_ETAP, 0); /* Send command. */ // 12.
}

//
// Shouldn't XferFastData check the value of PrAcc returned in
// the LSB? We don't seem to be even reading this back.
// UPDATE1: The check is not needed in 4-wire JTAG mode, seems
// to only be required if in 2-wire ICSP mode. It would also
// slow us down horribly.
// UPDATE2: We are operating at such a slow speed that the PrAcc
// check is not really needed. To date, have never seen PrAcc != 1
//
static void xfer_fastdata(bitbang_adapter_t *a, unsigned word)
{
a- & gt; FDataCount++;

if (CFG2 == 1)
bitbang_send(a, 0, 0, 33, (unsigned long long) word & lt; & lt; 1, 0);

if (CFG2 == 2) {
bitbang_send(a, 0, 0, 33, (unsigned long long) word & lt; & lt; 1, 2);
unsigned status = bitbang_recv(a);
if (! (status & 1)) {
printf( " ! " );
fflush(stdout);
}
}
//
// could add in code above to handle retrying if PrAcc == 0
//
// a better (faster) approach may be to 'accumulate' PrAcc at the
// programming adaptor, and then check the value at the end of a series
// of xfer_fastdata calls. we would need to implement an extra ascii
// command to use instead of 'D' (0x44) in the TDI header; '+' could be
// used as the check command (PrAcc |= TDO), while '=' used to read out
// the result (PrAcc) and reset the accumulator (PrAcc = 1) at the
// programming adaptor.
}

static void xfer_instruction(bitbang_adapter_t *a, unsigned instruction)
{
unsigned ctl;

if (debug_level & gt; 1)
fprintf(stderr, " xfer instruction %08x\n " , instruction);

// Select Control Register
bitbang_send(a, 1, 1, 5, ETAP_CONTROL, 0); /* Send command. */

// Wait until CPU is ready
// Check if Processor Access bit (bit 18) is set

int i = 0;
do {
if (i & gt; 100)
bitbang_delay10mS(a, 1);
bitbang_send(a, 0, 0, 32, CONTROL_PRACC | /* Xfer data. */
CONTROL_PROBEN |
CONTROL_PROBTRAP |
/* CONTROL_EJTAGBRK */ 0, 1); // this bit should NOT be set

// Microchip document 60001145N, " PIC32 Flash Programming
// Specification, DS60001145N page 18 stipulates 0x0004C000:
// CONTROL_PRACC | CONTROL_PROBEN | CONTROL_PROBTRAP

ctl = bitbang_recv(a);
i++;
} while (! (ctl & CONTROL_PRACC) & & i & lt; 150);

if (i == 150) {
fprintf(stderr, " PE response, PrAcc not set (in XferInstruction)\n " );
exit(-1);
}

// Select Data Register
// Send the instruction
bitbang_send(a, 1, 1, 5, ETAP_DATA, 0); /* Send command. */
bitbang_send(a, 0, 0, 32, instruction, 0); /* Send data. */

// Tell CPU to execute instruction
bitbang_send(a, 1, 1, 5, ETAP_CONTROL, 0); /* Send command. */
bitbang_send(a, 0, 0, 32, CONTROL_PROBEN | /* Send data. */
CONTROL_PROBTRAP, 0);
}

static unsigned get_pe_response(bitbang_adapter_t *a)
{
unsigned ctl, response;

// Select Control Register
bitbang_send(a, 1, 1, 5, ETAP_CONTROL, 0); /* Send command. */

// Wait until CPU is ready
// Check if Processor Access bit (bit 18) is set

int i = 0;
do {
if (i & gt; 100)
bitbang_delay10mS(a, 2);
bitbang_send(a, 0, 0, 32, CONTROL_PRACC | /* Xfer data. */
CONTROL_PROBEN |
CONTROL_PROBTRAP |
/* CONTROL_EJTAGBRK */ 0, 1); // this bit should NOT be set

// Microchip document 60001145N, " PIC32 Flash Programming
// Specification, DS60001145N page 30 stipulates 0x0004C000:
// CONTROL_PRACC | CONTROL_PROBEN | CONTROL_PROBTRAP

ctl = bitbang_recv(a);
i++;
} while (! (ctl & CONTROL_PRACC) & & i & lt; 150);

if (i == 150) {
fprintf(stderr, " PE response, PrAcc not set (in GetPEResponse)\n " );
exit(-1);
}

// Select Data Register
// Send the instruction
bitbang_send(a, 1, 1, 5, ETAP_DATA, 0); /* Send command. */
bitbang_send(a, 0, 0, 32, 0, 1); /* Get data. */
response = bitbang_recv(a);

// Tell CPU to execute NOP instruction
bitbang_send(a, 1, 1, 5, ETAP_CONTROL, 0); /* Send command. */
bitbang_send(a, 0, 0, 32, CONTROL_PROBEN | /* Send data. */
CONTROL_PROBTRAP, 0);
if (debug_level & gt; 1)
fprintf(stderr, " get PE response %08x\n " , response);
return response;
}

/*
* Read a word from memory (without PE).
*
* Only used to read configuration words.
*/
static unsigned bitbang_read_word(adapter_t *adapter, unsigned addr)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;
unsigned addr_lo = addr & 0xFFFF;
unsigned addr_hi = (addr & gt; & gt; 16) & 0xFFFF;

if (DBG2)
fprintf(stderr, " read_word\n " );

serial_execution(a);

xfer_instruction(a, 0x3c04bf80); // lui s3, 0xFF20
xfer_instruction(a, 0x3c080000 | addr_hi); // lui t0, addr_hi
xfer_instruction(a, 0x35080000 | addr_lo); // ori t0, addr_lo
xfer_instruction(a, 0x8d090000); // lw t1, 0(t0)
xfer_instruction(a, 0xae690000); // sw t1, 0(s3)

bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0); /* Send command. */
bitbang_send(a, 0, 0, 33, 0, 1); /* Get fastdata. */
unsigned word = bitbang_recv(a) & gt; & gt; 1;

if (debug_level & gt; 0)
fprintf(stderr, " read word at %08x - & gt; %08x\n " , addr, word);
return word;
}

/*
* Read a memory block.
*/
static void bitbang_read_data(adapter_t *adapter,
unsigned addr, unsigned nwords, unsigned *data)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;
unsigned words_read, i;

if (DBG2)
fprintf(stderr, " read_data\n " );

if (! a- & gt; use_executive) {
/* Without PE. */
for (i = nwords; i & gt; 0; i--) {
*data++ = bitbang_read_word(adapter, addr);
addr += 4;
}
return;
}

/* Use PE to read memory. */
for (words_read = 0; words_read & lt; nwords; words_read += 32) {

bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0);
xfer_fastdata(a, PE_READ & lt; & lt; 16 | 32); /* Read 32 words */
xfer_fastdata(a, addr); /* Address */

unsigned response = get_pe_response(a); /* Get response */
if (response != PE_READ & lt; & lt; 16) {
fprintf(stderr, " bad READ response = %08x, expected %08x\n " ,
response, PE_READ & lt; & lt; 16);
exit(-1);
}
for (i = 0; i & lt; 32; i++) {
*data++ = get_pe_response(a); /* Get data */
}
addr += 32 * 4;
}
}

/*
* Download programming executive (PE).
*/
static void bitbang_load_executive(adapter_t *adapter,
const unsigned *pe, unsigned nwords, unsigned pe_version)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;

a- & gt; use_executive = 1;
serial_execution(a);

printf( " Loading PE: " );
fflush(stdout);

if (memcmp(a- & gt; adapter.family_name, " mz " , 2) != 0) { // steps 1. to 3. not needed for MZ
/* Step 1. */
xfer_instruction(a, 0x3c04bf88); // lui a0, 0xbf88
xfer_instruction(a, 0x34842000); // ori a0, 0x2000 - address of BMXCON
xfer_instruction(a, 0x3c05001f); // lui a1, 0x1f
xfer_instruction(a, 0x34a50040); // ori a1, 0x40 - a1 has 001f0040
xfer_instruction(a, 0xac850000); // sw a1, 0(a0) - BMXCON initialized
printf( " 1 " );
fflush(stdout);

/* Step 2. */
xfer_instruction(a, 0x34050800); // li a1, 0x800 - a1 has 00000800
xfer_instruction(a, 0xac850010); // sw a1, 16(a0) - BMXDKPBA initialized
printf( " 2 " );
fflush(stdout);

/* Step 3. */
xfer_instruction(a, 0x8c850040); // lw a1, 64(a0) - load BMXDMSZ
xfer_instruction(a, 0xac850020); // sw a1, 32(a0) - BMXDUDBA initialized
xfer_instruction(a, 0xac850030); // sw a1, 48(a0) - BMXDUPBA initialized
printf( " 3 " );
fflush(stdout);
}

/* Step 4. */
xfer_instruction(a, 0x3c04a000); // lui a0, 0xa000
xfer_instruction(a, 0x34840800); // ori a0, 0x800 - a0 has a0000800
printf( " 4 (LDR) " );
fflush(stdout);

/* Download the PE loader. */
int i;
for (i = 0; i & lt; PIC32_PE_LOADER_LEN; i += 2) {
/* Step 5. */
unsigned opcode1 = 0x3c060000 | pic32_pe_loader[i];
unsigned opcode2 = 0x34c60000 | pic32_pe_loader[i+1];

xfer_instruction(a, opcode1); // lui a2, PE_loader_hi++
xfer_instruction(a, opcode2); // ori a2, PE_loader_lo++
xfer_instruction(a, 0xac860000); // sw a2, 0(a0)
xfer_instruction(a, 0x24840004); // addiu a0, 4
}
printf( " 5 " );
fflush(stdout);

/* Jump to PE loader (step 6). */
xfer_instruction(a, 0x3c19a000); // lui t9, 0xa000
xfer_instruction(a, 0x37390800); // ori t9, 0x800 - t9 has a0000800
xfer_instruction(a, 0x03200008); // jr t9
xfer_instruction(a, 0x00000000); // nop
printf( " 6 " );
fflush(stdout);

/* Switch from serial to fast execution mode. */
//bitbang_send(a, 1, 1, 5, TAP_SW_ETAP, 0);
//bitbang_send(a, 6, 31, 0, 0, 0); /* TMS 1-1-1-1-1-0 */

//
// the above two lines are not present in the Microchip programming specs
//

/* Send parameters for the loader (step 7-A).
* PE_ADDRESS = 0xA000_0900,
* PE_SIZE */
bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0); /* Send command. */
xfer_fastdata(a, 0xa0000900);
xfer_fastdata(a, nwords);
printf( " 7a (PE) " );
fflush(stdout);

/* Download the PE itself (step 7-B). */
for (i = 0; i & lt; nwords; i++) {
xfer_fastdata(a, *pe++);
}
bitbang_delay10mS(a, 3);
printf( " 7b " );
fflush(stdout);

/* Download the PE instructions. */
xfer_fastdata(a, 0); /* Step 8 - jump to PE. */
xfer_fastdata(a, 0xDEAD0000);
bitbang_delay10mS(a, 3);
printf( " 8 " );
fflush(stdout);

xfer_fastdata(a, PE_EXEC_VERSION & lt; & lt; 16);

unsigned version = get_pe_response(a);
if (version != (PE_EXEC_VERSION & lt; & lt; 16 | pe_version)) {
fprintf(stderr, " \nbad PE version = %08x, expected %08x\n " ,
version, PE_EXEC_VERSION & lt; & lt; 16 | pe_version);
exit(-1);
}

printf( " v%04x\n " , version & 0xFFFF);

if (debug_level & gt; 0)
fprintf(stderr, " PE version = %04x\n " , version & 0xffff);
}

/*
* Erase all flash memory.
*/
static void bitbang_erase_chip(adapter_t *adapter)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;

if (DBG2)
fprintf(stderr, " erase_chip\n " );

bitbang_send(a, 1, 1, 5, TAP_SW_MTAP, 0); /* Send command. */
bitbang_send(a, 1, 1, 5, MTAP_COMMAND, 0); /* Send command. */
bitbang_send(a, 0, 0, 8, MCHP_ERASE, 0); /* Xfer data. */

if (memcmp(a- & gt; adapter.family_name, " mz " , 2) == 0)
bitbang_send(a, 0, 0, 8, MCHP_DEASSERT_RST, 0); // needed for PIC32MZ devices only.

int i = 0;
unsigned status;
do {
bitbang_delay10mS(a, 0);
bitbang_send(a, 0, 0, 8, MCHP_STATUS, 1); /* Xfer data. */
status = bitbang_recv(a);
i++;
} while ((status & (MCHP_STATUS_CFGRDY |
MCHP_STATUS_FCBUSY)) != MCHP_STATUS_CFGRDY & & i & lt; 100);

if (i == 100) {
fprintf(stderr, " invalid status = %04x (in erase chip)\n " , status);
exit(-1);
}
printf( " (%imS) " , i * 10);
fflush(stdout);
}

/*
* Write a word to flash memory. (only seems to be used to write the four configuration words)
*
* !!!!!!!!!! WARNING !!!!!!!!!!
* on PIC32MZ EC family devices PE_WORD_PROGRAM will not generate the ECC parity bits;
* instead should use QUAD_WORD_PGRM to program all four configuration words at once.
* !!!!!!!!!! WARNING !!!!!!!!!!
*/
static void bitbang_program_word(adapter_t *adapter,
unsigned addr, unsigned word)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;

if (DBG2)
fprintf(stderr, " program_word\n " );

if (debug_level & gt; 0)
fprintf(stderr, " program word at %08x: %08x\n " , addr, word);
if (! a- & gt; use_executive) {
/* Without PE. */
fprintf(stderr, " slow flash write not implemented yet\n " );
exit(-1);
}

if (memcmp(a- & gt; adapter.family_name, " mz " , 2) == 0) {
printf( " !ECC! " ); // warn if word-write to MZ processor
fflush(stdout);
}

/* Use PE to write flash memory. */
bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0); /* Send command. */
xfer_fastdata(a, PE_WORD_PROGRAM & lt; & lt; 16 | 2);
xfer_fastdata(a, addr); /* Send address. */
xfer_fastdata(a, word); /* Send word. */

unsigned response = get_pe_response(a);
if (response != (PE_WORD_PROGRAM & lt; & lt; 16)) {
fprintf(stderr, " \nfailed to program word %08x at %08x, reply = %08x\n " ,
word, addr, response);
exit(-1);
}
}

/*
* Flash write row of memory.
*/
static void bitbang_program_row(adapter_t *adapter, unsigned addr,
unsigned *data, unsigned words_per_row)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;

if (DBG2)
fprintf(stderr, " program_row\n " );
if (DBG3)
fprintf(stderr, " \nprogramming %u words at %08x " ,
words_per_row, addr);

if (debug_level & gt; 0)
fprintf(stderr, " row program %u words at %08x\n " , words_per_row, addr);
if (! a- & gt; use_executive) {
/* Without PE. */
fprintf(stderr, " slow flash write not implemented yet\n " );
exit(-1);
}

/* Use PE to write flash memory. */
bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0); /* Send command. */
xfer_fastdata(a, PE_ROW_PROGRAM & lt; & lt; 16 | words_per_row);
xfer_fastdata(a, addr); /* Send address. */

//
// The below for loop seems to be where our biggest programming time bottleneck is.
//

/* Download data. */
int i;
for (i = 0; i & lt; words_per_row; i++) {
xfer_fastdata(a, *data++); /* Send word. */
}

unsigned response = get_pe_response(a);
if (response != (PE_ROW_PROGRAM & lt; & lt; 16)) {
fprintf(stderr, " \nfailed to program row at %08x, reply = %08x\n " ,
addr, response);
exit(-1);
}
}

/*
* Verify a block of memory.
*/
static void bitbang_verify_data(adapter_t *adapter,
unsigned addr, unsigned nwords, unsigned *data)
{
bitbang_adapter_t *a = (bitbang_adapter_t*) adapter;
unsigned data_crc, flash_crc;

if (DBG2)
fprintf(stderr, " verify_data\n " );
if (DBG3)
fprintf(stderr, " \nverifying %u words at %08x " , nwords, addr);

if (! a- & gt; use_executive) {
/* Without PE. */
fprintf(stderr, " slow verify not implemented yet\n " );
exit(-1);
}

/* Use PE to get CRC of flash memory. */
bitbang_send(a, 1, 1, 5, ETAP_FASTDATA, 0); /* Send command. */
xfer_fastdata(a, PE_GET_CRC & lt; & lt; 16);
xfer_fastdata(a, addr); /* Send address. */
xfer_fastdata(a, nwords * 4); /* Send length. */

unsigned response = get_pe_response(a);
if (response != (PE_GET_CRC & lt; & lt; 16)) {
fprintf(stderr, " \nfailed to verify %d words at %08x, reply = %08x\n " ,
nwords, addr, response);
exit(-1);
}

flash_crc = get_pe_response(a) & 0xffff;

data_crc = calculate_crc(0xffff, (unsigned char*) data, nwords * 4);
if (flash_crc != data_crc) {
fprintf(stderr, " \nchecksum failed at %08x: returned %04x, expected %04x\n " ,
addr, flash_crc, data_crc);
exit(-1);
}
}

/*
* Initialize bitbang adapter.
* Return a pointer to a data structure, allocated dynamically.
* When adapter not found, return 0.
*/
adapter_t *adapter_open_bitbang(const char *port, int baud_rate)
{
bitbang_adapter_t *a;

printf( " (ascii ICSP coded by Robert Rozee)\n\n " );

//
// the following block of code is used to upload firmware to
// an attached Arduino NANO using the STK500v1 protocol:
// PIC32PROG -d ASCII:COM5 -b3
//
// once the firmware upload is completed, exits from pic32prog
//

if (baud_rate & lt; 5) // invoked by a baud rate of 1, 2, 3, or 4.
{
#if 1 // change to 0 to not compile in firmware uplaod
#define STK_GET_SYNC 0x30 // synchronize
#define STK_ENTER_PROGMODE 0x50 // enter program mode
#define STK_READ_SIGN 0x75 // read signature
#define STK_LOAD_ADDRESS 0x55 // load address
#define STK_PROG_PAGE 0x64 // program page
#define STK_LEAVE_PROGMODE 0x51 // exit program mode

#define CRC_EOP 0x20 // end of packet

#define STK_INSYNC 0x14 // response - insync
#define STK_OK 0x10 // response - OK

#include " bitbang/ICSP_v1E.inc "

int i, n;
unsigned char buffer [140]; // 0x80 + 12d (max used is 133)
int bps[] = {0, 9600, 19200, 57600, 115200 }; // known arduino bootloader baud rates

if (serial_open(port, bps[baud_rate]) & lt; 0) {
fprintf(stderr, " Unable to configure serial port %s\n " , port);
serial_close();
exit(-1);
}
printf( " %i baud " , bps[baud_rate]);
fflush(stdout);

for (i = 0; i & lt; 40; i++) {

buffer[0] = STK_GET_SYNC; // get synchronization
buffer[1] = CRC_EOP;

serial_write(buffer, 2);
printf( " . " );
fflush(stdout);
n = serial_read(buffer, 2, 100);
if ((n == 2) & & (buffer[0] == STK_INSYNC) & & (buffer[1] == STK_OK))
i = 100;
}

if (i & lt; 100) {
fprintf(stderr, " \nFailed to find arduino/STK500 bootloader\n " );
serial_close();
exit(-1);
}
printf( " synchronized\n " );

buffer[0] = STK_ENTER_PROGMODE; // enter program mode (not needed)
buffer[1] = CRC_EOP;
serial_write(buffer, 2);
n = serial_read(buffer, 2, 100);

if ((n != 2) || (buffer[0] != STK_INSYNC) || (buffer[1] != STK_OK)) {
fprintf(stderr, " Failed to enter program mode\n " );
serial_close();
exit(-1);
}

buffer[0] = STK_READ_SIGN; // read signature bytes (3)
buffer[1] = CRC_EOP;
serial_write(buffer, 2);
n = serial_read(buffer, 5, 100);

if ((n != 5) || (buffer[0] != STK_INSYNC) || (buffer[4] != STK_OK)) {
fprintf(stderr, " Failed to get signature\n " );
serial_close();
exit(-1);
}
unsigned ID = (buffer[1] & lt; & lt; 16) + (buffer[2] & lt; & lt; 8) + buffer[3];
printf( " Signature = %06x Device = %s\n " , ID, ID == 0x1e950f ? " ATmega328P " : " (wrong uP) " );

for (i = 0; i & lt; sizeof(ICSP); i += 0x80)
printf( " . " );
for (i = 0; i & lt; sizeof(ICSP); i += 0x80)
printf( " \b " );

for (i = 0; i & lt; sizeof(ICSP); i += 0x80) {
printf( " # " );
fflush(stdout);

buffer[0] = STK_LOAD_ADDRESS; // load address
buffer[1] = (i & gt; & gt; 1) % 0x100; // address low (word boundary)
buffer[2] = (i & gt; & gt; 1) / 0x100; // address high
buffer[3] = CRC_EOP;
serial_write(buffer, 4);
n = serial_read(buffer, 2, 100);

if ((n != 2) || (buffer[0] != STK_INSYNC) || (buffer[1] != STK_OK)) {
fprintf(stderr, " \nFailed to load address %04x\n " , i);
serial_close();
exit(-1);
}

buffer[0] = STK_PROG_PAGE; // program page
buffer[1] = 0x00; // length high (in bytes, NOT words)
buffer[2] = 0x80; // length low (order reverse to address)
buffer[3] = 'F'; // memory type: 'E' = eeprom, 'F' = flash
memcpy( & buffer[4], & ICSP[i], 0x80); // data (128 bytes)
buffer[4 + 0x80] = CRC_EOP;
serial_write(buffer, 4 + 0x80 + 1);
n = serial_read(buffer, 2, 100);

if ((n != 2) || (buffer[0] != STK_INSYNC) || (buffer[1] != STK_OK)) {
fprintf(stderr, " \nFailed to program page\n " );
serial_close();
exit(-1);
}
}
printf( " \n " );

buffer[0] = STK_LEAVE_PROGMODE; // leave program mode
buffer[1] = CRC_EOP;
serial_write(buffer, 2);
n = serial_read(buffer, 2, 100);

if ((n != 2) || (buffer[0] != STK_INSYNC) || (buffer[1] != STK_OK)) {
fprintf(stderr, " Failed to exit program mode\n " );
serial_close();
exit(-1);
}
printf( " Firmware uploaded to 'ascii ICSP' adapter OK\n " );
serial_close();
#else
printf( " Firmware upload to arduino/STK500 not included\n " );
#endif
exit(0); // finished performing function, exit program
}

//
// carry on with normal startup
//

a = calloc(1, sizeof(*a));
if (! a) {
fprintf(stderr, " Out of memory (in open)\n " );
return 0;
}

/* Open serial port */
if (serial_open(port, 115200) & lt; 0) {
/* failed to open serial port */
fprintf(stderr, " Unable to configure serial port %s\n " , port);
serial_close();
free(a);
return 0;
}
usleep(200000);

//
// Serial port now open and configured.
//
printf( " Adapter: " );
fflush(stdout);

int i, n;
unsigned char ch;
for (i = 0; i & lt; 40; i++) {
ch = ' & gt; ';
serial_write( & ch, 1);
ch = (i & lt; 20 ? '.': ':');
if (i == 20)
for (n = 0; n & lt; 20; n++ )
printf( " \b " );
printf( " %c " , ch);
fflush(stdout);
n = serial_read( & ch, 1, 250);
if (n == 1 & & ch == ' & lt; ')
i = 100;
}

if (i & lt; 100) {
fprintf(stderr, " \nNo response from 'ascii ICSP' adapter\n " );
serial_close();
free(a);
return 0;
}
printf( " OK1 " );
fflush(stdout);

ch = '?';
unsigned char buffer[15] = " ..............\0 " ;
// " ascii ICSP v1X "
serial_write( & ch, 1);
n = serial_read(buffer, 14, 250);

if (n == 14 & & memcmp(buffer, " ascii ICSP v1 " , 13) == 0)
printf( " OK2 - %s\n " , buffer);
else {
fprintf(stderr, " \nBad response from 'ascii ICSP' adapter\n " );
serial_close();
free(a);
return 0;
}

//
// This is the end of 'ascii ICSP' ID probe
//

a- & gt; BitsToRead = 0;
a- & gt; CharToRead = 0;
a- & gt; PendingHandshake = 0; // handshake read req'd before next write

a- & gt; TotalCodeChrsSent = 0; // count of total # of code characters sent out
a- & gt; TotalCodeChrsRecv = 0; // count of total # of code characters received
a- & gt; TotalBitPairsSent = 0; // count of total # of TDI+TMS bits sent
a- & gt; TotalBitsReceived = 0; // count of total # of TDO bits recieved
a- & gt; MaxBufferedWrites = 0; // maximum continuous write length (chars)
a- & gt; RunningWriteCount = 0; // running count of writes, reset by read

a- & gt; WriteCount = 0;
a- & gt; Read1Count = 0;
a- & gt; Read2Count = 0;
a- & gt; FDataCount = 0;
for (i = 0; i & lt; 4; i++)
a- & gt; DelayCount[i] = 0;

a- & gt; use_executive = 0;
a- & gt; serial_execution_mode = 0;

//
// It is at this point that we start talking to the target.
//

bitbang_ICSP_enable(a, 1);
gettimeofday( & a- & gt; T1, 0);

//
// The below few lines enable a forced " emergency " erase,
// use -b8 for MX processors, -b9 for MZ processors
//
// once the erase is completed, exits from pic32prog
//

if ((baud_rate & gt; & gt; 1) == 4) { // 8 (MX) or 9 (MZ)
printf( " \nAttempting blind erase of %s processor\n " ,
(baud_rate & 1) ? " MZ " : " MX " );
bitbang_send(a, 6, 31, 0, 0, 0); // don't care about ID
bitbang_send(a, 1, 1, 5, TAP_SW_MTAP, 0); /* Send command. */
bitbang_send(a, 1, 1, 5, MTAP_COMMAND, 0); /* Send command. */
bitbang_send(a, 0, 0, 8, MCHP_ERASE, 0); /* Xfer data. */
if (baud_rate & 1)
bitbang_send(a, 0, 0, 8, MCHP_DEASSERT_RST, 0); // PIC32MZ devices only.
bitbang_delay10mS(a, 0);
bitbang_send(a, 0, 0, 8, MCHP_STATUS, 1); /* Xfer data. */
usleep(1000000); // allow 1 second for erase to complete
bitbang_ICSP_enable(a, 0); // shut down target
serial_close();
free(a);
exit(0); // finished performing function, exit program
}

/* Reset the JTAG TAP controller: TMS 1-1-1-1-1-0.
* After reset, the IDCODE register is always selected.
* Read out 32 bits of data. */
unsigned idcode;
bitbang_send(a, 6, 31, 32, 0, 1); // 1. (pg 20)
idcode = bitbang_recv(a);
if ((idcode & 0xfff) != 0x053) {
/* Microchip vendor ID is expected. */
if (debug_level & gt; 0 || (idcode != 0 & & idcode != 0xffffffff))
fprintf(stderr, " incompatible CPU detected, IDCODE=%08x\n " , idcode);
bitbang_ICSP_enable(a, 0); // shut down target
serial_close();
free(a);
return 0;
}

/* Check status. */
bitbang_send(a, 1, 1, 5, TAP_SW_MTAP, 0); /* Send command. */ // 2.
bitbang_send(a, 1, 1, 5, MTAP_COMMAND, 0); /* Send command. */ // 3.
#ifdef OLDWAY
bitbang_send(a, 0, 0, 8, MCHP_FLASH_ENABLE, 0); /* Xfer data. */ // may be an issue for MZ
// (above line) " This command requires a NOP to complete. "
#else
bitbang_send(a, 0, 0, 8, MCHP_STATUS, 0); /* Xfer data. */ // 4a.
bitbang_delay10mS(a, 3);
#endif
bitbang_send(a, 0, 0, 8, MCHP_STATUS, 1); /* Xfer data. */ // 4b.
unsigned status = bitbang_recv(a);
if (debug_level & gt; 0)
fprintf(stderr, " status %04x\n " , status);
#ifdef OLDWAY
if ((status & ~MCHP_STATUS_DEVRST) !=
(MCHP_STATUS_CPS | MCHP_STATUS_CFGRDY | MCHP_STATUS_FAEN)) {
#else
if ((status & (MCHP_STATUS_CFGRDY | MCHP_STATUS_FCBUSY)) != MCHP_STATUS_CFGRDY) {
#endif
fprintf(stderr, " invalid status = %04x (in open)\n " , status); // 5.
bitbang_ICSP_enable(a, 0); // shut down target
serial_close();
free(a);
return 0;
}
//
// the above two blocks of code that get the device ID and check status have been altered to
// bring into line with the current microchip recommendations. this also removes a potential
// incompatibility with MZ family devices, which do not support MCHP_FLASH_ENABLE.
//
// see: Microchip document 60001145N, " PIC32 Flash Programming
// Specification, DS60001145N page 20 (8.0 CHECK DEVICE STATUS)
//
// to return to old method, add line #define OLDWAY
//

a- & gt; adapter.block_override = 0;
a- & gt; adapter.flags = AD_PROBE | AD_ERASE | AD_READ | AD_WRITE;

/* User functions. */
a- & gt; adapter.close = bitbang_close;
a- & gt; adapter.get_idcode = bitbang_get_idcode;
a- & gt; adapter.load_executive = bitbang_load_executive;
a- & gt; adapter.read_word = bitbang_read_word;
a- & gt; adapter.read_data = bitbang_read_data;
a- & gt; adapter.verify_data = bitbang_verify_data;
a- & gt; adapter.erase_chip = bitbang_erase_chip;
a- & gt; adapter.program_word = bitbang_program_word;
a- & gt; adapter.program_row = bitbang_program_row;
return & a- & gt; adapter;
}