barectf-tracepoint: add QEMU ARM target example
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Wed, 13 Apr 2016 19:52:48 +0000 (15:52 -0400)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Wed, 13 Apr 2016 20:37:04 +0000 (16:37 -0400)
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
doc/examples/barectf-tracepoint/.gitignore [new file with mode: 0644]
doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart [new file with mode: 0644]
doc/examples/barectf-tracepoint/README.md
doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c [new file with mode: 0644]
doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h [new file with mode: 0644]
doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld [new file with mode: 0644]
doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh [new file with mode: 0755]
doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h [new file with mode: 0644]
doc/examples/barectf-tracepoint/barectf-tracepoint.c

diff --git a/doc/examples/barectf-tracepoint/.gitignore b/doc/examples/barectf-tracepoint/.gitignore
new file mode 100644 (file)
index 0000000..b288a24
--- /dev/null
@@ -0,0 +1,5 @@
+barectf-tracepoint-barectf-linux-fs
+barectf-tracepoint-barectf-qemu-arm-uart
+barectf-tracepoint-lttng-ust
+ctf-linux-fs
+ctf-qemu-arm-uart
diff --git a/doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart b/doc/examples/barectf-tracepoint/Makefile.barectf-qemu-arm-uart
new file mode 100644 (file)
index 0000000..073bc2b
--- /dev/null
@@ -0,0 +1,45 @@
+BARECTF ?= barectf
+ARCH = arm-none-eabi
+
+RM = rm -rf
+MKDIR = mkdir -p
+CC = $(ARCH)-gcc
+
+VERSION = qemu-arm-uart
+CPU=arm926ej-s
+EXTRA_DIR = ../../../extra
+CFLAGS = -DWITH_QEMU_ARM_UART=1 -ffunction-sections -mcpu=$(CPU) -O2 -Wall -pedantic -std=gnu99 -I$(EXTRA_DIR) -I.
+LDFLAGS= -T barectf-platform-$(VERSION).ld -lc -lnosys
+
+TARGET = barectf-tracepoint-barectf-$(VERSION)
+OBJS = $(TARGET).o barectf-$(VERSION).o barectf-platform-$(VERSION).o
+TRACEDIR = ctf-$(VERSION)
+
+.PHONY: all clean sim
+
+all: $(TARGET)
+
+$(TRACEDIR):
+       $(MKDIR) $@
+
+$(TARGET): $(OBJS)
+       $(CC) -o $@ $^ $(LDFLAGS)
+
+$(TRACEDIR)/metadata barectf-bitfield.h barectf.h barectf.c: config.yaml $(TRACEDIR)
+       $(BARECTF) $< -m $(TRACEDIR)
+
+barectf-$(VERSION).o: barectf.c
+       $(CC) -o $@ $(CFLAGS) -c $<
+
+barectf-platform-$(VERSION).o: barectf-platform-$(VERSION).c
+       $(CC) $(CFLAGS) -c $<
+
+$(TARGET).o: barectf-tracepoint.c barectf-tracepoint-$(VERSION).h barectf.h barectf-bitfield.h
+       $(CC) -o $@ $(CFLAGS) -c $<
+
+clean:
+       $(RM) $(TARGET) $(OBJS) $(TRACEDIR)
+       $(RM) barectf.h barectf-bitfield.h barectf.c
+
+sim: $(TARGET)
+       ./barectf-tracepoint-barectf-qemu-arm-uart.sh
index ba5a9a9c74ec6aca9f416c56b66bb9d69c1c5cad..5093d5094047107fff31fcc39333bb47053f56a0 100644 (file)
@@ -1,31 +1,32 @@
 # Example using `barectf-tracepoint.h`
 
-This example is based on the [linux-fs-simple example](../linux-fs-simple),
-but it uses the `tracepoint()` macro defined in
+This example is based on the [linux-fs-simple example](../linux-fs-simple)
+example, but it uses the `tracepoint()` macro defined in
 [`barectf-tracepoint.h`](../../../extra/barectf-tracepoint.h) instead of
 calling the generated tracing functions directly.
 
 This example also shows the compatibility with
 [LTTng-UST](http://lttng.org/) that this `barectf-tracepoint.h` allows.
 
+This example also includes a QEMU ARM target to simulate barectf used by
+a true bare-metal application.
 
-## Building
+All the targets of this example use the same application source:
+[`barectf-tracepoint.c`](barectf-tracepoint.c).
 
-To build both barectf and LTTng-UST targets, make sure both tools are
-installed, and do:
 
-    make
+## barectf tracing
 
-To build only the example using barectf:
+### linux-fs platform
 
-    make -f Makefile.barectf-linux-fs
+#### Building
 
-To build only the example using LTTng-UST:
+Do:
 
-    make -f Makefile.lttng-ust
+    make -f Makefile.barectf-linux-fs
 
 
-## barectf tracing
+#### Running
 
 Run this example:
 
@@ -39,8 +40,79 @@ as string fields in the events of the binary stream, e.g.:
     ./barectf-tracepoint-barectf-linux-fs this argument and this one will be recorded
 
 
+### QEMU ARM platform
+
+#### Building
+
+To build this example, you need an ARM cross-compiler toolchain
+(`gcc-arm-none-eabi`, `binutils-arm-none-eabi`, and
+`libnewlib-arm-none-eabi` Ubuntu packages), then do:
+
+    make -f Makefile.barectf-qemu-arm-uart
+
+
+#### Running
+
+To run this example, you need `qemu-system-arm` (`qemu-system-arm`
+Ubuntu package).
+
+Run this example:
+
+    make -f Makefile.barectf-qemu-arm-uart sim
+
+The complete CTF trace is written to the `ctf-qemu-arm-uart` directory.
+
+
+#### What happens when running?
+
+When you run this example, here's what happens:
+
+  1. The `barectf-tracepoint-barectf-qemu-arm-uart.sh` Bash script
+     is executed.
+  2. This Bash script executes `qemu-system-arm` with the appropriate
+     options to simulate the bare-metal application on an ARM system.
+     The simulated board is a Versatile platform baseboard from ARM. The
+     simulated CPU is an ARM926EJ-S. This is a 2001 ARM9 core
+     implementing the ARMv5TE architecture. QEMU is set to execute the
+     `barectf-tracepoint-barectf-qemu-arm-uart` ELF file (previously
+     built), and to connect the board's first UART with QEMU's standard
+     input/output streams, and the board's second UART to the
+     `ctf-qemu-arm-uart/stream` file (output only). The Bash script
+     reads each line printed by QEMU, and kills the QEMU process when
+     it reads the ending line written by the bare-metal application.
+  3. QEMU starts. Eventually, the bare-metal application's
+     `main()` function is called.
+  4. `main()` calls `init_tracing()`, which for this example, calls
+     `barectf_platform_qemu_arm_uart_init()`. This is a custom barectf
+     platform created specifically for this example. The platform
+     initializes a barectf context to get its clock source from a timer
+     on the simulated board, and to flush its packets by writing the
+     bytes to the second UART (which is connected to the
+     `ctf-qemu-arm-uart/stream` file by QEMU). The platform uses a
+     global buffer of 4 kiB to hold the current packet.
+  5. `main()` calls `trace_stuff()` which contains the `tracepoint()`
+     macro invocations. Events are recorded to the current packet by
+     the barectf machinery. When this packet is full, it is flushed
+     by the platform to the second UART.
+  6. `main()` calls `fini_tracing()`, which calls
+     `barectf_platform_qemu_arm_uart_fini()`, which prints the
+     ending line that `barectf-tracepoint-barectf-qemu-arm-uart.sh`
+     is waiting for to kill QEMU.
+
+
 ## LTTng-UST tracing
 
+### Building
+
+Make sure [LTTng-UST](http://lttng.org/) is installed.
+
+Do:
+
+    make -f Makefile.lttng-ust
+
+
+### Running
+
 Create an LTTng tracing session:
 
     lttng create my-session
diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.c
new file mode 100644 (file)
index 0000000..352d0aa
--- /dev/null
@@ -0,0 +1,107 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <barectf.h>
+
+#include "barectf-platform-qemu-arm-uart.h"
+
+#define BUF_SIZE               4096
+#define TIMER_CTRL_32BIT       (1 << 1)
+#define TIMER_CTRL_ENABLE      (1 << 7)
+
+volatile uint32_t * const uart0 = (uint32_t *) 0x101f1000;
+volatile uint32_t * const uart1 = (uint32_t *) 0x101f2000;
+volatile uint32_t * const timer0_ctrl = (uint32_t *) 0x101e2008;
+volatile uint32_t * const timer0_value = (uint32_t *) 0x101e2004;
+
+static struct barectf_default_ctx barectf_ctx;
+
+static uint8_t buf[BUF_SIZE];
+
+static uint64_t get_clock(void* data)
+{
+       return (uint64_t) -*timer0_value;
+}
+
+static void flush_packet(void)
+{
+       size_t i;
+
+       /* flush packet to UART 1 */
+       for (i = 0; i < BUF_SIZE; ++i) {
+               *uart1 = (uint32_t) buf[i];
+       }
+}
+
+static int is_backend_full(void *data)
+{
+       return 0;
+}
+
+static void open_packet(void *data)
+{
+       barectf_default_open_packet(&barectf_ctx);
+}
+
+static void close_packet(void *data)
+{
+       /* close packet now */
+       barectf_default_close_packet(&barectf_ctx);
+
+       /* flush current packet */
+       flush_packet();
+}
+
+void barectf_platform_qemu_arm_uart_init(void)
+{
+       struct barectf_platform_callbacks cbs = {
+               .default_clock_get_value = get_clock,
+               .is_backend_full = is_backend_full,
+               .open_packet = open_packet,
+               .close_packet = close_packet,
+       };
+
+       /* enable/start timer (clock source) */
+       *timer0_ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE;
+
+       /* initialize barectf context */
+       barectf_init(&barectf_ctx, buf, BUF_SIZE, cbs, NULL);
+
+       /* open first packet */
+       open_packet(NULL);
+
+       /* indicate that tracing is starting */
+       puts("tracing: starting");
+}
+
+void barectf_platform_qemu_arm_uart_fini(void)
+{
+       /* close last packet if it contains at least one event */
+       if (barectf_packet_is_open(&barectf_ctx) &&
+                       !barectf_packet_is_empty(&barectf_ctx)) {
+               close_packet(NULL);
+       }
+
+       /* indicate that tracing is done */
+       puts("tracing: done");
+}
+
+struct barectf_default_ctx *barectf_platform_qemu_arm_uart_get_barectf_ctx()
+{
+       return &barectf_ctx;
+}
+
+#define STDOUT 1
+#define STDERR 2
+
+/* custom write "syscall" for newlib's stdio: write to UART 0 */
+int _write(int file, char *ptr, int len) {
+       if (file == STDOUT || file == STDERR) {
+               int i;
+
+               for (i = 0; i < len; i++) {
+                       *uart0 = (uint32_t) ptr[i];
+               }
+       }
+
+       return 0;
+}
diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.h
new file mode 100644 (file)
index 0000000..5bf31c0
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _BARECTF_PLATFORM_QEMU_ARM_UART
+#define _BARECTF_PLATFORM_QEMU_ARM_UART
+
+#include <barectf.h>
+
+void barectf_platform_qemu_arm_uart_init(void);
+void barectf_platform_qemu_arm_uart_fini(void);
+struct barectf_default_ctx *barectf_platform_qemu_arm_uart_get_barectf_ctx(void);
+
+#endif /* _BARECTF_PLATFORM_QEMU_ARM_UART */
diff --git a/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld b/doc/examples/barectf-tracepoint/barectf-platform-qemu-arm-uart.ld
new file mode 100644 (file)
index 0000000..5e80b8e
--- /dev/null
@@ -0,0 +1,38 @@
+MEMORY {
+  SDRAM (XRW) : ORIGIN = 0x00000000, LENGTH = 0x08000000
+}
+
+/* heap size */
+heap_size = 0x10000;
+
+/* define stack base (grows downwards), used in newlib's crt0.S */
+__stack = ORIGIN(SDRAM) + LENGTH(SDRAM);
+
+/* libc's entry point */
+ENTRY(_mainCRTStartup);
+
+SECTIONS {
+  /* QEMU starts executing at 0x10000 */
+  . = 0x10000;
+
+  .text : {
+    *(.text)
+    *(.text.*)
+  } > SDRAM
+
+  .data : {
+    *(.data)
+    *(.data.*)
+  } > SDRAM
+
+  .bss : {
+    __bss_start__ = .;
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+    __bss_end__ = .;
+  } > SDRAM
+
+  /* "end" symbol needed by newlib's _sbrk */
+  end = .;
+}
diff --git a/doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh b/doc/examples/barectf-tracepoint/barectf-tracepoint-barectf-qemu-arm-uart.sh
new file mode 100755 (executable)
index 0000000..f70eb79
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+qemu-system-arm -M versatilepb -m 128M -nographic -monitor none \
+       -kernel barectf-tracepoint-barectf-qemu-arm-uart \
+       -serial stdio -serial file:ctf-qemu-arm-uart/stream |
+{
+       while read line; do
+               echo "$line"
+
+               if [ x"$line" = x"tracing: done" ]; then
+                       pkill -nf file:ctf-qemu-arm-uart
+               fi
+       done
+}
diff --git a/doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h b/doc/examples/barectf-tracepoint/barectf-tracepoint-qemu-arm-uart.h
new file mode 100644 (file)
index 0000000..aeae485
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _BARECTF_TRACEPOINT_QEMU_ARM_UART
+#define _BARECTF_TRACEPOINT_QEMU_ARM_UART
+
+#include <barectf-platform-qemu-arm-uart.h>
+
+/*
+ * Include generated barectf header file: this contains the prefix and
+ * default stream name to be used by the tracepoint() macro.
+ */
+#include "barectf.h"
+
+/* define how the context is to be found by tracepoint() calls */
+#define BARECTF_TRACEPOINT_CTX (global_barectf_ctx)
+
+/* then include this: */
+#include <barectf-tracepoint.h>
+
+/* global barectf context (default stream) */
+static struct barectf_default_ctx *global_barectf_ctx;
+
+/* init function for this version */
+static void init_tracing(void)
+{
+       /* initialize platform */
+       barectf_platform_qemu_arm_uart_init();
+       global_barectf_ctx = barectf_platform_qemu_arm_uart_get_barectf_ctx();
+}
+
+/* finalization function for this version */
+static void fini_tracing(void)
+{
+       /* finalize platform */
+       barectf_platform_qemu_arm_uart_fini();
+}
+
+#endif /* _BARECTF_TRACEPOINT_QEMU_ARM_UART */
index 41708d2aaf1bd6325a1a7fa9849ae9e5503361c1..ca0f7943e0135e7dee64c0e04e4ba0607b006466 100644 (file)
@@ -5,6 +5,8 @@
 
 #if defined(WITH_LTTNG_UST)
 #include "barectf-tracepoint-lttng-ust.h"
+#elif defined(WITH_QEMU_ARM_UART)
+#include "barectf-tracepoint-qemu-arm-uart.h"
 #else
 #include "barectf-tracepoint-linux-fs.h"
 #endif
@@ -24,16 +26,10 @@ static void trace_stuff(int argc, char *argv[])
 
        /* record 40000 events */
        for (i = 0; i < 5000; ++i) {
+               str = argv[i % argc];
                tracepoint(barectf_tp, simple_uint32, i * 1500);
                tracepoint(barectf_tp, simple_int16, -i * 2);
                tracepoint(barectf_tp, simple_float, (float) i / 1.23);
-
-               if (argc > 0) {
-                       str = argv[i % argc];
-               } else {
-                       str = "hello there!";
-               }
-
                tracepoint(barectf_tp, simple_string, str);
                tracepoint(barectf_tp, simple_enum, RUNNING);
                tracepoint(barectf_tp, a_few_fields, -1, 301, -3.14159,
@@ -44,9 +40,26 @@ static void trace_stuff(int argc, char *argv[])
        }
 }
 
+#define NUM_STRINGS    5
+
+static char *strings[] = {
+       "orange",
+       "mandarine",
+       "lemon",
+       "lime",
+       "grapefruit",
+};
+
 int main(int argc, char *argv[])
 {
        init_tracing();
+
+       if (argc <= 1) {
+               /* use static strings if there's nothing interesting in argv */
+               argc = NUM_STRINGS;
+               argv = strings;
+       }
+
        trace_stuff(argc, argv);
        fini_tracing();
 
This page took 0.030137 seconds and 4 git commands to generate.