Double and long overdue commit..
Various changes to STM8 SWIM code to make more versatile allowing SWIM pin to be located effectively on any STM32 GPIO pin. Still haven't touched an AVR implementation, but made place holders so it can compile for AVR at least. These SWIM changes aren't heavily tested, mostly just made sure could flash SOIC-8 STM8 CIC via CIC CLK. Beginings of JTAG code to configure CPLDs. Currently only tested state change and scan out reading MachXO-256, 4032/64v, & XC9572/36XL CPLDs Tested and working on inlretro6 v1.0p, stm adapter, & avr kazzos. Older devices with flipflops will apply 5v signals to JTAG pins but time is mostly minimized by keeping signals defaulted low unless actively changing states or scanning data. Still need to verify scan in working, probably move TDI/TDO long strings to buffers instead of 32byte PBJE data array. Also need smarter PBJE host code to keep track of current state and come up with PBJE register values without hard coding them.. But things are working fairly well so far with SWIM & JTAG implementations. Had some issues where I thought jtag pin toggling was getting optimized out, but I must have simply had the logic analyzer speed set too low and was missing pin changes that can be as quick as 40nsec with space optimized code. Current inl6 code is ~4400Bytes, without optimization it's nearly 50% larger at ~6550Bytes..! Optimizations seem fine in testing and with logic analyzer running at 50Mhz which is good because the GPIO registers are set as volatile so they better not be getting optimized away!
This commit is contained in:
parent
535b45be27
commit
3c359ac5ca
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <avr/io.h>
|
||||
|
||||
//AVR GPIO ports are 8bits wide
|
||||
//Use this type when need an int to hold pin mask
|
||||
#define GPIO_PinMask uint8_t
|
||||
|
||||
#define __IO volatile /*!< Defines 'read / write' permissions */
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ uint8_t io_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rd
|
|||
case SNES_INIT: snes_init(); break;
|
||||
case SWIM_INIT:
|
||||
return swim_init(operand); break;
|
||||
case JTAG_INIT:
|
||||
return jtag_init(operand); break;
|
||||
|
||||
case EXP0_PULLUP_TEST:
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
|
|
@ -210,6 +212,20 @@ uint8_t swim_init( uint8_t swim_lane )
|
|||
{
|
||||
switch (swim_lane) {
|
||||
case SWIM_ON_A0: //Most NES & Famicom carts
|
||||
//Enable A0 pin on EXT PORT
|
||||
EXT_A0_ENABLE();
|
||||
//set A0 to open drain with pull-up enabled
|
||||
A0_IP_PU();
|
||||
#ifdef STM_CORE
|
||||
A0_OD(); //set type to open drain
|
||||
A0_HI(); //set output high (deasserted)
|
||||
A0_OP(); //enable as output to have above take effect
|
||||
#endif
|
||||
swim_pin = A0;
|
||||
swim_base = A0bank;
|
||||
//swim_mask = 1<<A0;
|
||||
//set set as output high
|
||||
//define the swim pin, base, & mask
|
||||
break;
|
||||
case SWIM_ON_EXP0: //SNES carts
|
||||
//set to define used by shared_dict_pinport.h
|
||||
|
|
@ -223,7 +239,7 @@ uint8_t swim_init( uint8_t swim_lane )
|
|||
#endif
|
||||
swim_pin = EXP0_;
|
||||
swim_base = EXP0bank;
|
||||
swim_mask = 1<<EXP0;
|
||||
//swim_mask = 1<<EXP0;
|
||||
break;
|
||||
case SWIM_ON_D0: //NES/FC carts with CICOprocesor
|
||||
break;
|
||||
|
|
@ -233,6 +249,47 @@ uint8_t swim_init( uint8_t swim_lane )
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
//Initialization of JTAG communications
|
||||
//the JTAG pin depends on INL board design.
|
||||
//dict call must provide the "jtag_lane"
|
||||
//that jtag lane will be used for all subsequent communications.
|
||||
//if jtag lane is unknown or other problem return error, else return SUCCESS
|
||||
uint8_t jtag_init( uint8_t jtag_lane )
|
||||
{
|
||||
switch (jtag_lane) {
|
||||
case JTAG_ON_EXP0_3: //Most NES carts
|
||||
|
||||
|
||||
#ifdef STM_INL6
|
||||
//set base & masks
|
||||
tdo_base = EXP0bank;
|
||||
tdo_pin = EXP0;
|
||||
tdi_base = D8bank;
|
||||
tdi_pin = D8;
|
||||
tms_base = D9bank;
|
||||
tms_pin = D9;
|
||||
tck_base = D10bank;
|
||||
tck_pin = D10;
|
||||
#else
|
||||
#endif
|
||||
|
||||
|
||||
//enable GPIO banks
|
||||
//EXT_D8_10_ENABLE(); //EXP0 is also on this GPIO bank
|
||||
EXP_ENABLE();
|
||||
CTL_ENABLE(); //not really needed..
|
||||
|
||||
|
||||
//initialize PBJE
|
||||
jtag_init_pbje();
|
||||
break;
|
||||
default:
|
||||
return ERR_UNKN_JTAG_LANE;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
//Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN
|
||||
//followed by alternating 0xAA, 0x55, 0xAA...
|
||||
//This test pulls up EXP0 and then reads AUX_PIN 6 times in rapid succession returning error code
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "pinport.h"
|
||||
#include "swim.h"
|
||||
#include "jtag.h"
|
||||
#include "shared_dictionaries.h"
|
||||
#include "shared_errors.h"
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ void io_reset();
|
|||
void nes_init();
|
||||
void snes_init();
|
||||
uint8_t swim_init(uint8_t opcode);
|
||||
uint8_t jtag_init(uint8_t opcode);
|
||||
uint8_t exp0_pullup_test();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,455 @@
|
|||
#include "jtag.h"
|
||||
|
||||
//=================================================================================================
|
||||
//
|
||||
// JTAG operations
|
||||
// This file includes all the jtag functions possible to be called from the jtag dictionary.
|
||||
//
|
||||
// See description of the commands contained here in shared/shared_dictionaries.h
|
||||
//
|
||||
//=================================================================================================
|
||||
|
||||
//JTAG pin globals initialized by io.c when setting up JTAG port
|
||||
//Having these as variables allows pins to be easily relocated to any pin
|
||||
GPIO_TypeDef *tdo_base;
|
||||
uint8_t tdo_pin;
|
||||
GPIO_TypeDef *tdi_base;
|
||||
uint8_t tdi_pin;
|
||||
GPIO_TypeDef *tms_base;
|
||||
uint8_t tms_pin;
|
||||
GPIO_TypeDef *tck_base;
|
||||
uint8_t tck_pin;
|
||||
|
||||
//Paul's Basic JTAG Engine globals
|
||||
uint8_t pbje_status; //only engine can write, read only by host
|
||||
uint8_t pbje_command; //only host can write, read only by engine
|
||||
uint8_t pbje_numclk; //numclk is a sticky value, don't modify!
|
||||
#define PBJE_DATA_ARRAY_SIZE 32
|
||||
uint8_t pbje_data[PBJE_DATA_ARRAY_SIZE];
|
||||
uint8_t pbje_cmd_update_flag;
|
||||
|
||||
|
||||
/* Desc:Function takes an opcode which was transmitted via USB
|
||||
* then decodes it to call designated function.
|
||||
* shared_dict_jtag.h is used in both host and fw to ensure opcodes/names align
|
||||
* Pre: Macros must be defined in firmware pinport.h & jtag.h
|
||||
* opcode must be defined in shared_dict_jtag.h
|
||||
* Post:function call complete.
|
||||
* Rtn: SUCCESS if opcode found, error if opcode not present or other problem.
|
||||
*/
|
||||
uint8_t jtag_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata )
|
||||
{
|
||||
#define RD_LEN 0
|
||||
#define RD0 1
|
||||
#define RD1 2
|
||||
#define RD2 3
|
||||
#define RD3 4
|
||||
#define RD4 5
|
||||
#define RD5 6
|
||||
// uint16_t *ret_hword = (uint16_t*) &rdata[1];
|
||||
|
||||
#define BYTE_LEN 1
|
||||
#define HWORD_LEN 2
|
||||
switch (opcode) {
|
||||
case PBJE_INIT: jtag_init_pbje(); break;
|
||||
|
||||
case GET_CMD: rdata[RD0] = pbje_command;
|
||||
rdata[RD_LEN] = BYTE_LEN; break;
|
||||
|
||||
case GET_STATUS: rdata[RD0] = pbje_status;
|
||||
rdata[RD_LEN] = BYTE_LEN; break;
|
||||
|
||||
case SET_CMD: pbje_command = operand;
|
||||
//need to immediately update status to overwrite PBJE_DONE from previous command
|
||||
//signal to main thread that command was updated
|
||||
//this status is what triggers engine to process current command
|
||||
pbje_status = PBJE_CMD_RX;
|
||||
break;
|
||||
case SET_CMD_WAIT: pbje_command = operand;
|
||||
pbje_status = PBJE_CMD_RX;
|
||||
//perform command before returning
|
||||
jtag_run_pbje();
|
||||
//return current status
|
||||
rdata[RD0] = pbje_status;
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
break;
|
||||
|
||||
case SET_NUMCLK: pbje_numclk = operand; break;
|
||||
|
||||
//GET & SET ARRAY DATA
|
||||
case SET_2B_DATA: pbje_data[0] = operand;
|
||||
pbje_data[1] = operand>>8;
|
||||
break;
|
||||
case GET_6B_DATA: rdata[RD0] = pbje_data[0];
|
||||
rdata[RD1] = pbje_data[1];
|
||||
rdata[RD2] = pbje_data[2];
|
||||
rdata[RD3] = pbje_data[3];
|
||||
rdata[RD4] = pbje_data[4];
|
||||
rdata[RD5] = pbje_data[5];
|
||||
rdata[RD_LEN] = 6;
|
||||
break;
|
||||
|
||||
|
||||
|
||||
default:
|
||||
//opcode doesn't exist
|
||||
return ERR_UNKN_JTAG_OPCODE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
void jtag_init_pbje()
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
|
||||
//set outputs to default level
|
||||
#ifdef STM_INL6
|
||||
//while these are supposed to be default high, I'm going with low
|
||||
//these signals aren't 5v tolerant which could be problem with original kazzo boards
|
||||
TMS_LO();
|
||||
TDI_LO();
|
||||
//makes sense for TCK default state to be low as posedge is begining of cycle
|
||||
TCK_LO();
|
||||
|
||||
//enable ouput drivers
|
||||
TCK_OP();
|
||||
TCK_PP();
|
||||
TMS_OP();
|
||||
TMS_PP();
|
||||
TDI_OP();
|
||||
TDI_PP();
|
||||
#else
|
||||
exp_byte = 0;
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
|
||||
//enable TDO as input
|
||||
TDO_IP_PU();
|
||||
|
||||
//PBJE initialization
|
||||
//set status & command to INIT
|
||||
pbje_status = PBJE_INIT;
|
||||
//only the host writes to command
|
||||
//pbje_command = PBJE_INIT;
|
||||
|
||||
//set NUM_CLK to max this engine can clock based on DATA_ARRAY bit size
|
||||
pbje_numclk = 0; //byte variable, 0 -> 256
|
||||
|
||||
//clear DATA_ARRAY
|
||||
for( i=0; i<PBJE_DATA_ARRAY_SIZE; i++) {
|
||||
pbje_data[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//actual JTAG engine
|
||||
//called periodically from main thread when jtag engine is on
|
||||
//this is where the actual JTAG communications are generated
|
||||
//main thread will call this routine so long as pbje_status != PBJE_OFF
|
||||
void jtag_run_pbje()
|
||||
{
|
||||
//status needs to be CMD_RX to start processing of new command
|
||||
if (pbje_status == PBJE_CMD_RX) {
|
||||
//host has issued a command
|
||||
//process the command and update status accordingly
|
||||
switch (pbje_command) {
|
||||
case PBJE_INIT:
|
||||
jtag_init_pbje();
|
||||
//status set in function
|
||||
break;
|
||||
case PBJE_SHUTDOWN:
|
||||
pbje_status = PBJE_OFF;
|
||||
break;
|
||||
|
||||
case PBJE_STATE_CHG: //data array holds TMS values to clock values bit packed, TDI undefined
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_state_change( DATA0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
case PBJE_TDI_SCAN: //ignore TDO 256max
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_scan( DATA0, 0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
case PBJE_TDO_SCAN0: //TDI = 0, TMS=0 256max
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_scan( FORCE0, DATA0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
case PBJE_TDO_SCAN1: //TDI = 1, TMS=0 256max
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_scan( FORCE1, DATA0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
//case PBJE_HALF_SCAN: //TDI = first half of data array, TDO = second, TMS=0 128max
|
||||
// pbje_status = PBJE_PROC;
|
||||
// pbje_scan( DATA0, DATA1 );
|
||||
// pbje_status = PBJE_DONE;
|
||||
// break;
|
||||
|
||||
case PBJE_FULL_SCAN: //TDI = entire data array, TDO dumped into array stomping TDI, TMS=0 256max
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_scan( DATA0, DATA0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
case PBJE_CLOCK0: //data not used, clock TMS=0 for NUMCLK
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_state_change( FORCE0 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
case PBJE_CLOCK1: //data not used, clock TMS=1 for NUMCLK
|
||||
pbje_status = PBJE_PROC;
|
||||
pbje_state_change( FORCE1 );
|
||||
pbje_status = PBJE_DONE;
|
||||
break;
|
||||
|
||||
//TODO
|
||||
//case PBJE_FREE_CLOCK0: //data not used, clock TMS=0 indefinely
|
||||
// pbje_status = PBJE_PROCESSED;
|
||||
// break;
|
||||
//case PBJE_FREE_CLOCK1: //data not used, clock TMS=1 indefinely
|
||||
// pbje_status = PBJE_PROCESSED;
|
||||
// break;
|
||||
//case PBJE_LONG_CLOCK0: //data contains 32bit uint for number of clocks, TMS=0, numclk not used
|
||||
// pbje_status = PBJE_PROCESSED;
|
||||
// break;
|
||||
//case PBJE_LONG_CLOCK1: //data contains 32bit uint for number of clocks, TMS=1, numclk not used
|
||||
// pbje_status = PBJE_PROCESSED;
|
||||
// break;
|
||||
|
||||
default: //unknown command
|
||||
pbje_status = PBJE_UNKN_CMD;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//change the state of JTAG state machine
|
||||
//tms data bit packed in data array unless forced 0/1
|
||||
//numclk contains number of tck clocks to perform
|
||||
//PRE/POST: TCK is low, all signals low (limit 5v non-tolerance with original kazzos)
|
||||
void pbje_state_change( uint8_t tms_data )
|
||||
{
|
||||
//numclk is a sticky value, don't modify!
|
||||
uint8_t clk_count = pbje_numclk;
|
||||
uint8_t cur_byte = 0;
|
||||
uint8_t cur_bit = 0;
|
||||
|
||||
|
||||
#ifndef STM_INL6
|
||||
exp_byte = 0;
|
||||
#endif
|
||||
|
||||
//force TMS if not using data array
|
||||
if( tms_data == FORCE0 ) {
|
||||
#ifdef STM_INL6
|
||||
TMS_LO();
|
||||
#endif
|
||||
} else if ( tms_data == FORCE1 ) {
|
||||
#ifdef STM_INL6
|
||||
TMS_HI();
|
||||
#else
|
||||
exp_byte = TMS_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef STM_INL6
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
|
||||
do{
|
||||
//if TMS isn't forced, should be in data array
|
||||
if( tms_data == DATA0 ) {
|
||||
if( pbje_data[cur_byte] & (1<<cur_bit) ) {
|
||||
#ifdef STM_INL6
|
||||
TMS_HI();
|
||||
#else
|
||||
exp_byte = TMS_MASK;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef STM_INL6
|
||||
TMS_LO();
|
||||
#else
|
||||
exp_byte = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef STM_INL6
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
|
||||
cur_bit++;
|
||||
if( cur_bit == 8) {
|
||||
cur_bit = 0;
|
||||
cur_byte++;
|
||||
}
|
||||
}
|
||||
|
||||
//clock in TMS value with rising edge of TCK
|
||||
#ifdef STM_INL6
|
||||
TCK_HI();
|
||||
#else
|
||||
exp_byte_temp = exp_byte | TCK_MASK;
|
||||
//need to send macro a single byte variable
|
||||
EXP_SET(exp_byte_temp);
|
||||
#endif
|
||||
|
||||
//may need to slow between edges.. depending on max TCK frequency...
|
||||
clk_count--;
|
||||
|
||||
//end cycle
|
||||
#ifdef STM_INL6
|
||||
TCK_LO();
|
||||
#else
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
|
||||
} while( clk_count != 0x00 ) ;
|
||||
|
||||
//restore TMS low
|
||||
#ifdef STM_INL6
|
||||
TMS_LO();
|
||||
#else
|
||||
EXP_SET(0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//scan data in & out of JTAG shift register
|
||||
//tms forced 0 as should be in SHIFT_DR/IR already, leave it there when done
|
||||
//tdi/tdo data in data array, ingored, or forced 0/1
|
||||
//numclk contains number of tck clocks to perform
|
||||
//PRE/POST: TCK is low, all signals low (limit 5v non-tolerance with original kazzos)
|
||||
void pbje_scan( uint8_t tdi_data, uint8_t tdo_data )
|
||||
{
|
||||
//numclk is a sticky value, don't modify!
|
||||
uint8_t clk_count = pbje_numclk;
|
||||
uint8_t cur_byte = 0;
|
||||
uint8_t cur_bit = 0;
|
||||
|
||||
//TDO data may stomp over the top of TDI data
|
||||
//need to temporily save tdi byte before it gets stomped
|
||||
uint8_t temp_byte = pbje_data[cur_byte];
|
||||
GPIO_PinMask tdo_read;
|
||||
|
||||
//force TMS low to remain in SHIFT-DR/IR state
|
||||
#ifdef STM_INL6
|
||||
TMS_LO();
|
||||
#else
|
||||
exp_byte = 0;
|
||||
#endif
|
||||
|
||||
//force TDI if not using data array
|
||||
if( tdi_data == FORCE0 ) {
|
||||
#ifdef STM_INL6
|
||||
TDI_LO();
|
||||
#else
|
||||
//TDI clear by default
|
||||
#endif
|
||||
} else if ( tdi_data == FORCE1 ) {
|
||||
#ifdef STM_INL6
|
||||
TDI_HI();
|
||||
#else
|
||||
exp_byte |= TDI_MASK;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef STM_INL6
|
||||
//output to EXP Flopflop for first time
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
do {
|
||||
|
||||
//if TDI isn't forced, should be in data array
|
||||
if( tdi_data == DATA0 ) {
|
||||
if( temp_byte & (1<<cur_bit) ) {
|
||||
#ifdef STM_INL6
|
||||
TDI_HI();
|
||||
#else
|
||||
exp_byte |= TDI_MASK;
|
||||
#endif
|
||||
} else {
|
||||
#ifdef STM_INL6
|
||||
TDI_LO();
|
||||
#else
|
||||
exp_byte &= ~TDI_MASK;
|
||||
#endif
|
||||
}
|
||||
#ifndef STM_INL6
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
}
|
||||
|
||||
//The first TDO bit should already be shifted out by now
|
||||
//it actually spit out on falling TCK edge of entering SHIFT-DR/IR
|
||||
//so it's effectively like we read TDO before TCK rising edge as
|
||||
//it was shifted out last cycle
|
||||
|
||||
//if TDO isn't ignored, need to store in data array
|
||||
if( tdo_data == DATA0 ) {
|
||||
|
||||
//if bit0, clear byte so we only have to set bits
|
||||
if( cur_bit==0 ) {
|
||||
pbje_data[cur_byte] = 0;
|
||||
}
|
||||
|
||||
//TDO value should now be shifted out
|
||||
TDO_RD( tdo_read ); //will be 0 if low, non-zero if high
|
||||
|
||||
if( tdo_read ) {
|
||||
//TDO was set, store it in data array
|
||||
pbje_data[cur_byte] |= 1<<cur_bit;
|
||||
}
|
||||
}
|
||||
|
||||
//clock in TMS & TDI value with rising edge of TCK
|
||||
#ifdef STM_INL6
|
||||
TCK_HI();
|
||||
#else
|
||||
exp_byte_temp = exp_byte | TCK_MASK;
|
||||
//need to send macro a single byte variable
|
||||
EXP_SET(exp_byte_temp);
|
||||
#endif
|
||||
|
||||
//may need to slow between edges.. depending on max TCK frequency...
|
||||
clk_count--;
|
||||
|
||||
//end cycle TDO shifted out on falling edge of TCK
|
||||
#ifdef STM_INL6
|
||||
TCK_LO();
|
||||
#else
|
||||
EXP_SET(exp_byte);
|
||||
#endif
|
||||
|
||||
//increment bit counter
|
||||
cur_bit++;
|
||||
if( cur_bit == 8) {
|
||||
cur_bit = 0;
|
||||
cur_byte++;
|
||||
temp_byte = pbje_data[cur_byte];
|
||||
}
|
||||
|
||||
} while( clk_count != 0x00 ) ;
|
||||
|
||||
//leave default condition low (better for lack of 5v tolerance)
|
||||
#ifdef STM_INL6
|
||||
TDI_LO();
|
||||
TMS_LO();
|
||||
#else
|
||||
EXP_SET(0);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
#ifndef _jtag_h
|
||||
#define _jtag_h
|
||||
|
||||
#include "pinport.h"
|
||||
#include "shared_dictionaries.h"
|
||||
#include "shared_errors.h"
|
||||
|
||||
extern GPIO_TypeDef *tdo_base;
|
||||
extern uint8_t tdo_pin;
|
||||
extern GPIO_TypeDef *tdi_base;
|
||||
extern uint8_t tdi_pin;
|
||||
extern GPIO_TypeDef *tms_base;
|
||||
extern uint8_t tms_pin;
|
||||
extern GPIO_TypeDef *tck_base;
|
||||
extern uint8_t tck_pin;
|
||||
|
||||
//main thread needs access to status to know when engine is running
|
||||
extern uint8_t pbje_status;
|
||||
|
||||
//macros for JTAG signals on pins mcu has direct access to, for now only INL6
|
||||
#ifdef STM_INL6
|
||||
|
||||
//TCK JTAG clock signal
|
||||
//TMS & TDI latched on rising edges, TDO updated on falling
|
||||
#define TCK_HI() tck_base->BSRR = 1<<tck_pin
|
||||
#define TCK_LO() tck_base->BRR = 1<<tck_pin
|
||||
#define TCK_OP() tck_base->MODER |= (MODER_OP<<(tck_pin*2))
|
||||
#define TCK_PP() tck_base->OTYPER &= ~(OTYPER_OD<<tck_pin)
|
||||
|
||||
//TMS JTAG mode input
|
||||
#define TMS_HI() tms_base->BSRR = 1<< tms_pin
|
||||
#define TMS_LO() tms_base->BRR = 1<< tms_pin
|
||||
#define TMS_OP() tms_base->MODER |= (MODER_OP<<(tms_pin*2))
|
||||
#define TMS_PP() tms_base->OTYPER &= ~(OTYPER_OD<< tms_pin)
|
||||
|
||||
//TDI JTAG data input
|
||||
#define TDI_HI() tdi_base->BSRR = 1<< tdi_pin
|
||||
#define TDI_LO() tdi_base->BRR = 1<< tdi_pin
|
||||
#define TDI_OP() tdi_base->MODER |= (MODER_OP<<(tdi_pin*2))
|
||||
#define TDI_PP() tdi_base->OTYPER &= ~(OTYPER_OD<< tdi_pin)
|
||||
|
||||
//TDI JTAG data output
|
||||
#define TDO_IP_PU() tdo_base->MODER &= ~(MODER_OP<<(tdo_pin*2)); tdo_base->PUPDR |= (PUPDR_PU<<(tdo_pin*2))
|
||||
#define TDO_RD(val) val = (tdo_base->IDR & (1<<tdo_pin))
|
||||
|
||||
#else //everything else (AVR_KAZZO & STM_ADAPTER)
|
||||
|
||||
|
||||
//EXPANSION PORT SUPPORT
|
||||
//write only byte wide port
|
||||
//TDO EXP0 not part of EXP PORT definition (because it's read/write and not behind flipflop)
|
||||
#define TDO_IP_PU() EXP0_IP_PU()
|
||||
#define TDO_RD(val) EXP0_RD(val)
|
||||
//TDI EXP1 (bit 0)
|
||||
#define TDI_MASK 0x01
|
||||
//TMS EXP2 (bit 1)
|
||||
#define TMS_MASK 0x02
|
||||
//TCK EXP3 (bit 2)
|
||||
#define TCK_MASK 0x04
|
||||
|
||||
//global byte used for byte wide right only EXPANSION port to support devices with EXP flipflops
|
||||
uint8_t exp_byte;
|
||||
uint8_t exp_byte_temp;
|
||||
|
||||
//signal macros for EXP PORT
|
||||
#define EXP_ALL_LO() exp_byte = 0x00; EXP_SET(0x00)
|
||||
#define EXP_ONLY_TMS_HI() exp_byte = TMS_MASK; EXP_SET(TMS_MASK)
|
||||
|
||||
|
||||
#endif //end AVR_KAZZO & STM_ADAPTER
|
||||
|
||||
uint8_t jtag_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata );
|
||||
|
||||
void jtag_init_pbje();
|
||||
void jtag_run_pbje();
|
||||
|
||||
|
||||
// false = 0 = ignore
|
||||
#define FORCE0 0x10 //0x1x -> force
|
||||
#define FORCE1 0x11
|
||||
#define DATA0 0x20 //0x2x -> data array
|
||||
//#define DATA1 0x21
|
||||
void pbje_state_change( uint8_t tms_data );
|
||||
void pbje_scan( uint8_t tdi_data, uint8_t tdo_data );
|
||||
|
||||
#endif
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include "usb.h"
|
||||
#include "io.h"
|
||||
#include "buffer.h"
|
||||
#include "jtag.h"
|
||||
|
||||
#ifdef AVR_CORE
|
||||
#include <avr/interrupt.h>
|
||||
|
|
@ -86,6 +87,9 @@ int main(void)
|
|||
//intialize i/o and LED to pullup state
|
||||
io_reset();
|
||||
|
||||
//initialize jtag engine to be off
|
||||
pbje_status = PBJE_OFF;
|
||||
|
||||
//=================
|
||||
//MAIN LOOP
|
||||
//=================
|
||||
|
|
@ -112,5 +116,12 @@ int main(void)
|
|||
//another thought would be to call usbPoll mid programming
|
||||
//a few times to prevent incoming data from being delayed too long
|
||||
update_buffers();
|
||||
|
||||
//if paul's basic jtag engine "PBJE" is running, main
|
||||
//thread needs to call engine at periodic intervals to keep it
|
||||
//running.
|
||||
if (pbje_status != PBJE_OFF) {
|
||||
jtag_run_pbje();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,9 @@ uint8_t pinport_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_
|
|||
#define NOP() do { __asm__ __volatile__ ("nop"); } while (0)
|
||||
|
||||
|
||||
//PIN MACROS
|
||||
////////////////////////////////
|
||||
// CONTROL (CTL) PORT PINS
|
||||
////////////////////////////////
|
||||
|
||||
// PC0 "MCO"
|
||||
#define MCO_IP_PU() CTL_IP_PU(MCObank, MCO)
|
||||
|
|
@ -166,4 +168,35 @@ uint8_t pinport_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_
|
|||
|
||||
// PC21 "FCAPU"
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// EXTRA (EXT) PORT PINS
|
||||
////////////////////////////////
|
||||
|
||||
// PE0 "A0"
|
||||
#define A0_IP_PU() EXT_IP_PU(A0bank, A0)
|
||||
#define A0_IP_FL() EXT_IP_FL(A0bank, A0)
|
||||
#define A0_OP() EXT_OP(A0bank, A0)
|
||||
#define A0_LO() EXT_SET_LO(A0bank, A0)
|
||||
#define A0_HI() EXT_SET_HI(A0bank, A0)
|
||||
#define A0_RD(val) EXT_RD(A0bank, A0, val)
|
||||
|
||||
#ifdef STM_CORE
|
||||
#define A0_OD() EXT_OD(A0bank, A0)
|
||||
#define A0_PP() EXT_PP(A0bank, A0)
|
||||
#endif
|
||||
|
||||
// PE1 "D0"
|
||||
#define D0_IP_PU() EXT_IP_PU(D0bank, D0)
|
||||
#define D0_IP_FL() EXT_IP_FL(D0bank, D0)
|
||||
#define D0_OP() EXT_OP(D0bank, D0)
|
||||
#define D0_LO() EXT_SET_LO(D0bank, D0)
|
||||
#define D0_HI() EXT_SET_HI(D0bank, D0)
|
||||
#define D0_RD(val) EXT_RD(D0bank, D0, val)
|
||||
|
||||
#ifdef STM_CORE
|
||||
#define D0_OD() EXT_OD(D0bank, D0)
|
||||
#define D0_PP() EXT_PP(D0bank, D0)
|
||||
#endif
|
||||
|
||||
#endif //end of file
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@
|
|||
#include <avr/wdt.h>
|
||||
#elif STM_CORE
|
||||
#include <stm32f0xx.h>
|
||||
//STM32 GPIO ports are effectively 16bits wide
|
||||
//Use this type when need an int to hold pin mask
|
||||
#define GPIO_PinMask uint16_t
|
||||
#endif
|
||||
|
||||
//This file contains pinout translations from AVR names to "kazzo" names
|
||||
|
|
@ -1126,5 +1129,156 @@ void software_AXL_CLK();
|
|||
|
||||
#endif //AVR_KAZZO or STM_ADAPTER
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// EXTRA (EXT) PORT
|
||||
//
|
||||
// This port is present on all devices, but all pins aren't necessarily available
|
||||
// Intention is for pins on this port to act similar to CONTROL PORT, but require
|
||||
// individual enabling as these pins may conflict with other ports. This is a port
|
||||
// that allows rules of other ports to be broken. For example a single address pin
|
||||
// can become bidirectional open drain; which doesn't fit the ADDRESS PORT definition.
|
||||
// Another use for this would be to establish a SPI port on a few DATA BUS pins.
|
||||
// Other things that make sense here are serial protocols which need conveinent pin
|
||||
// macros, but don't make any sense to have individual bit control from host PC.
|
||||
// The low level protocol is handled from the firmware side since you would never want
|
||||
// to bit bang these from the host.
|
||||
//
|
||||
// Restrictions: Great care must be used when utilizing this port, doing so will often
|
||||
// break other ports which the pins are shared with. Best to disable this port
|
||||
// when done with it to then allow the other port to be enabled and initialized.
|
||||
// Each pin (set) needs it's own enable, the EXT PORT doesn't get enabled with one
|
||||
// macro since typically only one pin (set) is of interest.
|
||||
// Directionality: Any allowed, defined separately for each pin
|
||||
// Driver: Any allowed, defined separately for each pin
|
||||
// Write/Output: Depends on pins, any allowed
|
||||
// Read/Input: Depends on pins, any allowed
|
||||
//
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
#endif
|
||||
#ifdef STM_INL6
|
||||
|
||||
// PE0 "A0" mcupinC0
|
||||
#define E0bank GPIOC
|
||||
#define E0 (0U)
|
||||
|
||||
// PE1 "D0" mcupinB2
|
||||
#define E1bank GPIOB
|
||||
#define E1 (2U)
|
||||
|
||||
// PE2 "D8" mcupinB10
|
||||
#define E2bank GPIOB
|
||||
#define E2 (10U)
|
||||
|
||||
// PE3 "D9" mcupinB11
|
||||
#define E3bank GPIOB
|
||||
#define E3 (11U)
|
||||
|
||||
// PE4 "D10" mcupinB12
|
||||
#define E4bank GPIOB
|
||||
#define E4 (12U)
|
||||
|
||||
|
||||
#endif //STM_INL6
|
||||
|
||||
|
||||
#ifdef STM_ADAPTER
|
||||
|
||||
// PE0 "A0" mcupinB2
|
||||
#define E0bank GPIOB
|
||||
#define E0 (2U)
|
||||
|
||||
// PE1 "D0" mcupinB8
|
||||
#define E1bank GPIOB
|
||||
#define E1 (8U)
|
||||
|
||||
#define E2nodef
|
||||
#define E3nodef
|
||||
#define E4nodef
|
||||
|
||||
#endif //STM_ADAPTER
|
||||
|
||||
|
||||
#ifdef AVR_KAZZO
|
||||
|
||||
// PE0 "A0" mcupinA0
|
||||
#define E0bank GPIOA
|
||||
#define E0 (0U)
|
||||
|
||||
// PE1 "D0" mcupinB0
|
||||
#define E1bank GPIOB
|
||||
#define E1 (0U)
|
||||
|
||||
#define E2nodef
|
||||
#define E3nodef
|
||||
#define E4nodef
|
||||
|
||||
#endif //AVR_KAZZO
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// PORT E pin mappings
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//STM8 SWIM PINS A0 & D0 depending on cartridge
|
||||
#define A0 E0
|
||||
#define A0bank E0bank
|
||||
|
||||
#define D0 E1
|
||||
#define D0bank E1bank
|
||||
|
||||
//JTAG pins for INL6
|
||||
#ifdef STM_INL6
|
||||
|
||||
//TDI
|
||||
#define D8 E2
|
||||
#define D8bank E2bank
|
||||
|
||||
//TMS
|
||||
#define D9 E3
|
||||
#define D9bank E3bank
|
||||
|
||||
//TCK
|
||||
#define D10 E4
|
||||
#define D10bank E4bank
|
||||
|
||||
#endif //JTAG INL6
|
||||
|
||||
#ifdef STM_CORE
|
||||
|
||||
#define EXT_IP_PU(bank, pin) bank->MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR |= (PUPDR_PU<<(pin*2))
|
||||
#define EXT_IP_FL(bank, pin) bank->MODER &= ~(MODER_OP<<(pin*2)); bank->PUPDR &= ~(PUPDR_PU<<(pin*2))
|
||||
#define EXT_OP(bank, pin) bank->MODER |= (MODER_OP<<(pin*2))
|
||||
#define EXT_OD(bank, pin) bank->OTYPER |= (OTYPER_OD<<(pin)) //open drain has no effect when pin is input
|
||||
#define EXT_PP(bank, pin) bank->OTYPER &= ~(OTYPER_OD<<(pin))
|
||||
#define EXT_SET_LO(bank, pin) bank->BRR = 1<<pin
|
||||
#define EXT_SET_HI(bank, pin) bank->BSRR = 1<<pin
|
||||
#define EXT_RD(bank, pin, val) val = (bank->IDR & (1<<pin))
|
||||
//NOTE: STM registers are 16bit "halfwords" so must provide a 16bit val
|
||||
|
||||
//each pin needs it's own enable macro
|
||||
#define EXT_A0_ENABLE() ADDR_EN_CLK() //unnecessarily enables both GPIO banks for STM adapter, oh well
|
||||
#define EXT_D0_ENABLE() DATA_EN_CLK()
|
||||
#define EXT_D8_10_ENABLE() DATA_EN_CLK()
|
||||
|
||||
#endif //STM_CORE
|
||||
|
||||
#ifdef AVR_CORE
|
||||
|
||||
#define EXT_IP_PU(bank, pin) bank->DDR &= ~(1<<pin); bank->PORT |= (1<<pin)
|
||||
#define EXT_IP_FL(bank, pin) bank->DDR &= ~(1<<pin); bank->PORT &= ~(1<<pin)
|
||||
#define EXT_OP(bank, pin) bank->DDR |= (1<<pin)
|
||||
#define EXT_SET_LO(bank, pin) bank->PORT &= ~(1<<pin)
|
||||
#define EXT_SET_HI(bank, pin) bank->PORT |= (1<<pin)
|
||||
#define EXT_RD(bank, pin, val) val = (uint16_t) (bank->PIN & (1<<pin))
|
||||
|
||||
//each pin needs it's own enable macro
|
||||
#define EXT_A0_ENABLE() //nothing to be done for AVR
|
||||
#define EXT_D0_ENABLE() //nothing to be done for AVR
|
||||
|
||||
|
||||
#endif //AVR_CORE
|
||||
|
||||
|
||||
|
||||
#endif //file end
|
||||
|
|
|
|||
|
|
@ -10,13 +10,13 @@
|
|||
//=================================================================================================
|
||||
|
||||
uint8_t swim_pin;
|
||||
uint16_t swim_mask;
|
||||
//uint16_t swim_mask;
|
||||
GPIO_TypeDef *swim_base;
|
||||
|
||||
/* Desc:Function takes an opcode which was transmitted via USB
|
||||
* then decodes it to call designated function.
|
||||
* shared_dict_swim.h is used in both host and fw to ensure opcodes/names align
|
||||
* Pre: Macros must be defined in firmware pinport.h
|
||||
* Pre: Macros must be defined in firmware pinport.h & swim.h
|
||||
* opcode must be defined in shared_dict_swim.h
|
||||
* Post:function call complete.
|
||||
* Rtn: SUCCESS if opcode found, error if opcode not present or other problem.
|
||||
|
|
@ -36,7 +36,7 @@ uint8_t swim_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *
|
|||
case SWIM_SRST:
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
//assumes low speed
|
||||
rdata[RD0] = swim_xfr( 0x0000, ((SWIM_WR<<16) | 4), swim_base, swim_mask); break;
|
||||
rdata[RD0] = swim_xfr( 0x0000, ((SWIM_WR<<16) | 4), swim_base, 1<<swim_pin); break;
|
||||
case WOTF:
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
rdata[RD0] = swim_wotf( SWIM_LS, operand, miscdata ); break;
|
||||
|
|
@ -64,6 +64,27 @@ uint8_t swim_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *
|
|||
|
||||
}
|
||||
|
||||
//Doesn't actually delay exact usec, but it's proportional which is good enough for SWIM activation
|
||||
void delay_us( uint16_t delay )
|
||||
{
|
||||
uint16_t i = 0;
|
||||
|
||||
delay = delay *4;
|
||||
|
||||
//calling and pin toggling overhead is 0.1usec
|
||||
|
||||
for( i=0; i<delay; i++) {
|
||||
NOP();
|
||||
NOP(); //with delay * 4, and 2x NOP, 10 -> 10.64us, 100 -> 100.62us, 1k -> 1.0001 ms including pin delay
|
||||
// NOP();
|
||||
// NOP(); //with delay * 4, adding this NOP, adds 84nsec per delay
|
||||
//NOP();
|
||||
//NOP(); //6x NOP, 48Mhz, delay = 10 -> 2.92usec + overhead
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void delay( uint16_t delay )
|
||||
{
|
||||
|
|
@ -85,43 +106,30 @@ void swim_activate()
|
|||
{
|
||||
uint16_t i;
|
||||
|
||||
// pinport_call( CTL_OP_, 0, swim_pin, 0);
|
||||
|
||||
//toggles in this manner take 4.55-4.6usec on AVR
|
||||
//toggles in this manner take 4.9-4.95usec on STM adapter
|
||||
//TODO probably should disable interrupts during this process as they would muck up timing
|
||||
|
||||
//pulse low for 16usec spec says 16usec
|
||||
//but looking at working programmers they do twice the delays below
|
||||
pinport_call( CTL_SET_LO_, 0, swim_pin, 0);
|
||||
delay(3*16);
|
||||
pinport_call( CTL_SET_HI_, 0, swim_pin, 0);
|
||||
SWIM_SET_LO();
|
||||
delay_us(16);
|
||||
SWIM_SET_HI();
|
||||
|
||||
//toggle high->low T=1msec 4x
|
||||
for( i = 0; i < 4; i++) {
|
||||
//STM adapter 720 = 500.9usec
|
||||
//TODO move this timed code into a timer to make timing more stable
|
||||
//between boards, pinport.c code, etc....
|
||||
#ifdef STM_INL6
|
||||
delay(3*719);
|
||||
#endif
|
||||
#ifdef STM_ADAPTER
|
||||
delay(3*720);
|
||||
#endif
|
||||
pinport_call( CTL_SET_LO_, 0, swim_pin, 0);
|
||||
delay(3*718);
|
||||
pinport_call( CTL_SET_HI_, 0, swim_pin, 0);
|
||||
delay_us(500);
|
||||
SWIM_SET_LO();
|
||||
delay_us(500);
|
||||
SWIM_SET_HI();
|
||||
}
|
||||
|
||||
//toggle high->low T=0.5msec 4x
|
||||
for( i = 0; i < 4; i++) {
|
||||
//STM adapter 358 = 256usec
|
||||
delay(3*356);
|
||||
pinport_call( CTL_SET_LO_, 0, swim_pin, 0);
|
||||
delay(3*355);
|
||||
pinport_call( CTL_SET_HI_, 0, swim_pin, 0);
|
||||
delay_us(250);
|
||||
SWIM_SET_LO();
|
||||
delay_us(250);
|
||||
SWIM_SET_HI();
|
||||
}
|
||||
|
||||
//pinport_call( CTL_IP_PU_, 0, swim_pin, 0);
|
||||
|
||||
|
||||
//wait for device to take swim_pin low for ~16usec
|
||||
|
|
@ -143,29 +151,28 @@ void swim_activate()
|
|||
*/
|
||||
void swim_reset()
|
||||
{
|
||||
//pinport_call( CTL_OP_, 0, swim_pin, 0);
|
||||
|
||||
//pulse low for 16usec spec says 16usec
|
||||
//but looking at working programmers they do very long resets
|
||||
pinport_call( CTL_SET_LO_, 0, swim_pin, 0);
|
||||
delay(3*16);
|
||||
pinport_call( CTL_SET_HI_, 0, swim_pin, 0);
|
||||
SWIM_SET_LO();
|
||||
delay_us(16);
|
||||
SWIM_SET_HI();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define mov_swim_mask_r0() __asm ("mov r0, %[val]" : : [val] "r" (swim_mask) : "r0" )
|
||||
#define mov_pushpull_r6() __asm ("mov r6, %[val]" : : [val] "r" (pushpull) : "r6" )
|
||||
#define mov_opendrain_r7() __asm ("mov r7, %[val]" : : [val] "r" (opendrain) : "r7" )
|
||||
|
||||
//BSRR 0x18
|
||||
#define str_r0_bset() __asm volatile ("strh r0, [%[mmio], #0x18]" : : [mmio] "r" (swim_base))
|
||||
//BRR 0x28
|
||||
#define str_r0_bres() __asm volatile ("strh r0, [%[mmio], #0x28]" : : [mmio] "r" (swim_base))
|
||||
//OTYPER 0x04
|
||||
#define pp_swim() __asm volatile ("strh r6, [%[mmio], #0x04]" : : [mmio] "r" (swim_base))
|
||||
#define od_swim() __asm volatile ("strh r7, [%[mmio], #0x04]" : : [mmio] "r" (swim_base))
|
||||
//#define mov_swim_mask_r0() __asm ("mov r0, %[val]" : : [val] "r" (swim_mask) : "r0" )
|
||||
//#define mov_pushpull_r6() __asm ("mov r6, %[val]" : : [val] "r" (pushpull) : "r6" )
|
||||
//#define mov_opendrain_r7() __asm ("mov r7, %[val]" : : [val] "r" (opendrain) : "r7" )
|
||||
//
|
||||
////BSRR 0x18
|
||||
//#define str_r0_bset() __asm volatile ("strh r0, [%[mmio], #0x18]" : : [mmio] "r" (swim_base))
|
||||
////BRR 0x28
|
||||
//#define str_r0_bres() __asm volatile ("strh r0, [%[mmio], #0x28]" : : [mmio] "r" (swim_base))
|
||||
////OTYPER 0x04
|
||||
//#define pp_swim() __asm volatile ("strh r6, [%[mmio], #0x04]" : : [mmio] "r" (swim_base))
|
||||
//#define od_swim() __asm volatile ("strh r7, [%[mmio], #0x04]" : : [mmio] "r" (swim_base))
|
||||
|
||||
#define NO_RESP 0xFF
|
||||
#define ACK 0x01
|
||||
|
|
@ -200,7 +207,6 @@ uint16_t append_pairity(uint8_t n)
|
|||
uint16_t swim_rotf(uint8_t speed, uint16_t addr)
|
||||
{
|
||||
uint32_t ack_data = 0;
|
||||
#ifdef STM_CORE
|
||||
|
||||
uint16_t data_pb;
|
||||
uint32_t spddir_len;
|
||||
|
|
@ -212,26 +218,26 @@ uint16_t swim_rotf(uint8_t speed, uint16_t addr)
|
|||
// 0b0_0011
|
||||
data_pb = 0x3000;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 4; //data + pairity ( '0' header not included)
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write N "number of bytes for ROTF"
|
||||
data_pb = 0x0180;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @E extended address of write
|
||||
//always 0x00 since targetting stm8s003 which only has one section
|
||||
data_pb = 0x0000;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @H high address of write
|
||||
data_pb = append_pairity( addr>>8 );
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @L high address of write
|
||||
|
|
@ -239,7 +245,7 @@ uint16_t swim_rotf(uint8_t speed, uint16_t addr)
|
|||
//this is a read xfr because device will output data immediately after
|
||||
//writting last byte of command info
|
||||
spddir_len = ((SWIM_RD|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
|
||||
//read DATA portion of write
|
||||
|
||||
|
|
@ -247,7 +253,6 @@ uint16_t swim_rotf(uint8_t speed, uint16_t addr)
|
|||
//any time NAK is recieved must resend byte
|
||||
end_swim:
|
||||
|
||||
#endif
|
||||
return ack_data;
|
||||
|
||||
|
||||
|
|
@ -256,7 +261,6 @@ end_swim:
|
|||
uint8_t swim_wotf(uint8_t speed, uint16_t addr, uint8_t data)
|
||||
{
|
||||
uint32_t ack_data = 0;
|
||||
#ifdef STM_CORE
|
||||
uint16_t data_pb;
|
||||
uint32_t spddir_len;
|
||||
//bit sequence:
|
||||
|
|
@ -267,49 +271,58 @@ uint8_t swim_wotf(uint8_t speed, uint16_t addr, uint8_t data)
|
|||
// 0b0_0101
|
||||
data_pb = 0x5000;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 4; //data + pairity ( '0' header not included)
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write N "number of bytes for ROTF"
|
||||
data_pb = 0x0180;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @E extended address of write
|
||||
//always 0x00 since targetting stm8s003 which only has one section
|
||||
data_pb = 0x0000;
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @H high address of write
|
||||
data_pb = append_pairity( addr>>8 );
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
if (ack_data != ACK) goto end_swim;
|
||||
|
||||
//write @L high address of write
|
||||
data_pb = append_pairity( addr );
|
||||
//writting last byte of command info
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
|
||||
//DATA portion of write
|
||||
data_pb = append_pairity( data );
|
||||
spddir_len = ((SWIM_WR|speed)<<16) | 9;
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, swim_mask);
|
||||
ack_data = swim_xfr( data_pb, spddir_len, swim_base, 1<<swim_pin);
|
||||
|
||||
//More bytes can be written
|
||||
//any time NAK is recieved must resend byte
|
||||
end_swim:
|
||||
|
||||
#endif
|
||||
return ack_data;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef AVR_CORE
|
||||
|
||||
//TODO write assembly function that runs on AVR core....
|
||||
uint32_t swim_xfr( uint16_t data_pb, uint32_t spddir_len, GPIO_TypeDef *swim_base, uint16_t swim_mask)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Desc:Transfer SWIM bit stream
|
||||
* Always outputs '0' as first bit for header "from host"
|
||||
* Will output len number of bits plus one for header
|
||||
|
|
|
|||
|
|
@ -7,7 +7,30 @@
|
|||
|
||||
extern uint8_t swim_pin;
|
||||
extern GPIO_TypeDef *swim_base;
|
||||
extern uint16_t swim_mask;
|
||||
//extern uint16_t swim_mask;
|
||||
|
||||
//macros
|
||||
#ifdef STM_CORE
|
||||
#define SWIM_HI() swim_base->BSRR = 1<<swim_pin
|
||||
#define SWIM_LO() swim_base->BRR = 1<<swim_pin
|
||||
#define SWIM_OD() swim_base->OTYPER |= (OTYPER_OD<<swim_pin)
|
||||
#define SWIM_PP() swim_base->OTYPER &= ~(OTYPER_OD<<swim_pin)
|
||||
//artificial strong pull-up push pull on posedge, then go back to default open drain
|
||||
#define SWIM_SET_HI() SWIM_HI();SWIM_OD()
|
||||
//default is open drain, so going low is simple
|
||||
#define SWIM_SET_LO() SWIM_LO();SWIM_PP()
|
||||
|
||||
#else //AVR_CORE
|
||||
//TODO AVR SWIM macros here
|
||||
#define SWIM_HI()
|
||||
#define SWIM_LO()
|
||||
#define SWIM_OD()
|
||||
#define SWIM_PP()
|
||||
//artificial strong pull-up push pull on posedge, then go back to default open drain
|
||||
#define SWIM_SET_HI() SWIM_HI();SWIM_OD()
|
||||
//default is open drain, so going low is simple
|
||||
#define SWIM_SET_LO() SWIM_LO();SWIM_PP()
|
||||
#endif
|
||||
|
||||
//must match swim.s .equ statements!!!
|
||||
#define SWIM_RD 0x01
|
||||
|
|
@ -26,6 +49,10 @@ uint8_t swim_wotf(uint8_t speed, uint16_t addr, uint8_t data);
|
|||
uint16_t append_pairity(uint8_t n);
|
||||
|
||||
//assembly functions from swim.s
|
||||
#ifdef STM_CORE
|
||||
extern uint32_t swim_xfr( uint16_t data_pb, uint32_t spddir_len, GPIO_TypeDef *swim_base, uint16_t swim_mask);
|
||||
#else //AVR_CORE
|
||||
uint32_t swim_xfr( uint16_t data_pb, uint32_t spddir_len, GPIO_TypeDef *swim_base, uint16_t swim_mask);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -121,6 +121,10 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
|
|||
rv[RETURN_ERR_IDX] = swim_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] );
|
||||
break;
|
||||
|
||||
case DICT_JTAG:
|
||||
rv[RETURN_ERR_IDX] = jtag_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] );
|
||||
break;
|
||||
|
||||
|
||||
case DICT_BUFFER:
|
||||
//just give buffer.c the setup packet and let it figure things out for itself
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -419,6 +419,59 @@ RETURN_DAT_IDX = 4
|
|||
|
||||
end
|
||||
|
||||
-- external call for jtag dictionary
|
||||
local function jtag( opcode, operand, misc, data )
|
||||
|
||||
if not op_jtag[opcode] then
|
||||
print("ERROR undefined opcode:", opcode, "must be defined in shared_dict_jtag.h")
|
||||
return nil
|
||||
end
|
||||
|
||||
if not operand then
|
||||
operand = 0
|
||||
elseif type(operand) == "string" then
|
||||
if not op_jtag[operand] then
|
||||
print("ERROR undefined operand:", operand, "must be defined in shared_dict_jtag.h")
|
||||
return nil
|
||||
end
|
||||
--decode string operands into
|
||||
operand = op_jtag[operand]
|
||||
end
|
||||
|
||||
if not misc then misc = 0 end
|
||||
|
||||
local wLength, ep = default_rlen_1_in(op_jtag[opcode.."rlen"])
|
||||
|
||||
local count
|
||||
count, data = usb_vend_xfr(
|
||||
-- ep, dictionary wValue[misc:opcode] wIndex wLength data
|
||||
ep, dict["DICT_JTAG"], ( misc<<8 | op_jtag[opcode]), operand, wLength, data)
|
||||
--print(count)
|
||||
local error_code, data_len
|
||||
if ep == USB_IN then
|
||||
error_code = data:byte(RETURN_ERR_IDX)
|
||||
data_len = data:byte(RETURN_LEN_IDX)
|
||||
end
|
||||
--print("error:", error_code, "data_len:", data_len)
|
||||
|
||||
assert ( (error_code == err_codes["SUCCESS"]), "\n ERROR!!! problem with opcode: " .. opcode .. " device error code: " .. error_code)
|
||||
|
||||
if data_len and data_len ~= (wLength - RETURN_LEN_IDX) then
|
||||
print("WARNING!! Device's return data length:", data_len, "did not match expected:", wLength-RETURN_LEN_IDX)
|
||||
end
|
||||
|
||||
--process the return data string and return it to calling function
|
||||
if data_len then
|
||||
return string_to_int( data:sub(RETURN_DATA, data_len+RETURN_DATA), data_len)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
local function buffer_payload_in( wLength, buff_num )
|
||||
|
||||
|
|
@ -594,6 +647,7 @@ op_operation = {}
|
|||
op_nes = {}
|
||||
op_snes = {}
|
||||
op_swim = {}
|
||||
op_jtag = {}
|
||||
err_codes = {}
|
||||
|
||||
-- Dictionary table definitions initialized by calling parser
|
||||
|
|
@ -606,6 +660,7 @@ create_dict_tables( op_operation, "../shared/shared_dict_operation.h")
|
|||
create_dict_tables( op_nes, "../shared/shared_dict_nes.h")
|
||||
create_dict_tables( op_snes, "../shared/shared_dict_snes.h")
|
||||
create_dict_tables( op_swim, "../shared/shared_dict_swim.h")
|
||||
create_dict_tables( op_jtag, "../shared/shared_dict_jtag.h")
|
||||
create_dict_tables( err_codes, "../shared/shared_errors.h")
|
||||
|
||||
-- functions other modules are able to call
|
||||
|
|
@ -614,6 +669,7 @@ dict.io = io
|
|||
dict.nes = nes
|
||||
dict.snes = snes
|
||||
dict.swim = swim
|
||||
dict.jtag = jtag
|
||||
dict.buffer = buffer
|
||||
dict.buffer_payload_in = buffer_payload_in
|
||||
dict.buffer_payload_out = buffer_payload_out
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
|
||||
-- create the module's table
|
||||
local jtag = {}
|
||||
|
||||
-- import required modules
|
||||
local dict = require "scripts.app.dict"
|
||||
|
||||
-- file constants
|
||||
|
||||
-- local functions
|
||||
local function wait_pbje_done( num_polls, debug )
|
||||
|
||||
local status
|
||||
|
||||
while( num_polls > 0 ) do
|
||||
|
||||
status = dict.jtag("GET_STATUS")
|
||||
if( status == op_jtag["PBJE_DONE"]) then
|
||||
if( debug) then print("PBJE done num polls left:", num_polls) end
|
||||
return true
|
||||
else
|
||||
if( debug) then print("PBJE wasn't done, status:", status) end
|
||||
end
|
||||
num_polls = num_polls - 1
|
||||
end
|
||||
|
||||
print("JTAG timed out while waiting for PBJE_DONE")
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
|
||||
local function run_jtag( debug )
|
||||
|
||||
dict.io("JTAG_INIT", "JTAG_ON_EXP0_3")
|
||||
--dict.jtag("SET_3B_DATA", 0x0201, 0x03 )
|
||||
--print("return data:", dict.jtag("GET_6B_DATA"))
|
||||
--print(dict.jtag("SET_CMD", "PBJE_STATE_CHG"))
|
||||
--print(dict.jtag("GET_CMD"))
|
||||
--print(dict.jtag("GET_STATUS"))
|
||||
|
||||
--first put/verify jtag statemachine is in RESET
|
||||
dict.jtag("SET_2B_DATA", 0xFFFF)
|
||||
dict.jtag("SET_NUMCLK", 8)
|
||||
rv = dict.jtag("SET_CMD_WAIT", "PBJE_STATE_CHG")
|
||||
--verify command was done
|
||||
if(rv ~= op_jtag["PBJE_DONE"]) then print("error JTAG not done, status: ", rv) end
|
||||
|
||||
|
||||
--by default jtag should be in IDCODE or BYPASS if IDCODE not present
|
||||
|
||||
--change to SCAN-DR state
|
||||
--reset-DRshift c4 m0010
|
||||
dict.jtag("SET_2B_DATA", 0x0002)
|
||||
dict.jtag("SET_NUMCLK", 4)
|
||||
rv = dict.jtag("SET_CMD_WAIT", "PBJE_STATE_CHG")
|
||||
--verify command was done
|
||||
if(rv ~= op_jtag["PBJE_DONE"]) then print("error JTAG not done, status: ", rv) end
|
||||
|
||||
--scan out 32bit IDCODE while scanning in 1's to TDI
|
||||
dict.jtag("SET_NUMCLK", 32)
|
||||
dict.jtag("SET_CMD", "PBJE_TDO_SCAN1")
|
||||
--verify done before updating PBJE values
|
||||
jtag.wait_pbje_done( 4, true )
|
||||
|
||||
rv = dict.jtag("GET_6B_DATA")
|
||||
print("return data:", string.format(" %X, ",rv))
|
||||
if( rv == 0x1281043 ) then
|
||||
-- Mach XO 256 01281043
|
||||
-- 4032v (01805043)
|
||||
-- 4064v (01809043)
|
||||
--
|
||||
-- 9536xl
|
||||
-- //Loading device with 'idcode' instruction.
|
||||
-- SIR 8 TDI (fe) SMASK (ff) ;
|
||||
-- SDR 32 TDI (00000000) SMASK (ffffffff) TDO (f9602093) MASK (0fffffff) ;
|
||||
--
|
||||
-- 9572xl
|
||||
-- //Loading device with 'idcode' instruction.
|
||||
-- SIR 8 TDI (fe) SMASK (ff) ;
|
||||
-- SDR 32 TDI (00000000) SMASK (ffffffff) TDO (f9604093) MASK (0fffffff) ;
|
||||
-- test read gives 59604093
|
||||
print("IDCODE matches MACHXO-256")
|
||||
else
|
||||
print("no match for IDCODE")
|
||||
end
|
||||
|
||||
--Mach XO verify ID code
|
||||
-- ! Check the IDCODE
|
||||
--
|
||||
-- ! Shift in IDCODE(0x16) instruction
|
||||
-- SIR 8 TDI (16);
|
||||
-- SDR 32 TDI (FFFFFFFF)
|
||||
-- TDO (01281043)
|
||||
-- MASK (FFFFFFFF);
|
||||
|
||||
-- --change to SCAN-IR state
|
||||
-- dict.jtag("SET_2B_DATA", 0x0006)
|
||||
-- dict.jtag("SET_NUMCLK", 5)
|
||||
-- dict.jtag("SET_CMD", "PBJE_STATE_CHG")
|
||||
-- --verify done before updating PBJE values
|
||||
-- jtag.wait_pbje_done( 4, true )
|
||||
--
|
||||
-- --scan in IDCODE instruction
|
||||
-- dict.jtag("SET_2B_DATA", 0x0016)
|
||||
-- dict.jtag("SET_NUMCLK", 8)
|
||||
-- dict.jtag("SET_CMD", "PBJE_TDI_SCAN")
|
||||
-- --verify done before updating PBJE values
|
||||
-- jtag.wait_pbje_done( 4, true )
|
||||
--
|
||||
-- --change to SCAN-DR state
|
||||
-- --shift-pause c2 m01
|
||||
-- --IRpause-DRshift c5 m00111
|
||||
-- --together c7 m001_1101 -> 0x1D
|
||||
-- dict.jtag("SET_2B_DATA", 0x001D)
|
||||
-- dict.jtag("SET_NUMCLK", 7)
|
||||
-- dict.jtag("SET_CMD", "PBJE_STATE_CHG")
|
||||
-- --verify done before updating PBJE values
|
||||
-- jtag.wait_pbje_done( 4, true )
|
||||
--
|
||||
--
|
||||
-- --scan out 32bit IDCODE while scanning in 1's to TDI
|
||||
-- dict.jtag("SET_NUMCLK", 32)
|
||||
-- dict.jtag("SET_CMD", "PBJE_TDO_SCAN1")
|
||||
-- --verify done before updating PBJE values
|
||||
-- jtag.wait_pbje_done( 4, true )
|
||||
--
|
||||
-- print("return data:", dict.jtag("GET_6B_DATA"))
|
||||
|
||||
end
|
||||
|
||||
-- global variables so other modules can use them
|
||||
|
||||
|
||||
-- call functions desired to run when script is called/imported
|
||||
|
||||
|
||||
-- functions other modules are able to call
|
||||
jtag.wait_pbje_done = wait_pbje_done
|
||||
jtag.run_jtag = run_jtag
|
||||
|
||||
-- return the module's table
|
||||
return jtag
|
||||
|
|
@ -27,7 +27,8 @@ ECODE.HERR = 0x09
|
|||
|
||||
local cur_CSR = 0x00
|
||||
local SWIM_CSR = 0x7F80
|
||||
local DEF_MAX_NAK = 8
|
||||
--local DEF_MAX_NAK = 8
|
||||
local DEF_MAX_NAK = 12 --8 wasn't enough especially for long strings of 0x00 -> 0xff or vice versa
|
||||
|
||||
-- local functions
|
||||
local function get_key_for_value( t, value )
|
||||
|
|
@ -184,8 +185,15 @@ local function swim_test()
|
|||
|
||||
--print("wotf :", dict.swim("WOTF_HS", 0x0000, 0x00))
|
||||
--high speed now, enable flag with true
|
||||
-- wotf(0x0000, 0x00, true)
|
||||
-- rotf(0x0000, true)
|
||||
rotf(0x0000, true, true)
|
||||
wotf(0x0000, 0x00, true, true)
|
||||
rotf(0x0000, true, true)
|
||||
wotf(0x0000, 0xFF, true, true)
|
||||
rotf(0x0000, true, true)
|
||||
wotf(0x0000, 0xA5, true, true)
|
||||
rotf(0x0000, true, true)
|
||||
wotf(0x0000, 0xC3, true, true)
|
||||
rotf(0x0000, true, true)
|
||||
-- rotf(0x0000, true)
|
||||
-- rotf(0x0000, true)
|
||||
-- rotf(0x0000, true)
|
||||
|
|
@ -263,13 +271,13 @@ local function swim_test()
|
|||
-- lock_flash_eeprom(true)
|
||||
-- --read it back
|
||||
|
||||
print("READ BACK DATA")
|
||||
local byte_addr = 0x0200
|
||||
while byte_addr < 0x0280 do
|
||||
rotf(byte_addr, true, true)
|
||||
|
||||
byte_addr = byte_addr + 1
|
||||
end
|
||||
-- print("READ BACK DATA")
|
||||
-- local byte_addr = 0x0200
|
||||
-- while byte_addr < 0x0280 do
|
||||
-- rotf(byte_addr, true, true)
|
||||
--
|
||||
-- byte_addr = byte_addr + 1
|
||||
-- end
|
||||
|
||||
--test by blinking LED via periph register access
|
||||
--v2 board has LED on hi_lo_sel PA2
|
||||
|
|
@ -306,10 +314,10 @@ end
|
|||
|
||||
local function start( debug )
|
||||
|
||||
dict.io("IO_RESET")
|
||||
--dict.io("IO_RESET")
|
||||
|
||||
dict.io("SNES_INIT")
|
||||
dict.io("SWIM_INIT", "SWIM_ON_EXP0")
|
||||
--dict.io("SNES_INIT")
|
||||
--dict.io("SWIM_INIT", "SWIM_ON_EXP0")
|
||||
dict.swim("SWIM_ACTIVATE")
|
||||
|
||||
--holds SWIM pin low for 16usec+ to reset SWIM comms incase of error
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ function main ()
|
|||
local erase = require "scripts.app.erase"
|
||||
local flash = require "scripts.app.flash"
|
||||
local swim = require "scripts.app.swim"
|
||||
local jtag = require "scripts.app.jtag"
|
||||
-- local crc32 = require "scripts.app.crc32"
|
||||
|
||||
local rv
|
||||
|
|
@ -40,7 +41,7 @@ function main ()
|
|||
-- rv = cart.detect(debug)
|
||||
|
||||
local force_cart = true
|
||||
cart_console = "SNES"
|
||||
cart_console = "NES"
|
||||
|
||||
if (force_cart or cart.detect_console(true)) then
|
||||
if cart_console == "NES" or cart_console == "Famicom" then
|
||||
|
|
@ -67,37 +68,78 @@ function main ()
|
|||
nes.read_flashID_prgrom_exp0(true)
|
||||
--try mapper 30 flash ID
|
||||
|
||||
--determined all that could about mapper board
|
||||
--set rom types and sizes
|
||||
--perform desired operation
|
||||
|
||||
jtag.run_jtag()
|
||||
|
||||
|
||||
--FLASHING:
|
||||
--erase cart
|
||||
erase.erase_nes( true )
|
||||
--open file
|
||||
local file
|
||||
file = assert(io.open("inltest.bin", "rb"))
|
||||
--determine if auto-doubling, deinterleaving, etc,
|
||||
--needs done to make board compatible with rom
|
||||
--flash cart
|
||||
flash.flash_nes( file, true )
|
||||
--close file
|
||||
assert(file:close())
|
||||
|
||||
--DUMPING:
|
||||
--create new file
|
||||
local file
|
||||
file = assert(io.open("dump.bin", "wb"))
|
||||
--dump cart into file
|
||||
dump.dump_nes( file, true )
|
||||
|
||||
--close file
|
||||
assert(file:close())
|
||||
|
||||
-- --Check for SWIM on A0
|
||||
-- dict.io("IO_RESET")
|
||||
--
|
||||
-- dict.io("SWIM_INIT", "SWIM_ON_A0")
|
||||
-- if swim.start(true) then
|
||||
-- --SWIM is now established and running at HIGH SPEED
|
||||
-- snes_swimcart = false --don't want to use SWIM pin to control flash /OE, use SNES RESET (EXP0) instead
|
||||
--
|
||||
-- -- swim.swim_test()
|
||||
--
|
||||
-- --swim.write_optn_bytes( true, true ) -- enable ROP, debug
|
||||
--
|
||||
-- --check if ROP set, allow clearing ROP and erasing CIC
|
||||
-- --blindly erase STM8 CIC for now by disabling ROP
|
||||
-- swim.disable_ROP_erase(true)
|
||||
--
|
||||
-- --open CIC file
|
||||
-- --local cic_file = assert(io.open("stm8_8KB_zero.bin", "rb"))
|
||||
-- --local cic_file = assert(io.open("stm8_8KB_0xff.bin", "rb"))
|
||||
-- local cic_file = assert(io.open("stm8_8KB_testpattern.bin", "rb"))
|
||||
--
|
||||
-- --write CIC file
|
||||
-- swim.write_flash( cic_file )
|
||||
--
|
||||
-- --close CIC file
|
||||
-- assert(cic_file:close())
|
||||
--
|
||||
-- -- reset STM8 CIC and end SWIM comms to it can execute what we just flashed
|
||||
-- swim.stop_and_reset()
|
||||
-- else
|
||||
-- print("ERROR problem with STM8 CIC")
|
||||
-- end
|
||||
--
|
||||
-- print("done flashing STM8 on A0")
|
||||
|
||||
dict.io("IO_RESET")
|
||||
|
||||
-- --determined all that could about mapper board
|
||||
-- --set rom types and sizes
|
||||
-- --perform desired operation
|
||||
|
||||
|
||||
-- --FLASHING:
|
||||
-- --erase cart
|
||||
-- erase.erase_nes( true )
|
||||
-- --open file
|
||||
-- local file
|
||||
-- file = assert(io.open("inltest.bin", "rb"))
|
||||
-- --determine if auto-doubling, deinterleaving, etc,
|
||||
-- --needs done to make board compatible with rom
|
||||
-- --flash cart
|
||||
-- flash.flash_nes( file, true )
|
||||
-- --close file
|
||||
-- assert(file:close())
|
||||
|
||||
-- --DUMPING:
|
||||
-- --create new file
|
||||
-- local file
|
||||
-- file = assert(io.open("dump.bin", "wb"))
|
||||
-- --dump cart into file
|
||||
-- dump.dump_nes( file, true )
|
||||
|
||||
-- --close file
|
||||
-- assert(file:close())
|
||||
|
||||
|
||||
-- dict.io("IO_RESET")
|
||||
|
||||
elseif cart_console == "SNES" then
|
||||
|
||||
snes_swimcart = nil
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ libusb_device_handle * open_usb_device( libusb_context *context, int log_level )
|
|||
if ( libusb_get_string_descriptor_ascii( handle,
|
||||
desc.iManufacturer, (unsigned char *)manf, sizeof(manf) ) > LIBUSB_SUCCESS) {
|
||||
if (log_level>0) printf("manf_ascii: %s\n",manf);
|
||||
} else {
|
||||
printf("\nMatching PID/VID found and opened, but unable to communicate to device, verify drivers installed!!!\n\n");
|
||||
}
|
||||
}
|
||||
if (desc.iProduct) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@
|
|||
#define SWIM_ON_EXP0 0x02 //SNES carts
|
||||
#define SWIM_ON_D0 0x03 //NES discrete CICOprocessor
|
||||
|
||||
|
||||
//JTAG protocol init
|
||||
//4 wire serial protocol for configuring and communicating to programmable logic device cores
|
||||
//different INL boards have this signal on different pins or virtual CIC ports
|
||||
//So initialization must provide pins to perform all subsequent
|
||||
//communications with
|
||||
#define JTAG_INIT 4
|
||||
// don't define 0x00 to protect from forgetting to pass jtag lane
|
||||
#define JTAG_ON_EXP0_3 0x01 //Most NES carts with CPLDs
|
||||
|
||||
//Test EXP0 drive with pull up
|
||||
//This is an important test if reling on pulling up EXP0 pin to drive the cart's pin.
|
||||
//EXP0 is used for various things and may have pull up/down of it's own or significant load
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
#ifndef _shared_dict_jtag_h
|
||||
#define _shared_dict_jtag_h
|
||||
|
||||
//define dictionary's reference number in the shared_dictionaries.h file
|
||||
//then include this dictionary file in shared_dictionaries.h
|
||||
//The dictionary number is literally used as usb transfer request field
|
||||
//the opcodes and operands in this dictionary are fed directly into usb setup packet's wValue wIndex fields
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
// JTAG DICTIONARY
|
||||
//
|
||||
// opcodes contained in this dictionary must be implemented in firmware/source/jtag.c
|
||||
//
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
|
||||
|
||||
//JTAG opcodes
|
||||
#define GET_CMD 1 //RL=3
|
||||
#define SET_CMD 2 //command is only writable by host, read only by engine
|
||||
|
||||
#define SET_CMD_WAIT 3 //RL=3 returns command status effectively set, perform, and get/return command
|
||||
//set command and force device to perform command immediately
|
||||
//should only be used for quick commands like state change, not for long scan in/outs
|
||||
|
||||
#define GET_STATUS 4 //RL=3 only the engine can write to status, ready only by host
|
||||
#define SET_NUMCLK 5 //numclk is only writable by host, read only by engine
|
||||
#define SET_2B_DATA 7
|
||||
#define GET_6B_DATA 8 //RL=8
|
||||
|
||||
|
||||
//PBJE Paul's Basic Jtag engine commands & status'
|
||||
#define PBJE_STATE_CHG 0x01 //data array holds TMS values to clock values bit packed, TDI undefined
|
||||
#define PBJE_TDI_SCAN 0x02 //ignore TDO 256max
|
||||
#define PBJE_TDO_SCAN0 0x03 //TDI = 0, TMS=0 256max
|
||||
#define PBJE_TDO_SCAN1 0x04 //TDI = 1, TMS=0 256max
|
||||
#define PBJE_HALF_SCAN 0x05 //TDI = first half of data array, TDO = second, TMS=0 128max
|
||||
#define PBJE_FULL_SCAN 0x06 //TDI = entire data array, TDO dumped into array stomping TDI, TMS=0 256max
|
||||
#define PBJE_CLOCK0 0x07 //data not used, clock TMS=0 for NUMCLK
|
||||
#define PBJE_CLOCK1 0x08 //data not used, clock TMS=1 for NUMCLK
|
||||
#define PBJE_FREE_CLOCK0 0x09 //data not used, clock TMS=0 indefinely
|
||||
#define PBJE_FREE_CLOCK1 0x0A //data not used, clock TMS=1 indefinely
|
||||
#define PBJE_LONG_CLOCK0 0x0B //data contains 32bit uint for number of clocks, TMS=0, numclk not used
|
||||
#define PBJE_LONG_CLOCK1 0x0C //data contains 32bit uint for number of clocks, TMS=1, numclk not used
|
||||
|
||||
|
||||
//Statuses & commands to get to the status
|
||||
#define PBJE_INIT 0x80
|
||||
#define PBJE_PROC 0x81
|
||||
#define PBJE_DONE 0x82
|
||||
#define PBJE_CMD_RX 0x83
|
||||
#define PBJE_UNKN_CMD 0xEE
|
||||
#define PBJE_OFF 0xF0
|
||||
#define PBJE_SHUTDOWN 0xFF
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -112,4 +112,13 @@
|
|||
//dictionary used to control swim communications
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
#define DICT_JTAG 9
|
||||
#include "shared_dict_jtag.h"
|
||||
//dictionary used to control jtag communications
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,12 +10,14 @@
|
|||
|
||||
#define ERR_UNKN_SWIM_OPCODE 130
|
||||
|
||||
#define ERR_UNKN_JTAG_OPCODE 135
|
||||
|
||||
#define ERR_UNKN_PP_OPCODE 140
|
||||
#define ERR_CTL_PIN_NOT_PRESENT 141
|
||||
|
||||
#define ERR_UNKN_IO_OPCODE 150
|
||||
#define ERR_UNKN_SWIM_LANE 151
|
||||
#define ERR_UNKN_JTAG_LANE 152
|
||||
|
||||
#define ERR_UNKN_NES_OPCODE 160
|
||||
//
|
||||
|
|
|
|||
Loading…
Reference in New Issue