Skip to content

Commit

Permalink
bricks/ev3: Add hooks for a clock.
Browse files Browse the repository at this point in the history
This may be a useful starting point for contributors who are familiar with cpus like TI AM1808 even if they are not familiar with the Pybricks codebase.

The initial goal is to fill in the gaps designated by // TODO: TIAM1808. This implements the clock driver.

When this is done, the baked-in MicroPython code would print something like:

Hello, world at time (ms): 0
Hello, world at time (ms): 1000
Hello, world at time (ms): 2000

instead of

Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
  • Loading branch information
laurensvalk committed Jun 10, 2024
1 parent bc843db commit baf7047
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 72 deletions.
28 changes: 28 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,34 @@
"cStandard": "c11",
"intelliSenseMode": "gcc-arm"
},
{
"name": "ev3",
"includePath": [
"${workspaceFolder}/lib/contiki-core",
"${workspaceFolder}/lib/lego",
"${workspaceFolder}/lib/lwrb/src/include",
"${workspaceFolder}/lib/pbio/include",
"${workspaceFolder}/lib/pbio/platform/ev3",
"${workspaceFolder}",
"${workspaceFolder}/bricks/ev3",
"${workspaceFolder}/bricks/ev3/build",
"${workspaceFolder}/micropython",
],
"defines": [
"MICROPY_MODULE_FROZEN_MPY",
"MICROPY_ROM_TEXT_COMPRESSION",
],
"compilerArgs": [
"-Wall",
"-Werror",
"-Wextra",
"-Wno-unused-parameter",
"-Wdouble-promotion",
"-nostdlib"
],
"cStandard": "c11",
"intelliSenseMode": "gcc-arm"
},
{
"name": "ev3rt",
"includePath": [
Expand Down
1 change: 1 addition & 0 deletions bricks/_common/sources.mk
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ PBIO_SRC_C = $(addprefix lib/pbio/,\
drv/clock/clock_nxt.c \
drv/clock/clock_stm32.c \
drv/clock/clock_test.c \
drv/clock/clock_tiam1808.c \
drv/clock/clock_virtual.c \
drv/core.c \
drv/counter/counter_ev3dev_stretch_iio.c \
Expand Down
18 changes: 14 additions & 4 deletions bricks/ev3/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,23 @@ OK
Starting kernel ...
Hello!
World!
System init in platform.c called from startup.s
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Hello, world at time (ms): 0
Traceback (most recent call last):
File "%q", line %dhello.py", line %d8D��D�, in %q
File "%q", line %dhello.py", line %d9���D�, in %q
<module>
KeyboardInterrupt:
KeyboardInterrupt:
Pybricks MicroPython v1.20.0-23-g6c633a8dd on 2024-06-08; MINDSTORMS EV3 Brick with TI Sitara AM1808
Type "help()" for more information.
>>>
Expand Down
40 changes: 36 additions & 4 deletions bricks/ev3/mphalport.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <contiki.h>

#include <pbdrv/config.h>
#include <pbdrv/clock.h>
#include <pbio/main.h>
#include <pbsys/bluetooth.h>

Expand All @@ -25,11 +26,43 @@ void pb_stack_get_info(char **sstack, char **estack) {
}

void pb_event_poll_hook_leave(void) {
// There is a possible race condition where an interrupt occurs and sets the
// Contiki poll_requested flag after all events have been processed. So we
// have a critical section where we disable interrupts and check see if there
// are any last second events. If not, we can call __WFI(), which still wakes
// up the CPU on interrupt even though interrupts are otherwise disabled.


// TODO: TIAM1808 Implement commented out parts

// mp_uint_t state = disable_irq();
if (!process_nevents()) {
// __WFI();
}
// enable_irq(state);
}

// Core delay function that does an efficient sleep and may switch thread context.
// If IRQs are enabled then we must have the GIL.
void mp_hal_delay_ms(mp_uint_t Delay) {
}

// TODO: TIAM1808 implement IRQ enabled check

if (/*__get_PRIMASK() == 0*/ 0) {
// IRQs enabled, so can use systick counter to do the delay
uint32_t start = pbdrv_clock_get_ms();
// Wraparound of tick is taken care of by 2's complement arithmetic.
do {
// This macro will execute the necessary idle behaviour. It may
// raise an exception, switch threads or enter sleep mode (waiting
// for (at least) the SysTick interrupt).
MICROPY_EVENT_POLL_HOOK
} while (pbdrv_clock_get_ms() - start < Delay);
} else {
// IRQs disabled, so need to use a busy loop for the delay.
// TODO: TIAM1808
}
}

uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0;
Expand All @@ -49,8 +82,7 @@ typedef struct {
// Sensor port 1
static pb_hal_uart_t UART0 = { .thr = (volatile uint8_t *)0x01D0C000, .lsr = (volatile uint8_t *)0x01D0C014 };

// Define the write_str function
static void write_str(pb_hal_uart_t *uart, const char *s) {
static void debug(pb_hal_uart_t *uart, const char *s) {
while (*s) {
while ((*uart->lsr & (1 << 5)) == 0) {
}
Expand All @@ -59,7 +91,7 @@ static void write_str(pb_hal_uart_t *uart, const char *s) {
}

void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
write_str(&UART0, str);
debug(&UART0, str);
MICROPY_EVENT_POLL_HOOK
}

Expand Down
60 changes: 34 additions & 26 deletions lib/pbio/drv/block_device/block_device_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,43 @@
#include <pbsys/storage.h>

/**
* The following script is compiled using pybricksdev compile hello.py
* in MULTI_MPY_V6.
*
* from pybricks.tools import wait
*
* print("Hello!")
* wait(1000)
* print("World!")
* wait(1000)
*
* raise KeyboardInterrupt
The following script is compiled using pybricksdev compile hello.py in MULTI_MPY_V6.
from pybricks.tools import StopWatch, wait
timer = StopWatch()
for i in range(10):
print("Hello, world at time (ms):", timer.time())
wait(1000)
raise KeyboardInterrupt
*/
const uint8_t script[] = {
0x73, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x6D, 0x61,
0xAC, 0x00, 0x00, 0x00, 0x5F, 0x5F, 0x6D, 0x61,
0x69, 0x6E, 0x5F, 0x5F, 0x00, 0x4D, 0x06, 0x00,
0x1F, 0x08, 0x00, 0x10, 0x68, 0x65, 0x6C, 0x6C,
0x6F, 0x2E, 0x70, 0x79, 0x00, 0x0F, 0x08, 0x77,
0x61, 0x69, 0x74, 0x00, 0x1C, 0x70, 0x79, 0x62,
0x72, 0x69, 0x63, 0x6B, 0x73, 0x2E, 0x74, 0x6F,
0x6F, 0x6C, 0x73, 0x00, 0x0C, 0x48, 0x65, 0x6C,
0x6C, 0x6F, 0x21, 0x00, 0x0C, 0x57, 0x6F, 0x72,
0x6C, 0x64, 0x21, 0x00, 0x81, 0x77, 0x55, 0x83,
0x38, 0x08, 0x0C, 0x01, 0x4C, 0x27, 0x28, 0x27,
0x48, 0x80, 0x10, 0x02, 0x2A, 0x01, 0x1B, 0x03,
0x1C, 0x02, 0x16, 0x02, 0x59, 0x11, 0x06, 0x10,
0x04, 0x34, 0x01, 0x59, 0x11, 0x02, 0x22, 0x87,
0x68, 0x34, 0x01, 0x59, 0x11, 0x06, 0x10, 0x05,
0x34, 0x01, 0x59, 0x11, 0x02, 0x22, 0x87, 0x68,
0x34, 0x01, 0x59, 0x11, 0x07, 0x65, 0x51, 0x63,
0x1F, 0x0A, 0x01, 0x10, 0x68, 0x65, 0x6C, 0x6C,
0x6F, 0x2E, 0x70, 0x79, 0x00, 0x0F, 0x12, 0x53,
0x74, 0x6F, 0x70, 0x57, 0x61, 0x74, 0x63, 0x68,
0x00, 0x08, 0x77, 0x61, 0x69, 0x74, 0x00, 0x1C,
0x70, 0x79, 0x62, 0x72, 0x69, 0x63, 0x6B, 0x73,
0x2E, 0x74, 0x6F, 0x6F, 0x6C, 0x73, 0x00, 0x08,
0x74, 0x69, 0x6D, 0x65, 0x00, 0x0A, 0x74, 0x69,
0x6D, 0x65, 0x72, 0x00, 0x02, 0x69, 0x00, 0x81,
0x77, 0x55, 0x05, 0x1A, 0x48, 0x65, 0x6C, 0x6C,
0x6F, 0x2C, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64,
0x20, 0x61, 0x74, 0x20, 0x74, 0x69, 0x6D, 0x65,
0x20, 0x28, 0x6D, 0x73, 0x29, 0x3A, 0x00, 0x84,
0x40, 0x20, 0x0C, 0x01, 0x52, 0x46, 0x26, 0x2D,
0x50, 0x80, 0x10, 0x02, 0x10, 0x03, 0x2A, 0x02,
0x1B, 0x04, 0x1C, 0x02, 0x16, 0x02, 0x1C, 0x03,
0x16, 0x03, 0x59, 0x11, 0x02, 0x34, 0x00, 0x16,
0x06, 0x80, 0x42, 0x5A, 0x57, 0x16, 0x07, 0x11,
0x08, 0x23, 0x00, 0x11, 0x06, 0x14, 0x05, 0x36,
0x00, 0x34, 0x02, 0x59, 0x11, 0x03, 0x22, 0x87,
0x68, 0x34, 0x01, 0x59, 0x81, 0xE5, 0x57, 0x8A,
0xD7, 0x43, 0x21, 0x59, 0x11, 0x09, 0x65, 0x51,
0x63,
};

static union {
Expand Down
31 changes: 31 additions & 0 deletions lib/pbio/drv/clock/clock_tiam1808.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2024 The Pybricks Authors

#include <pbdrv/config.h>

#if PBDRV_CONFIG_CLOCK_TIAM1808

#include <stdint.h>

void pbdrv_clock_init(void) {
// Actual low level clocks should probably be configured at the very
// start of in SystemInit in platform.c instead.
// But optionally, additional things can be initialized here.
}

uint32_t pbdrv_clock_get_us(void) {
// TODO: TIAM1808 implementation.
return 0;
}

uint32_t pbdrv_clock_get_ms(void) {
// TODO: TIAM1808 implementation.
return 0;
}

uint32_t pbdrv_clock_get_100us(void) {
// TODO: TIAM1808 implementation (1 count = 100us, so 10 counts per millisecond.)
return 0;
}

#endif // PBDRV_CONFIG_CLOCK_TIAM1808
3 changes: 1 addition & 2 deletions lib/pbio/platform/ev3/pbdrvconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
// platform-specific configuration for LEGO MINDSTORMS EV3

#define PBDRV_CONFIG_CLOCK (1)
#define PBDRV_CONFIG_CLOCK_NONE (1)
#define PBDRV_CONFIG_CLOCK_TIAM1808 (1)

#define PBDRV_CONFIG_BLOCK_DEVICE (1)
#define PBDRV_CONFIG_BLOCK_DEVICE_TEST (1)
#define PBDRV_CONFIG_BLOCK_DEVICE_TEST_SIZE (8 * 1024)
#define PBDRV_CONFIG_BLOCK_DEVICE_TEST_SIZE_USER (512)

// FIXME: Can't build without a port
#define PBDRV_CONFIG_HAS_PORT_A (1)
#define PBDRV_CONFIG_HAS_PORT_B (1)
#define PBDRV_CONFIG_HAS_PORT_C (1)
Expand Down
30 changes: 28 additions & 2 deletions lib/pbio/platform/ev3/platform.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,30 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
// Copyright (c) 2024 The Pybricks Authors

// This file is unused, but required for the common make file.

#include <stdint.h>

typedef struct {
volatile uint8_t *thr;
volatile uint8_t *lsr;
} debug_uart_t;

// Sensor port 1
static debug_uart_t UART0 = { .thr = (volatile uint8_t *)0x01D0C000, .lsr = (volatile uint8_t *)0x01D0C014 };

static void debug(debug_uart_t *uart, const char *s) {
while (*s) {
while ((*uart->lsr & (1 << 5)) == 0) {
}
*uart->thr = *s++;
}
}

// Called from assembly code in startup.s. After this, the "main" function in
// lib/pbio/sys/main.c is called. That contains all calls to the driver
// initialization (low level in pbdrv, high level in pbio), and system level
// functions for running user code (currently a hardcoded MicroPython script).
void SystemInit(void) {
debug(&UART0, "System init in platform.c called from startup.s\n\n");
// TODO: TIAM1808 system init
}
59 changes: 25 additions & 34 deletions lib/pbio/platform/ev3/startup.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,36 @@
// Make _start global.
.globl _start

// Entry point for the kernel.
// r15 -> should begin execution at 0x8000.
// r0 -> 0x00000000
// r1 -> 0x00000C42
// r2 -> 0x00000100 - start of ATAGS
// preserve these registers as argument for kernel_main
_start:
// Setup the stack.
ldr sp, =__bss_end
// Setup the stack.
ldr sp, =__bss_end

// Clear out bss.
ldr r4, =__bss_start
ldr r9, =__bss_end
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
b 2f
// Clear out bss.
ldr r4, =__bss_start
ldr r9, =__bss_end
mov r5, #0
mov r6, #0
mov r7, #0
mov r8, #0
b 2f

1:
// store multiple at r4.
stmia r4!, {r5-r8}
// store multiple at r4.
stmia r4!, {r5-r8}

// If we are still below bss_end, loop.
// If we are still below bss_end, loop.
2:
cmp r4, r9
blo 1b

//poke serial register
//ldr r3, =#0x01D0C000
//ldr r3, =#0x101f1000
//mov r4, #'a'
//strb r4, [r3]
cmp r4, r9
blo 1b

// Call SystemInit
ldr r3, =SystemInit
blx r3

// Call main
ldr r3, =main
blx r3

// Call main
ldr r3, =main
blx r3

// halt
halt:
wfe
b halt
wfe
b halt

0 comments on commit baf7047

Please sign in to comment.