KRNL - Debugging

For breakout functions for intercept taskshift etc see breakout.html

It's possible to assert signals on pins

Krnl has a number of breakout functions you can implement

Here is one version - which is just in the bottom of your sketchfile

Some remarks

Due to pcb layout and internal cpu structure the IO pins on the Arduinos (uneo,mega,..) does not refer to same internal registers aka ports.

See pins and ports here

Below is shown Arduino digital pins which can be used for debugging. But there are ofcourse others available.

The ports below maps ordered IO pins (like 8,9,… on UNO) to one internal register which ease use for debugging.

YOu can find others - its up to you

(click for code)

Krnl breakout function

k_breakout is considered the most important debug facility in krnl.

  • k_breakout is called for every taskshift in krnl.

  • It is called after pRun is set to point to the task to become running

  • You can identify the running by pRun->nr

    • 0: dummy task - cpu time eater when nobody else want to rn

    • 1,2,3 your task numbered in same order as their respective k_crt_task calls

So we can identify the running task nr (pRun->nr)

On an UNO

PORTB bits is connected to digital pins 8,9,10,11,12,13 We will use PORTB in the followin way

  • PORTB bit 0 high when nr 0 (aka dummy is running)

  • PORTB bit 1 high when first created task is running

  • PORTB bit 2 high when second created task is running

  • etc

You can only use PORTB d0..d5, D6b and d6 is used for the 16MHz xtal

You may connect a logic analyser (like analog discovery) to D8-D13

// UNO UNO UNO
// init the digital pins  (place it in setup)

for (int i=0; i < 14 ; i++) {
  pinMode(i,OUTPUT);
  digitalWrite(i,LOW);
}

// and place the following outside any function

extern "C" {
  void k_breakout() // called every task shift from dispatcher
  {
    PORTB = (1 << pRun->nr);
  }
}

On MEGA

Basicly the same just on PORTA

  • PORTA bit 0: 22

  • PORTA bit 2: 23

  • etc

// MEGA MEGA
// init the digital pins  (place it in setup)

for (int i=2; i < 30 ; i++) {
  pinMode(i,OUTPUT);
  digitalWrite(i,LOW);
}

// and place the following outside any function

extern "C" {
  void k_breakout() // called every task shift from dispatcher
  {
    PORTA = (1 << pRun->nr);
  }
}

No analyser - use LED13

If you do not have a analyser or a handfull of LEDs youcan get some info by turning ON led13 when dummy is running.

If running is running from time to time there may be enough cpu time.

But beware we can not say anything about realtime requirements.

// UNO UNO UNO
// init the digital pins  (place it in setup)

  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);


// and place the following outside any function

extern "C" {
  void k_breakout() // called every task shift from dispatcher
  {
  if (pRun->nr == 0)
     PORTB |= 0x20; // ON - LED13 is bit 5 0010000 aka 0x20
  else
  	PORTB &= B11011111;   // OFF 0xcf
  }
}
// MEGA
// init the digital pins  (place it in setup)
// LED is PORTB bit 7
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);


// and place the following outside any function

extern "C" {
  void k_breakout() // called every task shift from dispatcher
  {
  if (pRun->nr == 0)
     PORTB |= 0x80; // ON - LED13 is bit7 10000000  aka 0x20
  else
  	PORTB &= B01111111;   // OFF 0xcf
  }
}

See here for at number of small programs with traces from analog discovery

/* or just LED13 if dummy ...

  YOu can test for board by #ifdef ARDUINO_AVR_UNO  etc
  see list below

  AVR_ADK
  AVR_BT
  AVR_DUEMILANOVE
  AVR_ESPLORA
  AVR_ETHERNET
  AVR_FIO
  AVR_GEMMA
  AVR_LEONARDO
  AVR_LILYPAD
  AVR_LILYPAD_USB
  AVR_MEGA
  AVR_MEGA2560
  AVR_MICRO
  AVR_MINI
  AVR_NANO
  AVR_NG
  AVR_PRO
  AVR_ROBOT_CONTROL
  AVR_ROBOT_MOTOR
  AVR_UNO
  AVR_YUN

    both: pinMode(13,OUTPUT);
    uno mega

    if (pRun->nr == 0)
    PORTB = PORTB | B00100000;  // led on uno
                  | B10000000;  // mega

    else

    PORTB = PORTB & B11011111;  // led off uno
                  & B01111111;   / mega

    mega

*/

/*

   Suggested PORTS TO USE

  UNO
  pin port
  8   PB0
  9   PB1
  10  PB2
  11  PB3
  12  PB4
  13  PB5  LED13
  PB6 and 7  etc not to be used !


  MEGA
  pin port
  22   PA0
  23   PA1
  24   PA2
  25   PA3
  26   PA4
  27   PA5
  38   PA6
  29   PA7

  13  PB7 LED13

  MICRO
  8  PB4
  9  PB5
  10 PB6
  11 PB7
  13 PC7 LED13

  NANO
  D8  PD0
  D9  PD1
  D2  PD2
  D3  PD3
  D4  PD4
  D5  PD5
  D6  PD6
  D7  PD7
  13  PB5  LED13

  PRO MINI
  2  PD2
  3  PD3
  4  PD4
  5  PD5
  6  PD6
  13 PB5 LED13

 * */

Who is running

Idea: We will switch on a LED acc to task number

We know running task number can be found by pRun->nr

  • dummy has number 0

  • There is no other tasks inside krnl

  • Task are numbered in the order they are created eg 1,2,3,…

In the example for the UNO we take pins 8,9,…,13 for identifying tasks, so dmy is pin 8, task 1 is pin 9 etc

(click for code)

LEDs

Forgot to say …

  • Std small LED to the pins and a 500 ohm resistor in series to ground

Logic analyzer

Instead of using LEDs you can attach a logic analyzer to the pins used to identify who is running.

As see below you can get an excellent overview over who is running and when - aka scheduling :-)

LED 13 when dummy is running

The following shows how you can use compiler directive to find out which arduino you have

The example is only coded for mega mega2560 and uno but can easily be extended

(click for code)

A large example

(click for code)

And an analyzer:

  • DIO 0: dummy task .- high when it is running

  • DIO 1: task nr 1 - function task1

  • DIO 1: task nr 2 - function task2

Observe when task1 has highest priority it gets the 5 tick eating time as once, a and therefore task2 might become dalyed

When they are equal they multitask for sharing cpu and they are both delayed a bit

  1. First image equal priority

  2. Second image task1 higher priority than task2.

Equal priority for task1 and task2 (DIO1 and DIO 2)

D0 is dummy task

alt text 

Task1 (DIO 1) higher priority than task2(DIO 2)

D0 is dummy task

alt text 

Suggested pins for LED debug

When using pins for debug by breakout from krnl its wise NOT to use digitalWrite functions because they are so so slow.

Instead direct port access is preferred. For that reason it is wise to use pins for the LEDs on the same port

Example code for an UNO

From the overview we will use PORTB bit 0 to 5 - remember bit 5 is the famous LED 13.


// FOR PORTB

void setup() {
  for (int i = 8; i < 14; i++)
    pinMode(i, OUTPUT);

  // Set 8-13 LOW and preserve the rest
  // 8-13 equals bit 0 to 5 so dont touch bit 6,7
  PORTB = PORTB & B11000000; // = 0XC0 = 128+64
  //   portn bit   76543210
}

void setAllPins0To5(uint8_t bits)
{
  bits = bits | B11000000;  // Set bit 6,7 mandatory high
  PORTB = PORTB & bits;
}

void setSingleBit(uint8_t bitnr, uint8_t highLow)
{
  uint8_t b;
  if (5 < bitnr)
    return; // Error PORTB 6 and 7 is not yours

  b = 0x01 << bitnr;

  if (highLow) {
    PORTB = PORTB | b;
  }
  else {
    b = ! b; // invert
    PORTB = PORTB & b;
  }
}


void loop() {
  // put your main code here, to run repeatedly:

  setAllPins0To5(B00000101); // set PORTB 0 and 2 high and rest low

  setSingleBit(4, 1);
  setSingleBit(3, 0);
  delay(1000);

  setSingleBit(4, 0);
  setSingleBit(3, 1);
  delay(1000);

}