1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
//! Does `std.Io.sleep` wake up on this chip?
//!
//! Written to answer one question during radio bring-up. ESP-Hosted's transport stops immediately
//! after a successful SDIO card init, at a `_h_msleep(100)` - and a cooperative scheduler whose
//! sleep never returns is indistinguishable, from the outside, from a driver that hung. The 21 host
//! tests in src/io/p4.zig cover the scheduler against a virtual clock; what they cannot cover is
//! whether a real deadline against the real systimer ever comes due.
//!
//! Four claims, each answered by the die:
//!
//! MARK IO_NOW the timebase advances at all, and at 16 MHz
//! MARK IO_SLEEP a sleep from the main task returns, and after roughly the right time
//! MARK IO_TASK a spawned task runs, sleeps, and finishes
//! MARK IO_ORDER three tasks with different deadlines wake in deadline order
//!
//! Run: zig build -Dapp=examples/iocheck.zig run -Dseconds=15
const std = @import("std");
const soc = @import("soc");
const hal = @import("hal");
const p4 = @import("io");
pub const std_options: std.Options = .{ .page_size_min = 4096 };
pub const panic = std.debug.FullPanic(struct {
fn call(msg: []const u8, _: ?usize) noreturn {
soc.rom.print("MARK IO_PANIC %s\r\n", .{msg.ptr});
while (true) {}
}
}.call);
var pool: p4.Static(4, 4096) = .{};
/// Wake order, appended by the three tasks in `IO_ORDER`.
var order: [3]u8 = .{ 0, 0, 0 };
var order_len: usize = 0;
fn sleeper(ctx: struct { io: std.Io, ms: i64, tag: u8 }) void {
ctx.io.sleep(.fromMilliseconds(ctx.ms), .awake) catch {};
order[order_len] = ctx.tag;
order_len += 1;
}
export fn zig_main() noreturn {
// The bootloader leaves this armed and nothing here feeds it.
_ = hal.rwdt.disable();
const runtime = pool.init(.{});
const io = runtime.io();
// 1. Does the timebase move? Everything below is meaningless if not.
const t0 = hal.systimer.read(.unit0) orelse 0;
soc.rom.ets_delay_us(10_000);
const t1 = hal.systimer.read(.unit0) orelse 0;
soc.rom.print("MARK IO_NOW advanced=%u ticks expect~160000\r\n", .{@as(u32, @truncate(t1 - t0))});
// 2. The question that matters: does a sleep from the calling task return? Measured against the
// systimer rather than trusted, because a sleep that returns instantly would also look like
// success from a print alone.
const before = hal.systimer.read(.unit0) orelse 0;
io.sleep(.fromMilliseconds(100), .awake) catch |err| {
soc.rom.print("MARK IO_SLEEP failed=%s\r\n", .{@errorName(err).ptr});
park();
};
const after = hal.systimer.read(.unit0) orelse 0;
const slept_ms = (after - before) / 16_000;
soc.rom.print("MARK IO_SLEEP returned after %u ms, asked 100\r\n", .{@as(u32, @truncate(slept_ms))});
// 3. A spawned task that sleeps: this is the shape ESP-Hosted's threads have.
var fut = io.async(sleeper, .{.{ .io = io, .ms = 20, .tag = 'A' }});
fut.await(io);
soc.rom.print("MARK IO_TASK ran=%u\r\n", .{@as(u32, @intCast(order_len))});
// 4. Three deadlines, out of submission order, to prove the scheduler picks the earliest.
order_len = 0;
var f1 = io.async(sleeper, .{.{ .io = io, .ms = 60, .tag = '3' }});
var f2 = io.async(sleeper, .{.{ .io = io, .ms = 20, .tag = '1' }});
var f3 = io.async(sleeper, .{.{ .io = io, .ms = 40, .tag = '2' }});
f1.await(io);
f2.await(io);
f3.await(io);
soc.rom.print("MARK IO_ORDER %c%c%c expect 123\r\n", .{
@as(u32, order[0]), @as(u32, order[1]), @as(u32, order[2]),
});
soc.rom.print("MARK IO_DONE\r\n", .{});
park();
}
fn park() noreturn {
while (true) {}
}
export fn _start() linksection(".text.entry") callconv(.naked) noreturn {
asm volatile (
\\ li t0, 1 << 13
\\ csrs mstatus, t0
\\ la sp, __stack_top
\\ mv fp, sp
\\ la t0, __bss_start
\\ la t1, __bss_end
\\ bgeu t0, t1, 2f
\\1:
\\ sw zero, 0(t0)
\\ addi t0, t0, 4
\\ bltu t0, t1, 1b
\\2:
\\ j zig_main
);
}
|