Select Page

UART based debugger

Topic:

UART based debugger


Motivation:

To build a software based debugger which is cheap in comparison with sophisticated DEBUG tools


Debug techniques:

Source level debugging: Breakpoints, single step can be done and the content of registers as well as the memory contents can be checked at any given time and instruction

JTAG: Costly debug interface tool, which allows us to do source level debugging

UART: We can send commands from a hyper-terminal, to suspend the current running task and go to the debug sub-routine. In debug sub-routine, we can check/modify the register and memory content at the instance when we sent the suspend command


Task-switching:

Concurrent programming let us execute more than one process (or thread) one at a time. To run multiple threads on a single processor, we need a task scheduler which does the task-switching. Task-switching can be triggered by hardware interrupt or software interrupt. One example of software interrupt is systick timer interrupt which will trigger the task scheduler to switch the task periodically, in round robin fashion. In our project, we are using UART commands as a trigger to task scheduler.


Implementation of a basic task scheduler:

The task scheduler needs to do some ground level stuff before switching the task. Say for example we have two threads (from now on we will say task and thread interchangeably). To run two independent task reliably, we need two register banks and two stack pointers. But, for a light embedded application, we cannot afford multiple hardware for multiple task. So, how we implement the task scheduler is by using multiple stack regions in memory for multiple task.

First, we will have too implement a circular linked list. For this we will define a TCB (global structure) for each task (2 in our case). One TCB would have 2 pointers. next_task points to the next task’s TCB. stack_pointer will point to the stack region corresponding to that task.

There is also a global pointer Run_ptr. It points to the current running task. Hence we can access the current running task’s stack_pointer using the Run_ptr inside our code. NOTE: Run_ptr should be updated to the current running task after every task switching.

Structure for TCB:

struct{

long *stack_pointer;

struct tcb *next_task;

}tcb;

 


Things that happen during task-switching: Suppose we are in task 1 and want to switch to task 2, following things would take place in task-scheduler ISR:

1) Hardware would save R0-R3, LR, PC and PSR automatically

2) interrupts are disabled

3) ISR would save R4-R11

4) Save the stack pointer to the stack_pointer in TCB1

5) Update the Run_ptr to point to the TCB2

6) Update the stack pointer to the stack_pointer of TCB2

7) Pop R4-R11 (This was saved last time to the stack of task 2, when we switched from task 2 to task 1)

8) Enable interrupts

9) BX LR (This will pop R0-R3, LR, PC and PSR. Stack pointer is pointing to the stack of task 2. Hence, PC will get the return address of task 2, which was previously saved when we switched the task from task 2 to task 1)

In the above 9 steps, replace 2 with 1, and we get the steps when task 2 is switched with task 1.

We want to be specific about this process and we don’t want the compiler to add any extra unnecessary code, which can potentially disrupt the pushing or popping sequence. Hence, all the steps are to be implemented in assembly language. Also, we have to give the naked_attribute_ to the task scheduler ISR, because compiler can push or pop after going to the ISR, without our knowledge.

 

Code for task scheduler:

Task scheduler ISR 1) Saves R0-R3,R12,LR,PC,PSR

CPSID I ; 2) Prevent interrupt during switch

PUSH {R4-R11} ; 3) Save remaining regs r4-11

LDR R0, =RunPt ; 4) R0=pointer to RunPt, old thread

LDR R1, [R0] ; R1 = RunPt

STR SP, [R1] ; Save SP into TCB

LDR R1, [R1,#4] ; 5) R1 = RunPt->next

STR R1, [R0] ; RunPt = R1

LDR SP, [R1] ; 6) new thread SP; SP = RunPt->sp;

POP {R4-R11} ; 7) restore regs r4-11

CPSIE I ; 8) tasks run with interrupts enabled

BX LR ; 9) restore R0-R3,R12,LR,PC,PSR

 

 

https://github.com/Vishal1234516/Debug-shell.git