Loadmeter

During embedded development, an accurate idea of the MCU load is important, and it’s nice to have it confirmed by a second source ... enter the “Loadmeter”.

A 53 year old Sangamo Weston uA meter

_images/loadmeter-load-small.jpg

Cooperative Multitasking

A cooperatively multitasked system relies on each process regularly giving up time to other processes on the system. One poorly designed task or process can consume all of the CPU time for itself, either by performing extensive calculations or by busy waiting; both would cause the whole system to hang.

Whilst a cooperative scheduler starts each task, they must voluntarily give back control when they are finished or even during stages of their operation by using the pause Word.

Note

busy-waiting, busy-looping or spinning is a technique in which a process repeatedly checks to see if a condition is true

How Does It Work ?

A loadmeter-task sends a short pulse to a Microamp Meter. Any other tasks delay the rate at which loadmeter-task can send pulses, therby reducing the duty cycle of the square wave pulse train to the meter, giving a lower reading and indicating more load.

A moving coil meter is ideal because the mechanical inertia will average the duty cycle of the pulse train.

Calibration

The Loadmeter is calibrated with a trimpot for a point near the high reading of the meter, (in this case the “0” on the DB meter scale) to indicate the minimum load of the default system. This is done while only the loadmeter-task is running.

Usage

Once the loadmeter-task is running, subsequent tasks will cause the Loadmeter pointer to move to the left, indicating they are using MCU time, which is a increase in load.

While indicating MCU load, a steady pointer shows ideal rapid cycling between tasks, but a pulsing Loadmeter pointer indicates a task may be hogging the MCU or perhaps the “pause” Word is in the wrong place, such as at the end of a 1 second delay, when it should be in the loop counter instead ?

The Loadmeter also indicates:
  1. How additional “pause” Words can have zero effect
  2. Whether a task can be made more efficient with better code or perhaps by using a timer for a delay instead of spinning ?

Schematic Diagram

A STM32F0 Discovery board was used.

Loadmeter Schematic Diagram

_images/ms-loadmeter-schematic.jpg

Source Code and Notes

Notes:

  • The F0 Discovery board lacks RAM for more tasks, having only 8KB of RAM. Mecrisp-Stellaris will raise a ‘Not Enough Ram’ error if one more task is added.
  • This is all running from Flash so I can fit in the 5 tasks, if ms-loadmeter.fs is run from ram, then a task must be removed.
  • The USER push button lights the GREEN LED when depressed.
  • The Blinky flashes the BLUE LED on and off about once a second
  • Delays 1 and 2 just delay for a second each, they are there to waste time.
  • All ancillary files are available from the library
  • ms-loadmeter.fs and ms-loadmeter.memmap.fs are available here.
\ Program Name: ms-loadmeter.fs
\ Edit template.xml, commenting out unwanted register lines ( <!- commented out -> F9 ), then run 'make' 
\ Date: Tue  9 May 2017 05:29:17 AEST
\ Copyright 2017  t.porter <terry@tjporter.com.au> Released under the GPL
\ For Mecrisp-Stellaris by Matthias Koch
\ Chip: STM32F051
\ Board: STM32F0 Discovery Board
\ Terminal: e4thcom Copyright (C) 2013-2017 Manfred Mahlow;   https://wiki.forth-ev.de/doku.php/en:projects:e4thcom
\ Clock: 8 Mhz using the internal STM32F051 RC clock, unless otherwise stated
\ All register names must be CMSIS-SVD compliant
\
\ This Program Does: Indicates MCU load using a external uA moving coil meter.
\
\ Inputs: none
\ Outputs: PF-1
\
\ ------------------ USER CODE HERE ------------------ \

compiletoflash			    \ seems that compiletoflash is reset to compiletoram after each upload ?
#require f0-id.fs		    \ Optional development word

compiletoflash
#require memstat.fs		    \ Optional development word

compiletoflash
#require dict.fs		    \ Optional development word

compiletoflash
#require f0-legends.fs

compiletoflash
#require ms-loadmeter.memmap.fs

compiletoflash
#require multitask.fs

compiletoflash

\ Initialisations
%01  2 lshift GPIOF_MODER bis!	    \ use PF-1 as meter driver o/p
%01  18 lshift GPIOC_MODER bis!	    \ PC-9 as output
%01  16 lshift GPIOC_MODER bis!	    \ PC-8 as outpu


: .5s-delay 25000 0 do pause loop ;		    \ Used by Blinky
: delay-1 50000 0 do pause loop ;		    \ 1 second delay
: delay-2 50000 0 do pause loop ;		    

: green-on   %1 9 lshift GPIOC_BSRR bis!  ;	    \ Activated by User pushbutton	
: green-off  %1 9 lshift GPIOC_BRR bis!  ; 

: blue-on   %1 8 lshift GPIOC_BSRR bis!  ;	    \ Activated by Blinky    	
: blue-off  %1 8 lshift GPIOC_BRR bis!  ;

: meter-high	%1  1 lshift GPIOF_BSRR bis! ;	    \ PF-1 high
: meter-low	%1  17 lshift GPIOF_BSRR bis! ;	    \ PF-1 low

: blink	blue-on .5s-delay blue-off .5s-delay ;

: pb? ( -- ? ) 1 0 lshift GPIOA_IDR bit@	    \  test User pushbutton, lights green led if pressed
if green-on else green-off then pause
;


: loadmeter
    meter-high
    nop
    nop						    \ some small delays to extend the meter pulse as this mcu is so fast
    meter-low
    pause
;

task: loadmeter-task
:   load& ( -- )
    loadmeter-task activate
    begin loadmeter again
;

task: blinktask
:   blinky& ( -- )
    blinktask activate
    begin blink again
;

task: delay1
: delay1& ( -- )
    delay1  activate
    begin delay-1  again
;

task: delay2
: delay2& ( -- )
    delay2  activate
    begin delay-2  again
;

task: user-pb-task
:   user-pb& ( -- )
    user-pb-task activate
    begin  pb? again
;


\ multitask
 
    load&
    blinky&
    delay1&
    delay2&
    user-pb&
    id				    \ Optional development word
    mem				    \ Optional development word
    multitask
      



Loadmeter Pics

Load task running

_images/loadmeter-load.jpg

Load and blinky tasks running

_images/loadmeter-load-blinky.jpg

Load, blinky and delay1 tasks running

_images/loadmeter-load-blinky-delay1.jpg

Load, blinky, delay1, and delay2 tasks running

_images/loadmeter-load-blinky-delay1-delay2.jpg

Load, blinky, delay1, delay2 and user-pb tasks running

_images/loadmeter-all-tasks-running.jpg