UNO R3: Developing a Single-Stepping Routine for ATmega328P without relying on JTAG Interface which contributes to flash wear

@westfw @gilhad @EmilyJane

Let's explore whether we can implement @westfw's proposed approach (Fig-1) to achieve single-stepping on the ATmega328P running on the Arduino Uno R3, thereby avoiding the Flash erase-and-reprogram method used by the JTAG interface for single-step debugging.

Figure-1:

Sample Instructions to be single stepped:

                                       `.org $3000`
003000 e000                      START:	ldi r16, 0x00
003001 b904                      		out	ddrb, r16      ; PB0 - PB5 are inputs
003002 9a25                      		sbi	ddrb, 5        ;pb5 = DPin-13 is output
                                 
003003 e200                      		ldi	r16, 0b100000
003004 b905                      		out	portb, r16     ; onboard L is On
003005 940c 3005                 HERE:	jmp	HERE           ; wait here for ever

Figure-1:

Intel-HEX File:

:020000020000FC
:0E60000000E004B9259A00E205B90C940530C1
:00000001FF

Fields of an Intel-Hex Frame:
: 0E 6000 00 00E0 04B9 259A 00E2 05B9 0C94 0530 C1
(a) (b) (c) (d) (e)------------------------------> (f)
a: Beginning of a new frame
b: Number of bytes to be transmitted in (e) (14 bytes)
c: Byte location address in flash from which the byes of (e) to be stored
d: 00 indicates there are more Intel-HEX frames to be transmitted
e: Actual data bytes in the frame (here: 0x0E = 14 bytes)
f: Check sum computed over the bytes from (b) to (e)
==> 0E + 60 + 00 + 00 + 00 + E0 + 04 + B9 + 25 + 9A + 00 + E2 + 05 + B9 + 0C + 94 + 05 + 30

==> 053F
==> (discard carries) 3F
==>(take 2's complement) C1

Figure-2:

Procedures:
1. The above sample instrucion code will be loaded into the MCU of the UNO R3 using a ROM Programmer statrting at word locaion 0x3000 (byte location: 0x6000) of the flash so that they stay far away from the application program code related to S/S (Fig-3) routine.


Fig-3: Memoy Spaces of UNO R3

2. Develop S/S Routine using IDE and upload it into UNO R3.
(1) Press RESET Button; LCD will show: 3000 - E000
(2) Press S/S Buton; LCD will show: 3001 - B904
(3) Press RESET Button; LCD will show: 3002 - 9A25
(4) Press S/S Buton; LCD will show: 3003 - E200
(5) Press RESET Button; LCD will show: 3004 - B905
(6) Press S/S Buton; LCD will show: 3005 - 940C
(7) Let us Check that onboard L has turned On.

3. Developing Sketch for S/S Routne
(1) Create sketch for the MCU to read the 16-bit content of word location 0x3000 (E000) and show it on Serial Monitor/LCD.

...in progress

I won't be able to participate as my UNO R3 doesn't have a JTAG interface.
Sorry.

Please, read the itle of this thread.

I am not using JTAG Interface to S/S the 328P of the UNO R3 Board; instead as suggested by @westfw, I am trying to implement a mechanism that is used for the S/S of 8051 (Fig-1, 2).


Fugure-1:


Figure-2:

Will you be able to examine and change processor registers and data memory after each instruction is executed?

If the scheme of post #2 works for stepping the PC through the instructions, then other functions could be slowly added with a 4x4 Keypad. I have experienec in implemeting S/S for 89S52 of MCS-51 Family (Fig-1).


Figure-1:

I use simulators for this single stepping, so I do not feel the urge develope new method.

And I am just slow and hard learning CPLD programming, as I need resolve GLUE for my new 8bit computer with HD6309 (this is, for what my atmega2560 based graphic card (which I was writing here about mainly) is dedicated (all the FORTH is hypertrophed debuging tool :slight_smile: ))

Which takes most of my creative ability and power.

But if I would need to debug some part of my code by single instructions on real hardware, I would probabelly try other approach:

  1. converse the code to assembly with labels

  2. add call debug after each label and instruction (except CPSE, SBRC/S, SBIC/S and such)

  3. ???

  4. profit!

(so no FLASH wear, no HW needed, just simple text tool and modified make chain :slight_smile: )

Serial.print() is a super debugger tool for the uploaded sketch in UNO R3.

Yes, it is :slight_smile:

And this is the same approach on assembly level, with possibility to use automated tools to do that. And the debug routine may be interactive too, reading commands from some source (say keypad) and decide which register/memory modify, or at what address to continue, or if let it go automatically until next return or whatever else would Debug Monitor have to offer :slight_smile:

I have little doubt that @westfw's approach is viable.

Help me understand what the purpose would be of single stepping the processor through its program. When the program is stopped what would you then be able to do? Can you suggest a way to examine and change I/O registers, RAM locations, etc like a regular debugger can do?

In many educational institutions, the 8085, 8086, and 89S52 are taught to help students grasp the fundamentals of microprocessors and CISC microcontrollers using commercially available training kits equipped with single-step (S/S) capability for examining and modifying register contents.

However, I have not found an AVR trainer designed in a similar manner for educational institutions. Instead, the Arduino UNO R3 is widely used with C++ and the Arduino IDE for microcontroller interfacing and system design.

In view of the above, developing a single-step (S/S) scheme for the AVR would be a worthwhile exercise, demonstrating that such a capability can indeed be implemented without dedicated hardware support.

1.

There are valid technical challenges, and persistent efforts should be made to overcome them. Having explored the possibilities thoroughly, we may conclude that an idea cannot be transformed into reality?

2.

In single-stepping mode, one instruction is executed, after which control returns to the keypad, allowing the user to examine and modify the contents of MCU registers, inspect the EEPROM data memory, and examine/modify the SRAM contents.

Fig-1 shows the keypad layout of an 8086 trainer. By pressing the S/S (Single-Step) key, the user can execute one instruction at a time and then examine/edit the contents of the CPU registers before proceeding to the next instruction.


Figure-1:

How do you propose to do that for an ATmega328P?

I will follow the same procedures that I used to develop the single-step (S/S) scheme for my 89S52 trainer, which may or may not work for AVR.

I would like to begin with the task outlined in Post #1.

It will not.

Go ahead and solve the proposed task but there will be nothing to follow it. The AVR doesn't have a way to insert breakpoints in its program other than via the one wire debug which will wear the flash. If you stop the AVR, how will you command it to execute tasks from the keypad without writing some kind of program into it and using some of its I/O to communicate with the keypad. Doable in some sense of the word but hardly practical as a debugging tool.

I claim that there is almost 98% possibility that it will! @westfw's approach is viable with confidence!


Figure-1:

`                                       .org $3000`
003000 e000                      START:	ldi r16, 0x00
003001 b904                      		out	ddrb, r16      ; PB0 - PB5 are inputs
003002 9a25                      		sbi	ddrb, 5        ;pb5 = DPin-13 is output
                                 
003003 e200                      		ldi	r16, 0b100000
003004 b905                      		out	portb, r16     ; onboard L is On
003005 940c 3005                 HERE:	jmp	HERE           ; wait here for ever

Principles of Single Stepping the above sample instructions:
1. Clear the I-bit (Global Interrupt Enable bit).

2. Push the word address (0x3000) of the first instruction onto the stack.

3. Use DPin-4 (Fig-1) to generate a High-to-Low pulse on DPin-2 so that the INT0-pin sees a falling trigger signal. As a result, the INTF0 flag will be set. Since the I-bit = 0, the MCU will not vector to the ISRINT0 interrupt service routine.

4. Execute the RETI instruction artificially. The PC is restored with the value 0x3000 from the stack, and the I-bit is automatically set.

5. The instruction at address 0x3000 is executed. Immediately after its execution, the MCU detects that the INTF0 flag is set, pushes the return address (0x3001) onto the stack, and vectors to ISRINT0.

6. In the ISRINT0() routine, the user performs the required tasks, such as examining or editing MCU registers, updating the display, adjusting the stack pointer (SP), and then returns to Step 3 manually (jmp L without executing RETI) to execute the next instruction at 0x3001, 0x3002, and so on.

Do you see any logical flaw in the above single-step (S/S) implementation strategy? The MCU is neither halted nor trapped in a loop; instead, it continues normal execution and periodically enters ISRINT0() to provide the single-step service.

Testing:
... in progess

In post #12, I asked how you would examine and modify the contents of MCU registers, inspect the EEPROM data memory, and examine/modify the SRAM contents after each single step. You still refuse to address that.

As shown in Post #15, all of those tasks (provided they are implementable) can be carried out within the ISRINT0() routine. The primary objective is to single-step the MCU, and that objective has, at least theoretically, been achieved. The remaining tasks are implementation details.

So to debug a sketch, you have to include a library with your interrupt service routines as well as make sure you have in interrupt pin available as well as pins for the 4 X 4 keypad and some sort of display.

Seems a little intrusive.

It was stated up front that @westfw's idea was doable. What is in question is whether or not it enables one to make a debugger.

I'll stick with the $16 ATmega328P Xplained Mini board from Microchip with the Arduino shield connectors if I want to have a debugger that doesn't wear out flash.