µController vs µProcessor

Let's play a game!

Name your favourite µController

Name your favourite µProcessor

So... this happened..

I see your $20, and raise you $9

NOT! SO! FAST!!

$5

Ermm.....

Arduino

Raspberry Pi

Arduino

Raspberry Pi

Arduino

RaspberryPi

Processes

App

Arduino Library

ATmega328

App1

Library

BCM2837

OS (Linux)

Kernel Driver

App2

Library

MMU

Real Time-ness..

What is real-time?

Real-time applications have operational deadlines between some triggering event and the application's response to that event. To meet these operational deadlines, programmers use real-time operating systems (RTOS) on which the maximum response time can be calculated or measured reliably for the given application and environment.


A typical RTOS uses priorities. The highest priority task wanting the CPU always gets the CPU within a fixed amount of time after the event waking the task has taken place. On such an RTOS the latency of a task only depends on the tasks running at equal or higher priorities, all other tasks can be ignored. On a normal OS (such as normal Linux) the latencies depend on everything running on the system, which of course makes it much harder to be convinced that the deadlines will be met every time on a reasonably complicated system. This is because preemption can be switched off for an unknown amount of time. The high priority task wanting to run can thus be delayed for an unknown amount of time by low priority tasks running with preemption switched off.

 

- https://rt.wiki.kernel.org/index.php/Frequently_Asked_Questions

WS2812 aka NeoPixel

asm volatile(
  "headD:"                   "\n\t" // Clk  Pseudocode
  // Bit 7:
  "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
  "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
  "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
  "rjmp .+0"                "\n\t" // 2    nop nop
  "sbrc %[byte] , 6"        "\n\t" // 1-2  if(b & 0x40)
   "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
  "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
  "rjmp .+0"                "\n\t" // 2    nop nop
  // Bit 6:
  "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
  "mov  %[n1]   , %[lo]"    "\n\t" // 1    n1   = lo
  "out  %[port] , %[n2]"    "\n\t" // 1    PORT = n2
  "rjmp .+0"                "\n\t" // 2    nop nop
  "sbrc %[byte] , 5"        "\n\t" // 1-2  if(b & 0x20)
   "mov %[n1]   , %[hi]"    "\n\t" // 0-1   n1 = hi
  "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
  "rjmp .+0"                "\n\t" // 2    nop nop
  // Bit 5:
  "out  %[port] , %[hi]"    "\n\t" // 1    PORT = hi
  "mov  %[n2]   , %[lo]"    "\n\t" // 1    n2   = lo
  "out  %[port] , %[n1]"    "\n\t" // 1    PORT = n1
  "rjmp .+0"                "\n\t" // 2    nop nop
  "sbrc %[byte] , 4"        "\n\t" // 1-2  if(b & 0x10)
   "mov %[n2]   , %[hi]"    "\n\t" // 0-1   n2 = hi
  "out  %[port] , %[lo]"    "\n\t" // 1    PORT = lo
  "rjmp .+0"                "\n\t" // 2    nop nop
  // ...
// Dirty trick: RJMPs proceeding to the next 
// instruction are used to delay two clock 
// cycles in one instruction word (rather than
// using two NOPs).  This was necessary in 
// order to squeeze the loop down to exactly 
// 64 words -- the maximum possible for a
// relative branch.
// Hand-tuned assembly code issues data 
// to the LED drivers at a specific rate.  
// There's separate code for different CPU 
// speeds (8, 12, 16 MHz) for both the WS2811
// (400 KHz) and WS2812 (800 KHz) drivers.

On Arduino..

Let's talk about Linux

App1

Library

BCM2837

OS (Linux)

Kernel Driver

App2

Library

// Use /proc/self/pagemap to figure out the mapping between virtual and physical addresses
pid = getpid();
sprintf(pagemap_fn, "/proc/%d/pagemap", pid);
fd = open(pagemap_fn, O_RDONLY);

if (fd < 0) {
  fatal("Failed to open %s: %m\n", pagemap_fn);
}

if (lseek(fd, (unsigned long)virtbase >> 9, SEEK_SET) != (unsigned long)virtbase >> 9) {
  fatal("Failed to seek on %s: %m\n", pagemap_fn);
}
// Map a peripheral's IO memory into our virtual memory, so we can read/write it directly
static void * map_peripheral(uint32_t base, uint32_t len) {
  int fd = open("/dev/mem", O_RDWR);
  void * vaddr;
  if (fd < 0)
    fatal("Failed to open /dev/mem: %m\n");
  vaddr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, base);
  if (vaddr == MAP_FAILED)
    fatal("Failed to map peripheral at 0x%08x: %m\n", base);
  close(fd);

  return vaddr;
}

Hacks all the way down..

Where do you need realtime processing?

  • Feedback Control (Motors)

  • Digital Signal Processing

  • Interactive Interfaces

You don't have to run Linux!

FreeRTOS

µCLinux

Baremetal!

Power Consumption

Arduino

Raspberry Pi

Price Per IC

Arduino (ATmega328)

iMX6 (MCIMX6X4AVM08AB)

Power Domains

Arduino (ATmega328)

iMX6 (i.MX6QP)

Pins

Arduino (ATmega328) - TQFP

iMX6 (i.MX6QP) - BGA

Routing and Layers

Arduino (ATmega328)

iMX6 (i.MX6QP)

Manufacturing Cost

  • Number of Layers (Fabrication)

  • Number of Pins (Assembly)

But ..

.. the lines are blurring

Heterogeneous Devices

i.MX 6SoloX

Heterogeneous Devices

AM335x (Beaglebone)

Beefy µC

STM32F756NG

Choose your poison!

µController vs µProcessor

By Chinmay Pendharkar

µController vs µProcessor

  • 1,369