923 lines
42 KiB
HTML
923 lines
42 KiB
HTML
<!doctype html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
|
|
<title>Renode: Easy CI for your Weird Hardware</title>
|
|
|
|
<link rel="stylesheet" href="dist/reset.css">
|
|
<link rel="stylesheet" href="dist/reveal.css">
|
|
<link rel="stylesheet" href="dist/theme/black.css">
|
|
|
|
<!-- Theme used for syntax highlighted code -->
|
|
<link rel="stylesheet" href="plugin/highlight/monokai.css">
|
|
</head>
|
|
|
|
<!--
|
|
* Emulators are useful tools
|
|
- PC emulator (e.g. Docker on Mac, WSL on Linux)
|
|
- NES emulator -- fun and games, realtime output
|
|
- Also have debugging emulators
|
|
- Renode
|
|
|
|
* Renode Stack
|
|
- CPU cores written in C
|
|
- arm, i386, ppc, riscv, sparc, xtensa
|
|
- Windows, Mac, Linux
|
|
- Peripherals and UI written in C#
|
|
- Extensible via Python and C#
|
|
- Write once. Run anywhere. Using C# to define new peripherals
|
|
|
|
* Three major users
|
|
- Designers of new boards
|
|
- Reverse engineering exsisting hardware
|
|
- Silicon designers
|
|
|
|
* Designers of new boards
|
|
- One or more chips
|
|
- How are they connected?
|
|
- What weird hardware exists?
|
|
|
|
* Concurrent emulation of multiple devices
|
|
- Can connect multiple devices, e.g. via UART, GPIO, SPI, Ethernet, CAN...
|
|
- All devices are emulated using the same time source
|
|
- Helps to debug timing differences with different processors on a board
|
|
|
|
* Board definition format
|
|
- Easily define memory layout
|
|
- Easily move blocks around
|
|
- Only define what's necessary
|
|
- You don't need to be perfect, just good enough!
|
|
|
|
* Can read SVD files
|
|
|
|
* Hardware has Similarities
|
|
- Picture of existing register sets
|
|
- There are only so many combinations
|
|
- Rip. Mix. Burn. Many chips are just copies of one another.
|
|
|
|
* Tests in CI
|
|
|
|
* Reverse engineering existing hardware
|
|
|
|
* If it's a supported architecture, it's easy to run code
|
|
* LoadBinary and set PC
|
|
* Can skip much of the boot ROM
|
|
* Attach GDB
|
|
* Reproducible makes it easy to test theories
|
|
|
|
* Developing new Silicon blocks
|
|
|
|
* Betrusted hardware
|
|
- Create a new design in LiteX / Verilog
|
|
- Document the design
|
|
- Create a model
|
|
- Timing isn't as critical
|
|
|
|
-->
|
|
|
|
<body>
|
|
<div class="reveal">
|
|
<div class="slides">
|
|
<section>
|
|
<section>
|
|
<h2>Renode</h2>
|
|
<p>I find it a useful tool. Maybe you will, too!
|
|
</section>
|
|
<section>
|
|
<h2>About Me: I Do Weird Hardware</h2>
|
|
<ul>
|
|
<li>Simmel: Contact Tracing with Audio</li>
|
|
<li>Chibitronics: Programming Stickers with Audio</li>
|
|
<li>Novena: Open Source Laptop</li>
|
|
<li>Senoko: Open Source Power Board for Novena</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Hardware with Embedded Software</h2>
|
|
<ul>
|
|
<li>Software needs to be written</li>
|
|
<li class="fragment">Software needs to be <strong>tested</strong></li>
|
|
<li class="fragment">Software needs to be <i>debugged</i></li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>About Renode</h2>
|
|
<ul>
|
|
<li>Whole-System Emulator</li>
|
|
<li>Supports concurrent emulation</li>
|
|
<li>Extensible with C# and Python</li>
|
|
<li>Windows, Mac, Linux</li>
|
|
<li>MIT Licensed</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>About This Talk</h2>
|
|
<ul>
|
|
<li>Overview of Emulators</li>
|
|
<li>Oevrview of Weird Hardware</li>
|
|
<li>Cool things you can do</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Who will find this interesting?</h2>
|
|
<ul>
|
|
<li>Creators: Those making new boards or hardware</li>
|
|
<li>Integrators: Running CI on firmware files</li>
|
|
<li>Reverse Engineers: Understanding new hardware and firmware</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Creators: Making New Things!</h2>
|
|
<ul>
|
|
<li>Reusing an existing platform</li>
|
|
<li>Reusing an existing microcontroller</li>
|
|
<li>New microcontroller fron existing family</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Integrators: Making Sure Nothing Broke!</h2>
|
|
<ul>
|
|
<li>Hardware testing incompatible with cloud</li>
|
|
<ul>
|
|
<li>...it sure is effective, though</li>
|
|
</ul>
|
|
<li>Hardware crunch makes it difficult to get hardware</li>
|
|
<li>Downloading software is much cheaper than shipping</li>
|
|
<li>Can run tests on every code push</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Reverse Engineers: What Is This Blob Doing?</h2>
|
|
<ul>
|
|
<li>Staring at code flow is enlightening, but time-consuming</li>
|
|
<li>What is it doing and how does it get there?</li>
|
|
<li>How can we make it do $x?</li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<section data-transition="fade-out">
|
|
<h2>What is an Emulator?</h2>
|
|
<img class="fragment" src="media/bbs-example.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is an Emulator?</h2>
|
|
<img src="media/DEC_VT100_terminal_cropped.jpg">
|
|
</section>
|
|
<section data-transition="fade-in slide-out">
|
|
<h2>What is an Emulator?</h2>
|
|
<img src="media/bbs-example.png">
|
|
</section>
|
|
<section data-transition="slide-in fade-out">
|
|
<h2>Whole-System Emulator</h2>
|
|
<img src="media/fceux-smb.png">
|
|
<!--
|
|
<ul>
|
|
<li>Wii Virtual Console</li>
|
|
<li>VirtualBox</li>
|
|
<li>Parallels</li>
|
|
</ul>
|
|
-->
|
|
</section>
|
|
<section data-transition="fade-in">
|
|
<h2>Whole-System Emulator</h2>
|
|
<img src="media/fceux-smb-debug.png">
|
|
<!--
|
|
<ul>
|
|
<li>Wii Virtual Console</li>
|
|
<li>VirtualBox</li>
|
|
<li>Parallels</li>
|
|
</ul>
|
|
-->
|
|
</section>
|
|
<section>
|
|
<h2>Transparent Emulator</h2>
|
|
<ul>
|
|
<li>WSL2/Docker</li>
|
|
<li>qemu on Linux</li>
|
|
<li>Rosetta on Mac</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Renode Is Many of These</h2>
|
|
<ul>
|
|
<li>Console: Able to present an interactive environment</li>
|
|
<li>Transparent: Can run in CI via Robot commands</li>
|
|
<li>Debugger: Has a GDB server built in</li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<section data-transition="fade-out">
|
|
<h2>What is a Computer?</h2>
|
|
<img class="fragment" src="media/bluenrg-block-diagram.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is a Computer?</h2>
|
|
<ul>
|
|
<li>A system of devices</li>
|
|
<li>One or more CPU</li>
|
|
<li>One or more buses</li>
|
|
<li>One or more blocks of memory</li>
|
|
<li>Some I/O</li>
|
|
</ul>
|
|
</section>
|
|
<section data-transition="fade-out">
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-block-diagram.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-block-diagram-no-extra-bits.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-block-diagram-cpu.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-block-diagram-memories.png">
|
|
</section>
|
|
<section data-transition="fade-in">
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-block-diagram-peripherals.png">
|
|
</section>
|
|
<section>
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-peripherals.png">
|
|
</section>
|
|
<section>
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/bluenrg-memory-map.png">
|
|
</section>
|
|
<section>
|
|
<h2>What is a Computer?</h2>
|
|
<img src="media/conceptual-diagram.png">
|
|
</section>
|
|
<section>
|
|
<h2>Defining a Computer in Renode</h2>
|
|
<pre><code data-trim>
|
|
flash: Memory.MappedMemory @ sysbus 0x00000000
|
|
size: 0x00008000
|
|
|
|
sram: Memory.MappedMemory @ sysbus 0x20000000
|
|
size: 0x00001000
|
|
|
|
nvic: IRQControllers.NVIC @ sysbus 0xE000E000
|
|
IRQ -> cpu@0
|
|
|
|
cpu: CPU.CortexM @ sysbus
|
|
nvic: nvic
|
|
cpuType: "cortex-m0+"
|
|
PerformanceInMips: 24
|
|
</code></pre>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<h2>That's Nice, but What About...</h2>
|
|
<ol>
|
|
<li>Loading firmware?</li>
|
|
<li>Adding peripherals?</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<section>
|
|
<section>
|
|
<h2>What is "Firmware"?</h2>
|
|
<blockquote class="fragment strike">Firmware is a series of instructions executed by the CPU in
|
|
order to accomplish a task</blockquote>
|
|
<blockquote class="fragment">Firmware is Memory</blockquote>
|
|
</section>
|
|
<section>
|
|
<h2>Loading Firmware in Renode</h2>
|
|
<pre><code data-trim>
|
|
sysbus LoadELF @firmware.elf
|
|
</code></pre>
|
|
<pre class="fragment"><code data-trim>
|
|
sysbus LoadBinary @rom.bin 0x20000000
|
|
</code></pre>
|
|
<pre class="fragment"><code data-trim>
|
|
sysbus LoadSymbolsFrom @rom.elf
|
|
</code></pre>
|
|
</section>
|
|
<section>
|
|
<h2>How does Renode Interact With $VENDOR_TOOL?</h2>
|
|
<ul>
|
|
<li>Hopefully your vendor tool produces ELF files</li>
|
|
<li class="fragment">At the end of the day, it's all bytes. Just use <code>LoadBinary</code>!
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>What About Boot ROMs?</h2>
|
|
<ol>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Initialize peripherals</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Check for boot override</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Check for low-power state</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Load firmware into RAM</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Validate firmware</li>
|
|
<li>Jump to loaded program</li>
|
|
</ol>
|
|
<pre class="fragment"><code data-trim>
|
|
sysbus.cpu VectorTableOffset 0x20000000
|
|
sysbus.cpu PC 0x20000c00
|
|
</code></pre>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<section>
|
|
<h2>What about New Peripherals?</h2>
|
|
</section>
|
|
<section>
|
|
<h2>It's All About Small Victories</h2>
|
|
<ul>
|
|
<li>Serial ports are super rewarding</li>
|
|
<li>They're also usually simple!</li>
|
|
<li>They are easy to script</li>
|
|
</ul>
|
|
</section>
|
|
<section data-transition="fade-out">
|
|
<h2>What is a Register?</h2>
|
|
<img src="media/pl011-bluenrg.png">
|
|
<img class="fragment" src="media/pl011-cc2538-cropped.png">
|
|
</section>
|
|
<section data-transition="fade">
|
|
<h2>What is a Register?</h2>
|
|
<img src="media/pl011-bcm2835-cropped.png">
|
|
</section>
|
|
<section data-transition="fade-in">
|
|
<h2>What is a Register?</h2>
|
|
<img src="media/pl011-arm.png">
|
|
</section>
|
|
<section>
|
|
<h2>Reuse an Existing Block!</h2>
|
|
<pre data-id="code-animation"><code data-trim data-line-numbers="|10-12">
|
|
flash: Memory.MappedMemory @ sysbus 0x00000000
|
|
size: 0x00008000
|
|
|
|
sram: Memory.MappedMemory @ sysbus 0x20000000
|
|
size: 0x00001000
|
|
|
|
nvic: IRQControllers.NVIC @ sysbus 0xE000E000
|
|
IRQ -> cpu@0
|
|
|
|
// 👇 Add a UART with IRQ #10 at address 0x40300000
|
|
uart: UART.PL011 @ sysbus 0x40300000
|
|
-> nvic@10
|
|
|
|
cpu: CPU.CortexM @ sysbus
|
|
nvic: nvic
|
|
cpuType: "cortex-m0+"
|
|
PerformanceInMips: 24
|
|
</code></pre>
|
|
</section>
|
|
<section>
|
|
<h2>Output Success!</h2>
|
|
<img src="media/bluenrg-renode-uart.png">
|
|
</section>
|
|
<section>
|
|
<h2>Always Check for Block Reuse</h2>
|
|
Blocks are frequently reused across designs, and can save you from having to reimplement
|
|
everything from scratch!
|
|
</section>
|
|
<section>
|
|
<h2>Steps to Set Up a Serial Port</h2>
|
|
<ol>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Enable peripheral</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Set up clock</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Mux GPIOs</li>
|
|
<li class="fragment strike semi-fade-out" data-fragment-index="1">Calculate baud rate</li>
|
|
<li>Write to UART TX register</li>
|
|
</ol>
|
|
</section>
|
|
<section>
|
|
<h2>Steps to Set Up a Serial Port</h2>
|
|
<ul>
|
|
<li>Interrupt Support</li>
|
|
<ul>
|
|
<li>Handled as a GPIO within the peripheral</li>
|
|
</ul>
|
|
<li>DMA</li>
|
|
<ul>
|
|
<li>Handled as a different peripheral</li>
|
|
</ul>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Example Serial Port</h2>
|
|
<pre class="code-animation"><code class="cs" data-trim data-line-numbers="|22-33|132-140">
|
|
//
|
|
// Copyright (c) 2010-2018 Antmicro
|
|
//
|
|
// This file is licensed under the MIT License.
|
|
// Full license text is available in 'licenses/MIT.txt'.
|
|
//
|
|
using System.Collections.Generic;
|
|
using Antmicro.Renode.Peripherals.Bus;
|
|
using Antmicro.Renode.Core.Structure.Registers;
|
|
using Antmicro.Renode.Core;
|
|
using Antmicro.Renode.Logging;
|
|
|
|
namespace Antmicro.Renode.Peripherals.UART
|
|
{
|
|
public class LiteX_UART : UARTBase, IDoubleWordPeripheral, IBytePeripheral, IKnownSize
|
|
{
|
|
public LiteX_UART(Machine machine) : base(machine)
|
|
{
|
|
IRQ = new GPIO();
|
|
var registersMap = new Dictionary<long, DoubleWordRegister>
|
|
{
|
|
{(long)Registers.RxTx, new DoubleWordRegister(this)
|
|
.WithValueField(0, 8,
|
|
writeCallback: (_, value) =>
|
|
this.TransmitCharacter((byte)value),
|
|
valueProviderCallback: _ => {
|
|
if(!TryGetCharacter(out var character))
|
|
{
|
|
this.Log(LogLevel.Warning, "Empty Rx FIFO.");
|
|
}
|
|
return character;
|
|
})
|
|
},
|
|
{(long)Registers.TxFull, new DoubleWordRegister(this)
|
|
.WithFlag(0, FieldMode.Read) //tx is never full
|
|
},
|
|
{(long)Registers.RxEmpty, new DoubleWordRegister(this)
|
|
.WithFlag(0, FieldMode.Read, valueProviderCallback: _ => Count == 0)
|
|
},
|
|
{(long)Registers.EventPending, new DoubleWordRegister(this)
|
|
// `txEventPending` implements `WriteOneToClear` semantics to avoid fake warnings
|
|
// `txEventPending` is generated on the falling edge of TxFull; in our case it means never
|
|
.WithFlag(0, FieldMode.Read | FieldMode.WriteOneToClear, valueProviderCallback: _ => false, name: "txEventPending")
|
|
.WithFlag(1, out rxEventPending, FieldMode.Read | FieldMode.WriteOneToClear, name: "rxEventPending")
|
|
.WithWriteCallback((_, __) => UpdateInterrupts())
|
|
},
|
|
{(long)Registers.EventEnable, new DoubleWordRegister(this)
|
|
.WithFlag(0, name: "txEventEnabled")
|
|
.WithFlag(1, out rxEventEnabled)
|
|
.WithWriteCallback((_, __) => UpdateInterrupts())
|
|
},
|
|
};
|
|
|
|
registers = new DoubleWordRegisterCollection(this, registersMap);
|
|
}
|
|
|
|
public uint ReadDoubleWord(long offset)
|
|
{
|
|
return registers.Read(offset);
|
|
}
|
|
|
|
public byte ReadByte(long offset)
|
|
{
|
|
if(offset % 4 != 0)
|
|
{
|
|
// in the current configuration, only the lowest byte
|
|
// contains a meaningful data
|
|
return 0;
|
|
}
|
|
return (byte)ReadDoubleWord(offset);
|
|
}
|
|
|
|
public override void Reset()
|
|
{
|
|
base.Reset();
|
|
registers.Reset();
|
|
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
public void WriteDoubleWord(long offset, uint value)
|
|
{
|
|
registers.Write(offset, value);
|
|
}
|
|
|
|
public void WriteByte(long offset, byte value)
|
|
{
|
|
if(offset % 4 != 0)
|
|
{
|
|
// in the current configuration, only the lowest byte
|
|
// contains a meaningful data
|
|
return;
|
|
}
|
|
|
|
WriteDoubleWord(offset, value);
|
|
}
|
|
|
|
public long Size => 0x100;
|
|
|
|
public GPIO IRQ { get; private set; }
|
|
|
|
public override Bits StopBits => Bits.One;
|
|
|
|
public override Parity ParityBit => Parity.None;
|
|
|
|
public override uint BaudRate => 115200;
|
|
|
|
protected override void CharWritten()
|
|
{
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
protected override void QueueEmptied()
|
|
{
|
|
UpdateInterrupts();
|
|
}
|
|
|
|
private void UpdateInterrupts()
|
|
{
|
|
// rxEventPending is latched
|
|
rxEventPending.Value = (Count != 0);
|
|
|
|
// tx fifo is never full, so `txEventPending` is always false
|
|
var eventPending = (rxEventEnabled.Value && rxEventPending.Value);
|
|
IRQ.Set(eventPending);
|
|
}
|
|
|
|
private IFlagRegisterField rxEventEnabled;
|
|
private IFlagRegisterField rxEventPending;
|
|
private readonly DoubleWordRegisterCollection registers;
|
|
|
|
private enum Registers : long
|
|
{
|
|
RxTx = 0x0,
|
|
TxFull = 0x04,
|
|
RxEmpty = 0x08,
|
|
EventStatus = 0x0c,
|
|
EventPending = 0x10,
|
|
EventEnable = 0x14,
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
</section>
|
|
<section>
|
|
<h2>Steps to Set Up a Serial Port</h2>
|
|
<img src="media/renode-xous-kernel-uart.png">
|
|
</section>
|
|
<section>
|
|
<h2>What about Missing Definitions?</h2>
|
|
<ul>
|
|
<li>Most registers are unused</li>
|
|
<ul>
|
|
<li>Start/Stop bits</li>
|
|
<li>One-wire mode</li>
|
|
<li>Infrared mode</li>
|
|
</ul>
|
|
<li class="fragment">Most writes can be ignored</li>
|
|
</ul>
|
|
</section>
|
|
<section data-transition="fade-out">
|
|
<h2>Advantages of Emulation</h2>
|
|
<img src="media/betrusted-soc-uart-mux.png">
|
|
</section>
|
|
<section data-transition="fade-in">
|
|
<h2>Advantages of Emulation</h2>
|
|
<img src="media/renode-xous-double-uart-tiled.png">
|
|
</section>
|
|
</section>
|
|
<!--
|
|
<section>
|
|
<section>
|
|
<h2>Example of Weird Hardware</h2>
|
|
<ul>
|
|
<li>NRF52840</li>
|
|
<li>LM74 Temperature Sensor</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Example of Weird Hardware</h2>
|
|
<ul>
|
|
<li>NRF52833</li>
|
|
<li>LM74 Temperature Sensor</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Example of Weird Hardware</h2>
|
|
<ul>
|
|
<li>BlueNRG1</li>
|
|
<li>LM74 Temperature Sensor</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Example of Weird Hardware</h2>
|
|
<ul>
|
|
<li>RISC-V</li>
|
|
<li>FPGA-based framebuffer</li>
|
|
<li>Initial graphical demo in 1 hour</li>
|
|
</ul>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<section>
|
|
<h2>What makes hardware "Weird"?</h2>
|
|
<ul>
|
|
<li>Unusual CPU architecture</li>
|
|
<li>Different model of chip than commonly found</li>
|
|
<li>Additional hardware</li>
|
|
<li>More CPUs per board</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Unusual CPU architecture</h2>
|
|
Sorry, can't help
|
|
</section>
|
|
<section>
|
|
<h2>Different model CPU</h2>
|
|
<ul>
|
|
<li>Maybe it's just a variant</li>
|
|
<li>Perhaps memory regions were shuffled</li>
|
|
<li>Does it use the same hardware block as someone else?</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>New hardware version</h2>
|
|
<ul>
|
|
<li>Do you use the new, specialized features?</li>
|
|
<li>Lots of UARTs support Infrared. Do you need that?</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h2>Completely new hardware</h2>
|
|
<ul>
|
|
<li>Time to break out C#</li>
|
|
</ul>
|
|
</section>
|
|
</section> -->
|
|
<section>
|
|
<section>
|
|
<h2>Robot Framework: Running Tests in CI</h2>
|
|
<pre class="code-animation"><code class="robot" data-trim data-line-numbers="|1-6|8-18|20-26|28-40">
|
|
*** Settings ***
|
|
Suite Setup Setup
|
|
Suite Teardown Teardown
|
|
Test Setup Reset Emulation
|
|
Test Teardown Test Teardown
|
|
Resource ${RENODEKEYWORDS}
|
|
|
|
*** Variables ***
|
|
${UART} sysbus.uart0
|
|
${URI} @https://dl.antmicro.com/projects/renode
|
|
|
|
${LIS2DS12}= SEPARATOR=
|
|
... """ ${\n}
|
|
... using "platforms/cpus/nrf52840.repl" ${\n}
|
|
... ${\n}
|
|
... lis2ds12: Sensors.LIS2DS12 @ twi1 0x1c ${\n}
|
|
... ${SPACE*4}IRQ -> gpio0@28 ${\n}
|
|
... """
|
|
|
|
*** Keywords ***
|
|
Create Machine
|
|
Execute Command mach create
|
|
Execute Command machine
|
|
... LoadPlatformDescriptionFromString ${LIS2DS12}
|
|
Execute Command sysbus LoadELF
|
|
... ${URI}/nrf52840--zephyr_lis2dh.elf-s_747800-163b7e7cc986d4b1115f06b5f3df44ed0defc1fa
|
|
|
|
*** Test Cases ***
|
|
Should Read Acceleration
|
|
Create Machine
|
|
Create Terminal Tester ${UART}
|
|
|
|
Execute Command sysbus.twi1.lis2ds12 AccelerationX 10
|
|
Execute Command sysbus.twi1.lis2ds12 AccelerationY 5
|
|
Execute Command sysbus.twi1.lis2ds12 AccelerationZ -5
|
|
|
|
Start Emulation
|
|
|
|
Wait For Line On Uart
|
|
... x 9.997213 , y 4.997410 , z -4.999803
|
|
</code></pre>
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<section>
|
|
<h2>Renode for Reverse Engineering</h2>
|
|
</section>
|
|
<section>
|
|
<h2>SVD: Standard Chip Documentation</h2>
|
|
<pre class="code-animation"><code class="xml" data-trim data-line-numbers="|3-9|25-87|27-31|39-57|46-47|48-56">
|
|
<?xml version='1.0' encoding='utf-8'?>
|
|
<device xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" schemaVersion="1.1" xsi:noNamespaceSchemaLocation="CMSIS-SVD_Schema_1_1_draft.xsd">
|
|
<vendor>STMicroelectronics</vendor>
|
|
<vendorID>ST</vendorID>
|
|
<name>BlueNRG2</name>
|
|
<series>BlueNRG1</series>
|
|
<version>1.0.0</version>
|
|
<description>ARM 32-bit Cortex-M0 Microcontroller based device, CPU clock up to 32MHz</description>
|
|
<licenseText>License</licenseText>
|
|
<cpu>
|
|
<name>CM0</name>
|
|
<revision>r0p0</revision>
|
|
<endian>little</endian>
|
|
<mpuPresent>false</mpuPresent>
|
|
<fpuPresent>false</fpuPresent>
|
|
<nvicPrioBits>2</nvicPrioBits>
|
|
<vendorSystickConfig>false</vendorSystickConfig>
|
|
</cpu>
|
|
<addressUnitBits>8</addressUnitBits>
|
|
<width>32</width>
|
|
<size>32</size>
|
|
<access>read-write</access>
|
|
<resetValue>0x00000000</resetValue>
|
|
<resetMask>0xFFFFFFFF</resetMask>
|
|
<peripherals>
|
|
<peripheral>
|
|
<name>RNG</name>
|
|
<version>1.0</version>
|
|
<description>RNG</description>
|
|
<groupName>RNG</groupName>
|
|
<baseAddress>0xB0000000</baseAddress>
|
|
<size>32</size>
|
|
<access>read-write</access>
|
|
<addressBlock>
|
|
<offset>0</offset>
|
|
<size>0x1000</size>
|
|
<usage>registers</usage>
|
|
</addressBlock>
|
|
<registers>
|
|
<register>
|
|
<name>CR</name>
|
|
<description>RNG configuration register</description>
|
|
<addressOffset>0x00</addressOffset>
|
|
<size>32</size>
|
|
<access>read-write</access>
|
|
<resetValue>0x00000000</resetValue>
|
|
<resetMask>0x0000FFFF</resetMask>
|
|
<fields>
|
|
<field>
|
|
<name>DIS</name>
|
|
<description>Set the state of the random number generator.<ul><li>0: RNG is enable.</li><li>1: RNG is disabled. The internal free-running oscillators are put in power-down mode and the RNG clock is stopped at the input of the block.</li></ul></description>
|
|
<bitOffset>2</bitOffset>
|
|
<bitWidth>1</bitWidth>
|
|
<access>read-write</access>
|
|
</field>
|
|
</fields>
|
|
</register>
|
|
<register>
|
|
<name>SR</name>
|
|
<description>RNG status register</description>
|
|
<addressOffset>0x04</addressOffset>
|
|
<size>32</size>
|
|
<access>read-only</access>
|
|
<resetValue>0x00000000</resetValue>
|
|
<resetMask>0x0000FFFF</resetMask>
|
|
<fields>
|
|
<field>
|
|
<name>RDY</name>
|
|
<description>New random value ready.<ul><li>0: The RNG_VAL register value is not yet valid. If performing a read access to VAL, the host will be put on hold (by wait-states insertion on the AHB bus) until a random value is available.</li><li>1: The VAL register contains a valid random number.</li></ul>This bit remains at 0 when the RNG is disabled (RNGDIS bit = 1b in CR)</description>
|
|
<bitOffset>0</bitOffset>
|
|
<bitWidth>1</bitWidth>
|
|
<access>read-only</access>
|
|
</field>
|
|
</fields>
|
|
</register>
|
|
<register>
|
|
<name>VAL</name>
|
|
<description>RNG 16 bit random value</description>
|
|
<addressOffset>0x08</addressOffset>
|
|
<size>32</size>
|
|
<access>read-only</access>
|
|
<resetValue>0x00000000</resetValue>
|
|
<resetMask>0x0000FFFF</resetMask>
|
|
</register>
|
|
</registers>
|
|
</peripheral>
|
|
</peripherals>
|
|
</device>
|
|
</code></pre>
|
|
</section>
|
|
<section>
|
|
<h2>SVD: Using with Renode</h2>
|
|
<pre class="code-animation"><code data-trim data-line-numbers="|1-6|8-18|20-26|28-40">
|
|
sysbus ApplySVD @BlueNRG2.svd
|
|
</code></pre>
|
|
<img class="fragment" src="media/bluenrg-renode-svd.png">
|
|
</section>
|
|
<section>
|
|
<h2>Logging Memory Accesses</h2>
|
|
<img src="media/renode-betrusted-log.png">
|
|
</section>
|
|
<section>
|
|
<h2>Debugging with GDB</h2>
|
|
<img src="media/renode-start-gdb.png">
|
|
<img class="fragment" src="media/renode-connect-gdb.png">
|
|
</section>
|
|
<section>
|
|
<h2>Creating ELF Files</h2>
|
|
<img src="media/ghidra-decompile.png">
|
|
</section>
|
|
</section>
|
|
<section>
|
|
<h2>Multi-System Emulation</h2>
|
|
<img src="media/renode-multi-system.png">
|
|
</section>
|
|
<section>
|
|
<h2>Multi-System Emulation</h2>
|
|
<img src="media/betrusted-ec-com-1.png">
|
|
</section>
|
|
<section>
|
|
|
|
</section>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="dist/reveal.js"></script>
|
|
<script src="plugin/notes/notes.js"></script>
|
|
<script src="plugin/zoom/zoom.js"></script>
|
|
<script src="plugin/markdown/markdown.js"></script>
|
|
<script src="plugin/highlight/highlight.js"></script>
|
|
<script type="text/javascript" src="js/robot.js"></script>
|
|
<script>
|
|
/** This used to be a part of Reveal.js, but was removed at some point */
|
|
function getQueryHash() {
|
|
function deserialize(value) {
|
|
if (typeof value === 'string') {
|
|
if (value === 'null') return null;
|
|
else if (value === 'true') return true;
|
|
else if (value === 'false') return false;
|
|
else if (value.match(/^-?[\d\.]+$/)) return parseFloat(value);
|
|
}
|
|
return value;
|
|
}
|
|
|
|
let query = {};
|
|
location.search.replace(/[A-Z0-9]+?=([\w\.%-]*)/gi, a => {
|
|
query[a.split('=').shift()] = a.split('=').pop();
|
|
});
|
|
// Basic deserialization
|
|
for (let i in query) {
|
|
let value = query[i];
|
|
|
|
query[i] = deserialize(unescape(value));
|
|
}
|
|
|
|
// Do not accept new dependencies via query config to avoid
|
|
// the potential of malicious script injection
|
|
if (typeof query['dependencies'] !== 'undefined') delete query['dependencies'];
|
|
|
|
return query;
|
|
|
|
}
|
|
var presenter = !!getQueryHash().s;
|
|
// More info about initialization & config:
|
|
// - https://revealjs.com/initialization/
|
|
// - https://revealjs.com/config/
|
|
Reveal.initialize({
|
|
hash: true,
|
|
|
|
controls: presenter ? false : true,
|
|
progress: true,
|
|
history: true,
|
|
center: true,
|
|
controlsTutorial: presenter ? false : true,
|
|
|
|
slideNumber: presenter ? null : 'c/t',
|
|
|
|
// The "normal" size of the presentation, aspect ratio will be preserved
|
|
// when the presentation is scaled to fit different resolutions. Can be
|
|
// specified using percentage units.
|
|
width: 960,
|
|
height: 700,
|
|
|
|
// Factor of the display size that should remain empty around the content
|
|
margin: 0.1,
|
|
|
|
multiplex: {
|
|
// Example values. To generate your own, see the socket.io server instructions.
|
|
secret: getQueryHash().s || null,
|
|
id: 'ef4a6dfa448e19c1',
|
|
url: 'https://p.xobs.io/'
|
|
},
|
|
|
|
|
|
// Bounds for smallest/largest possible scale to apply to content
|
|
minScale: 0.02,
|
|
maxScale: 5.5,
|
|
|
|
transition: 'slide', // none/fade/slide/convex/concave/zoom
|
|
|
|
highlight: {
|
|
beforeHighlight: hljs => hljs.registerLanguage('robot', window.hljsDefineRobot)
|
|
},
|
|
|
|
// Don't forget to add the dependencies
|
|
dependencies: [
|
|
{ src: 'https://reveal-multiplex.glitch.me/socket.io/socket.io.js', async: true },
|
|
{ src: 'https://reveal-multiplex.glitch.me/client.js', async: true }
|
|
],
|
|
|
|
// Learn about plugins: https://revealjs.com/plugins/
|
|
plugins: [RevealMarkdown, RevealHighlight, RevealZoom]
|
|
});
|
|
|
|
|
|
</script>
|
|
</body>
|
|
|
|
</html> |