If you find out new details about the OCD commands, please report them to the Free AVR ICE project.


 AVR OCD (On Chip Debug) Documentation
 Note: this information is retrieved from public domain information.
 It is partially guessed only, and also not complete.
 Described here are only AVR OCD "Private" Commands (JTAG Instructions 8,9,A,B).
 Only commands and status bits are described that are actually verified on real silicon.
 

AVR Flash Programming using JTAG
 Copyleft 2003 Nugis Foundation.

AVR JTAG OCD (Private) Commands

Document Date 05 April 2003

JTAG Instruction 0x08 - Force Break

JTAG Instruction 0x09 - Run

JTAG Instruction 0x0A - Execute AVR Instruction (2 Words!)

 use 0x0A, SDR 0xFFFF0000 to read PC (actually returns PC+2 or PC+4)

JTAG Instruction 0x0B - Access OCD Registers

 there are total 16 Addressable Registers
 after IR next DRSHIFT is RW Flag (1=Write) + 4 Bits Address
 those Data in Instruction is 21 (5 + 16) bits
 note for read operation OCD Address need to be pre latched!

Register 0 PSB0

Register 1 PSB1

Register 2 PDMSB

Register 3 PDSB

Register 8 Break Control Register (BCR)

 Bit  rw  Description 
 D15  rw  1=Enable Timers to Run during Break 
 D14  rw  1=PC is read as +4 not +2 after break ? 
 D13  rw  1=Break on change Flow ?! 
 D12  rw  1=Enable PSB0 
 D11  rw  1=Enable PSB1 
 D10  rw  1=Enable PDMSB as single break 
 D9  rw  1=Enable Mask in Break Comparison 
 D8  rw  1= 
 D7  rw  1=* 
 D6  rw  1= 
 D5  rw  1= 
 D4  rw  1=* 
 D3  rw  1=* 
 D2  rw  1= 
 D1-0  r  (read as 0) 
 * note when D7, D4, D3 are all set then PDSB is enabled s Program Break

Register 9 - Break Status Register (BSR)

 Bit  rw  Description 
 D15-D8  r   
 D7  r  1=Break on change flow 
 D6  r  1=Break on PSB0 (Reg0) 
 D5  r  1=Break on PSB1 (Reg1) 
 D4  r  1=Break on PDMSB (Reg2 as single break) 
 D3  r  1=Break on PDSB (Reg3) 
 D2  r  1=Break on ? (has been seen) 
 D1  r  1=Break forced by OCD (Instr 8) 
 D0  r  1=Break by AVR Break Instruction (0x9598) 

Register C - OCDR Readback

 Bit  rw  Description 
 D15-8  rw  OCDR 7..0 
 D7-0  r  unused (read as 0) 

Register D - Control and Status Register

 Bit  rw  Description 
 D15  rw  1=Enable OCDR 
 D14  rw  1=? 
 D13-D5  r   
 D4  r  1=OCDR written by AVR and not read by OCD 
 D3  r  1=Reset not active 
 D2  r  1=Reset not active 
 D1-0  r   

Test Program (JAM)

it enables access to OCDR, and then writes a constant to OCDR (using 0xA exec-avr-insts) and then reads and displays OCDR contents

NOTE "MAX_FREQ" "100000";
IRSTOP IDLE;
   DRSTOP IDLE;
ACTION read_idcode = header RECOMMENDED,
   check_chain RECOMMENDED,
   exiting;
DATA data_chain;
   BOOLEAN idval[32];
'**********************************
   INTEGER ilen = 4; ' IR length is 4
   INTEGER scanlen = 141; ' Boundary Scan lenght is 141 for ATmega16
'****************************************************
   ' AVR JTAG Commands
   '****************************************************
   '
   ' JTAG Mandatory commands
   '
   BOOLEAN extest[ilen] = $0;
   '
   ' JTAG IDCODE command (see IEEE 1149.1)
   '
   BOOLEAN idcode[ilen] = $1;
   BOOLEAN sample_preload[ilen] = $2;
   '
   ' AVR JTAG Programming Commands (fully documented in Atmel Docs!)
   '
   BOOLEAN prog_enable[ilen] = $4; ' 
   BOOLEAN prog_commands[ilen] = $5; ' 
   BOOLEAN prog_preload[ilen] = $6; ' 
   BOOLEAN prog_pageread[ilen] = $7; ' 
   '
   ' AVR JTAG OCD "Private" commands (need NDA and Atmel Approval!)
   '
   '
   ' Command 0x8: 
   '
   BOOLEAN avr_08[ilen] = $8; ' 08 Private
   '
   ' Command 0x9: Release from Break?
   '
   BOOLEAN avr_09[ilen] = $9; ' 09 Private
   '
   ' Command 0xA: Execute AVR Instruction
   '
   ' IRSCAN 4, $A;
   ' DRSCAN 16, instr_1
   ' ..
   ' DRSCAN 16, instr_n
   '
   BOOLEAN avr_instr[ilen] = $A; ' 0A Private
   '
   ' Command 0xB: Read/Write internal Addres Space
   '
   '
   ' IRSCAN 4, $B;
   ' DRSCAN n?, ADDR_SPACE_SELECTOR+RW_FLAG
   ' DRSCAN 16,addr?
   ' DRSCAN 16,data?
' B:C - Read OCDR
   ' IRSCAN 4, $B;
   ' DRSCAN n, $0C;
   ' DRSCAN 16, $0000, CAPTURE OCDR[15..0];
BOOLEAN avr_comm[ilen] = $B; ' 0B Private
   '
   ' JTAG OCD "Public" Command: RESET_AVR
   ' DR is 1 bit wide, "1" is hold in Reset, "0" means Run    normal
   ' notice execution of 
   ' IRSCAN 3, $C; 
   ' DRSCAN 1, $1;
   ' Clears the sysclk counter always, Clears the AVR Core always
   ' Notice while JTAG_AVR_RESET is active, core is not executing
   ' but the peripherals are not hold in reset, that is command
   ' 0xA will write to peripherals
   '
   BOOLEAN avr_reset[ilen] = $C; ' 0C Reset, one bit, 1=RESET
' Commands 0x3, 0xD, 0xE are not implemented.
'
   ' JTAG Mandatory command, place TAP controller in "Bypass"
   '
   BOOLEAN bypass[ilen] = $F;
BOOLEAN comm [32];
   BOOLEAN b16 [16];
   BOOLEAN b24 [24];
   BOOLEAN b32 [32];
BOOLEAN ocd [40];
BOOLEAN scanr [scanlen]; ' Boundary Scan Register
   BOOLEAN instr [16]; ' Instruction
   BOOLEAN tick [16]; ' Clock Ticks
   ENDDATA;
PROCEDURE header;
   PRINT "******************************************************************************";
   PRINT " AVR JTAG OCD sniffer! ";
   ENDPROC;
PROCEDURE print16 USES data_chain;
   PRINT "B16= ", b16[15],b16[14],b16[13],b16[12],b16[11],b16[10],b16[9],b16[8],    b16[7],b16[6],b16[5],b16[4],b16[3],b16[2],b16[1],b16[0];
   ENDPROC;
PROCEDURE print_ocd USES data_chain;
   PRINT "OCD= ", ocd[39],ocd[38],ocd[37],ocd[36],ocd[35],ocd[34],ocd[33],ocd[32],    " ", ocd[31],ocd[30],ocd[29],ocd[28],ocd[27],ocd[26],ocd[25],ocd[24],    " ", ocd[23],ocd[22],ocd[21],ocd[20],ocd[19],ocd[18],ocd[17],ocd[16],    " ", ocd[15],ocd[14],ocd[13],ocd[12],ocd[11],ocd[10],ocd[9],ocd[8],    " ", ocd[7],ocd[6],ocd[5],ocd[4],ocd[3],ocd[2],ocd[1],ocd[0];
   ENDPROC;
   PROCEDURE print_port USES data_chain;
   ' INTEGER i_32;
   ' FOR i_32 = 0 to scanlen-1;
   ' scanr[0] = 0;
   ' NEXT i_32;
 scanr[135] = 0;
   scanr[132] = 0;
 IRSCAN ilen, sample_preload[3..0];
   ' Boundary Scan
   DRSCAN scanlen, scanr[(scanlen-1)..0], CAPTURE scanr[(scanlen-1)..0];
 ' Print PORTA
   PRINT "PORTA ", scanr[23],scanr[20],scanr[17],scanr[14],scanr[11],scanr[8],scanr[5],scanr[2];
   PRINT "DDRA ", scanr[22],scanr[19],scanr[16],scanr[13],scanr[10],scanr[7],scanr[4],scanr[1];
 IF (scanr[72] == 1) THEN PRINT "RESET HIGH";
   IF (scanr[72] == 0) THEN PRINT "RESET LOW";
' PRINT "OSC: ", scanr[66],scanr[65],scanr[64],scanr[63];
   ENDPROC;
   PROCEDURE reset_avr USES data_chain;
   IRSCAN ilen, avr_reset[3..0];
   DRSCAN 1, $1;
   ENDPROC;
PROCEDURE exec_avr USES data_chain;
   IRSCAN ilen, avr_instr[3..0];
   DRSCAN 16, instr[15..0];
   ENDPROC;
   PROCEDURE check_chain USES data_chain, print16, print_ocd, exec_avr, reset_avr,    print_port;
   PRINT "******************************************************************************";
 IRSCAN ilen, avr_reset[3..0];
   DRSCAN 1, $1;
 IRSCAN ilen, avr_reset[3..0];
   DRSCAN 1, $0;
 WAIT IDLE, 7000 USEC, IDLE;
 PRINT "TEST OCDR";
   PRINT "******************************************************************************";
 IRSCAN ilen,avr_comm[3..0]; ocd[4..0] = $0D; DRSCAN 5, ocd[4..0]; 
   ocd[39..0] = $1D8000; DRSCAN 21, ocd[20..0];
 WAIT IDLE, 7000 USEC, IDLE;
 instr[15..0] = $EF05; CALL exec_avr; instr[15..0] = $BF01; CALL exec_avr;
 IRSCAN ilen,avr_comm[3..0]; ocd[4..0] = $0C; DRSCAN 5, ocd[4..0]; 
   ocd[39..0] = $0000000000; DRSCAN 16, ocd[15..0], CAPTURE ocd[15..0]; CALL print_ocd;
 instr[15..0] = $EA06; CALL exec_avr; instr[15..0] = $BF01; CALL exec_avr;
 IRSCAN ilen,avr_comm[3..0]; ocd[4..0] = $0C; DRSCAN 5, ocd[4..0]; 
   ocd[39..0] = $0000000000; DRSCAN 16, ocd[15..0], CAPTURE ocd[15..0]; CALL print_ocd;
   ENDPROC;
   PROCEDURE exiting;
   PRINT "******************************************************************************";
   EXIT (0);
   ENDPROC;