From 9d41fccc8612a36e6693cff03d72a890c31367e2 Mon Sep 17 00:00:00 2001 From: Tido Klaassen Date: Mon, 13 Jul 2015 18:33:11 +0200 Subject: [PATCH] Added rudimentary QEMU board for running the test suite binaries --- ports/cortex-m/Makefile | 6 + ports/cortex-m/boards/qemu/Makefile.include | 14 +++ ports/cortex-m/boards/qemu/README.md | 21 ++++ ports/cortex-m/boards/qemu/board_setup.c | 119 ++++++++++++++++++++ 4 files changed, 160 insertions(+) create mode 100644 ports/cortex-m/boards/qemu/Makefile.include create mode 100644 ports/cortex-m/boards/qemu/README.md create mode 100644 ports/cortex-m/boards/qemu/board_setup.c diff --git a/ports/cortex-m/Makefile b/ports/cortex-m/Makefile index f778222..d2666ba 100644 --- a/ports/cortex-m/Makefile +++ b/ports/cortex-m/Makefile @@ -134,6 +134,7 @@ endif # Target specific version libopencm3 LDLIBS += -l$(LIBNAME) +ifneq ($(BOARD),qemu) ## Flags for newlibc. # This uses the version of newlib optimised for size and without libnosys. # This usually is the version of newlib you want to use, although it has some @@ -150,6 +151,11 @@ LDLIBS += -Wl,--start-group -lc_nano -lgcc -Wl,--end-group # the top end of memory while the threads' stacks are positioned inside # the BSS. #LDLIBS += -Wl,--start-group -lc_nano -lgcc -lnosys -Wl,--end-group +else +# Special LDLIBS for qemu target to enable semi-hosting. +# TODO: Check if this is also useful for real hardware +LDLIBS += -Wl,--start-group --specs=rdimon.specs -lc -lrdimon -lgcc -Wl,--end-group +endif # All .PHONY: all diff --git a/ports/cortex-m/boards/qemu/Makefile.include b/ports/cortex-m/boards/qemu/Makefile.include new file mode 100644 index 0000000..4ccb960 --- /dev/null +++ b/ports/cortex-m/boards/qemu/Makefile.include @@ -0,0 +1,14 @@ +TARGET ?= stm32f103rb +LIBNAME ?= opencm3_stm32f1 +DEFS ?= -DSTM32F1 +DEFS += -DSTD_CON=USART2 +DEFS += -DMST_SIZE=0x400 + +FP_FLAGS ?= -msoft-float +ARCH_FLAGS ?= -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd + +OOCD ?= openocd +OOCD_INTERFACE ?= stlink-v2-1 +OOCD_BOARD ?= st_nucleo_f103rb + +objs += board_setup.o diff --git a/ports/cortex-m/boards/qemu/README.md b/ports/cortex-m/boards/qemu/README.md new file mode 100644 index 0000000..a7b3aee --- /dev/null +++ b/ports/cortex-m/boards/qemu/README.md @@ -0,0 +1,21 @@ +This board is a quick n' dirty copy of nucleo-f103rb, stripped down to run +atomthread's test suite on qemu. Since it must be linked against newlib's +librdimon to enable semi-hosting, the stubs provided in the common directory +can not be used. Do not be surprised if malloc etc. do not work as expected. + +The [GNU ARM Eclipse](http://gnuarmeclipse.livius.net/blog/) project maintains +a fork of qemu that is able to emulate a Nucleo-F103RB board. Check out their +gnuarmeclipse-dev branch from [here] +(http://sourceforge.net/p/gnuarmeclipse/qemu/ci/gnuarmeclipse-dev/tree/). + +At time of writing (2015-07-13), I had to run configure with +`--disable-werror --target-list="gnuarmeclipse-softmmu"` to build +a usable target. + +After installing you can use it to run the test binaries like this: + +``` +qemu-system-gnuarmeclipse -nographic -monitor null -serial stdio \ + -semihosting --semihosting-config target=native \ + --machine NUCLEO-F103RB --kernel build/kern1.elf --verbose +``` diff --git a/ports/cortex-m/boards/qemu/board_setup.c b/ports/cortex-m/boards/qemu/board_setup.c new file mode 100644 index 0000000..ef4d008 --- /dev/null +++ b/ports/cortex-m/boards/qemu/board_setup.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, Tido Klaassen. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. No personal names or organizations' names associated with the + * Atomthreads project may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "atomport.h" + +/** + * initialise and start SysTick counter. This will trigger the + * sys_tick_handler() periodically once interrupts have been enabled + * by archFirstThreadRestore(). Since we did not change the clock source, + * the MCU is still running from 16MHz PIOSC + */ +static void systick_setup(void) +{ + systick_set_frequency(SYSTEM_TICKS_PER_SEC, 16000000); + + systick_interrupt_enable(); + + systick_counter_enable(); +} + +/** + * Set up the core clock to something other than the internal 16MHz PIOSC. + * Make sure that you use the same clock frequency in systick_setup(). + */ +/** + * Set up user LED and provide function for toggling it. This is for + * use by the test suite programs + */ +static void test_led_setup(void) +{ + /* LED is connected to GPIO5 on port A */ + rcc_periph_clock_enable(RCC_GPIOA); + + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); + + gpio_set(GPIOA, GPIO5); +} + +void test_led_toggle(void) +{ + static bool on = true; + + /* qemu does not seem to know how to handle gpio_toggle() */ + if(on){ + gpio_clear(GPIOA, GPIO5); + } else { + gpio_set(GPIOA, GPIO5); + } + + on = !on; +} + +/** + * Callback from your main program to set up the board's hardware before + * the kernel is started. + */ +extern void initialise_monitor_handles(void); +int board_setup(void) +{ + /* initialise semi-hosting */ + initialise_monitor_handles(); + + /* Disable interrupts. This makes sure that the sys_tick_handler will + * not be called before the first thread has been started. + * Interrupts will be enabled by archFirstThreadRestore(). + */ + cm_mask_interrupts(true); + + /* configure user LED*/ + test_led_setup(); + + /* initialise SysTick counter */ + systick_setup(); + + /* Set exception priority levels. Make PendSv the lowest priority and + * SysTick the second to lowest + */ + nvic_set_priority(NVIC_PENDSV_IRQ, 0xFF); + nvic_set_priority(NVIC_SYSTICK_IRQ, 0xFE); + + return 0; +} +