2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-25 11:18:27 +08:00

watchdog support on core device (broken by bug similar to issue #19)

This commit is contained in:
Sebastien Bourdeauducq 2015-04-29 12:58:37 +08:00
parent f60868f084
commit 967145f2dc
15 changed files with 241 additions and 26 deletions

View File

@ -12,6 +12,8 @@ llvm.initialize_all_targets()
llvm.initialize_all_asmprinters()
_syscalls = {
"watchdog_set": "i:i",
"watchdog_clear": "i:n",
"rtio_set_o": "Iii:n",
"rtio_set_oe": "Iib:n",
"rtio_set_sensitivity": "Iii:n",

View File

@ -120,7 +120,7 @@ class _UnitsLowerer(ast.NodeTransformer):
else:
if any(hasattr(arg, "unit") for arg in node.args):
raise units.DimensionError
elif node.func.id in ("delay", "at", "time_to_cycles"):
elif node.func.id in ("delay", "at", "time_to_cycles", "watchdog"):
if getattr(node.args[0], "unit", None) != "s":
raise units.DimensionError
elif node.func.id == "check_unit":

View File

@ -7,8 +7,7 @@ It does so by inserting multiplication/division/rounding operations around
those calls.
The time_to_cycles and cycles_to_time core language functions are also
implemented here.
implemented here, as well as watchdog to syscall conversion.
"""
import ast
@ -47,6 +46,7 @@ def _cycles_to_time(ref_period, node):
class _TimeQuantizer(ast.NodeTransformer):
def __init__(self, ref_period):
self.ref_period = ref_period
self.watchdog_id_counter = 0
def visit_Call(self, node):
funcname = node.func.id
@ -78,6 +78,51 @@ class _TimeQuantizer(ast.NodeTransformer):
self.generic_visit(node)
return node
def visit_With(self, node):
self.generic_visit(node)
if (isinstance(node.items[0].context_expr, ast.Call)
and node.items[0].context_expr.func.id == "watchdog"):
idname = "__watchdog_id_" + str(self.watchdog_id_counter)
self.watchdog_id_counter += 1
time = ast.BinOp(left=node.items[0].context_expr.args[0],
op=ast.Mult(),
right=ast.Num(1000))
time_int = ast.Call(
func=ast.Name("round", ast.Load()),
args=[time],
keywords=[], starargs=None, kwargs=None)
syscall_set = ast.Call(
func=ast.Name("syscall", ast.Load()),
args=[ast.Str("watchdog_set"), time_int],
keywords=[], starargs=None, kwargs=None)
stmt_set = ast.copy_location(
ast.Assign(targets=[ast.Name(idname, ast.Store())],
value=syscall_set),
node)
syscall_clear = ast.Call(
func=ast.Name("syscall", ast.Load()),
args=[ast.Str("watchdog_clear"),
ast.Name(idname, ast.Load())],
keywords=[], starargs=None, kwargs=None)
stmt_clear = ast.copy_location(ast.Expr(syscall_clear), node)
node.items[0] = ast.withitem(
context_expr=ast.Name(id="sequential",
ctx=ast.Load()),
optional_vars=None)
node.body = [
stmt_set,
ast.Try(body=node.body,
handlers=[],
orelse=[],
finalbody=[stmt_clear])
]
return node
def quantize_time(func_def, ref_period):
_TimeQuantizer(ref_period).visit(func_def)

View File

@ -8,7 +8,7 @@ from artiq.language import units
embeddable_funcs = (
core_language.delay, core_language.at, core_language.now,
core_language.time_to_cycles, core_language.cycles_to_time,
core_language.syscall,
core_language.syscall, core_language.watchdog,
range, bool, int, float, round, len,
core_language.int64, core_language.round64,
Fraction, units.Quantity, units.check_unit, core_language.EncodedException

View File

@ -1,6 +1,6 @@
include $(MSCDIR)/software/common.mak
OBJECTS := isr.o flash_storage.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o main.o
OBJECTS := isr.o flash_storage.o clock.o elf_loader.o services.o session.o log.o test_mode.o kloader.o mailbox.o ksupport_data.o main.o
OBJECTS_KSUPPORT := ksupport.o exception_jmp.o exceptions.o mailbox.o bridge.o rtio.o dds.o
CFLAGS += -Ilwip/src/include -Iliblwip

81
soc/runtime/clock.c Normal file
View File

@ -0,0 +1,81 @@
#include <generated/csr.h>
#include "log.h"
#include "clock.h"
static int clkdiv;
void clock_init(void)
{
timer0_en_write(0);
timer0_load_write(0x7fffffffffffffffLL);
timer0_reload_write(0x7fffffffffffffffLL);
timer0_en_write(1);
clkdiv = identifier_frequency_read()/1000;
}
long long int clock_get_ms(void)
{
long long int clock_sys;
long long int clock_ms;
timer0_update_value_write(1);
clock_sys = 0x7fffffffffffffffLL - timer0_value_read();
clock_ms = clock_sys/clkdiv;
return clock_ms;
}
struct watchdog {
int active;
long long int threshold;
};
static struct watchdog watchdogs[MAX_WATCHDOGS];
void watchdog_init(void)
{
int i;
for(i=0;i<MAX_WATCHDOGS;i++)
watchdogs[i].active = 0;
}
int watchdog_set(int ms)
{
int i, id;
id = -1;
for(i=0;i<MAX_WATCHDOGS;i++)
if(!watchdogs[i].active) {
id = i;
break;
}
if(id < 0) {
log("Failed to add watchdog");
return id;
}
watchdogs[id].active = 1;
watchdogs[id].threshold = clock_get_ms() + ms;
return id;
}
void watchdog_clear(int id)
{
if((id < 0) || (id >= MAX_WATCHDOGS))
return;
watchdogs[id].active = 0;
}
int watchdog_expired(void)
{
int i;
long long int t;
t = 0x7fffffffffffffffLL;
for(i=0;i<MAX_WATCHDOGS;i++)
if(watchdogs[i].active && (watchdogs[i].threshold < t))
t = watchdogs[i].threshold;
return clock_get_ms() > t;
}

14
soc/runtime/clock.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef __CLOCK_H
#define __CLOCK_H
void clock_init(void);
long long int clock_get_ms(void);
#define MAX_WATCHDOGS 16
void watchdog_init(void);
int watchdog_set(int ms);
void watchdog_clear(int id);
int watchdog_expired(void);
#endif /* __CLOCK_H */

View File

@ -8,6 +8,8 @@ from elftools.elf.elffile import ELFFile
services = [
("syscalls", [
("rpc", "rpc"),
("watchdog_set", "watchdog_set"),
("watchdog_clear", "watchdog_clear"),
("rtio_set_o", "rtio_set_o"),
("rtio_set_oe", "rtio_set_oe"),
("rtio_set_sensitivity", "rtio_set_sensitivity"),

View File

@ -7,6 +7,8 @@
#include "rtio.h"
#include "dds.h"
/* for the prototypes for watchdog_set() and watchdog_clear() */
#include "clock.h"
/* for the prototype for rpc() */
#include "session.h"
/* for the prototype for log() */
@ -61,6 +63,34 @@ int main(void)
while(1);
}
int watchdog_set(int ms)
{
struct msg_watchdog_set_request request;
struct msg_watchdog_set_reply *reply;
int id;
request.type = MESSAGE_TYPE_WATCHDOG_SET_REQUEST;
request.ms = ms;
mailbox_send_and_wait(&request);
reply = mailbox_wait_and_receive();
if(reply->type != MESSAGE_TYPE_WATCHDOG_SET_REPLY)
exception_raise(EID_INTERNAL_ERROR);
id = reply->id;
mailbox_acknowledge();
return id;
}
void watchdog_clear(int id)
{
struct msg_watchdog_clear request;
request.type = MESSAGE_TYPE_WATCHDOG_CLEAR;
request.id = id;
mailbox_send_and_wait(&request);
}
int rpc(int rpc_num, ...)
{
struct msg_rpc_request request;

View File

@ -21,26 +21,16 @@
#include <lwip/timers.h>
#endif
#include "clock.h"
#include "test_mode.h"
#include "session.h"
#ifdef CSR_ETHMAC_BASE
unsigned char macadr[6] = {0x10, 0xe2, 0xd5, 0x00, 0x00, 0x00};
static int clkdiv;
u32_t sys_now(void)
{
static unsigned long long int clock_sys;
u32_t clock_ms;
timer0_update_value_write(1);
clock_sys += 0xffffffff - timer0_value_read();
timer0_en_write(0);
timer0_en_write(1);
clock_ms = clock_sys/clkdiv;
return clock_ms;
return clock_get_ms();
}
static struct netif netif;
@ -60,12 +50,6 @@ static void network_init(void)
struct ip4_addr netmask;
struct ip4_addr gateway_ip;
timer0_en_write(0);
timer0_load_write(0xffffffff);
timer0_reload_write(0xffffffff);
timer0_en_write(1);
clkdiv = identifier_frequency_read()/1000;
IP4_ADDR(&local_ip, 192, 168, 0, 42);
IP4_ADDR(&netmask, 255, 255, 255, 0);
IP4_ADDR(&gateway_ip, 192, 168, 0, 1);
@ -276,6 +260,7 @@ static void kserver_service(void)
static void regular_main(void)
{
clock_init();
network_init();
kserver_init();
@ -332,6 +317,8 @@ static void serial_service(void)
static void regular_main(void)
{
clock_init();
/* Open the session for the serial control. */
session_start();
while(1)

View File

@ -6,6 +6,9 @@
enum {
MESSAGE_TYPE_FINISHED,
MESSAGE_TYPE_EXCEPTION,
MESSAGE_TYPE_WATCHDOG_SET_REQUEST,
MESSAGE_TYPE_WATCHDOG_SET_REPLY,
MESSAGE_TYPE_WATCHDOG_CLEAR,
MESSAGE_TYPE_RPC_REQUEST,
MESSAGE_TYPE_RPC_REPLY,
MESSAGE_TYPE_LOG,
@ -32,6 +35,21 @@ struct msg_exception {
long long int eparams[3];
};
struct msg_watchdog_set_request {
int type;
int ms;
};
struct msg_watchdog_set_reply {
int type;
int id;
};
struct msg_watchdog_clear {
int type;
int id;
};
struct msg_rpc_request {
int type;
int rpc_num;

View File

@ -2,6 +2,7 @@
#include "elf_loader.h"
#include "session.h"
#include "clock.h"
#include "rtio.h"
#include "dds.h"
#include "exceptions.h"

View File

@ -7,6 +7,7 @@
#include "mailbox.h"
#include "messages.h"
#include "clock.h"
#include "log.h"
#include "kloader.h"
#include "exceptions.h"
@ -282,6 +283,7 @@ static int process_input(void)
break;
}
watchdog_init();
kloader_start_user_kernel(k);
user_kernel_state = USER_KERNEL_RUNNING;
break;
@ -364,6 +366,9 @@ int session_input(void *data, int len)
return consumed;
}
#include <generated/mem.h>
#define KERNELCPU_MAILBOX MMPTR(MAILBOX_BASE)
/* assumes output buffer is empty when called */
static int process_kmsg(struct msg_base *umsg)
{
@ -379,6 +384,7 @@ static int process_kmsg(struct msg_base *umsg)
kloader_stop_kernel();
user_kernel_state = USER_KERNEL_LOADED;
mailbox_acknowledge();
break;
case MESSAGE_TYPE_EXCEPTION: {
struct msg_exception *msg = (struct msg_exception *)umsg;
@ -390,6 +396,23 @@ static int process_kmsg(struct msg_base *umsg)
kloader_stop_kernel();
user_kernel_state = USER_KERNEL_LOADED;
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_WATCHDOG_SET_REQUEST: {
struct msg_watchdog_set_request *msg = (struct msg_watchdog_set_request *)umsg;
struct msg_watchdog_set_reply reply;
reply.type = MESSAGE_TYPE_WATCHDOG_SET_REPLY;
reply.id = watchdog_set(msg->ms);
mailbox_send_and_wait(&reply);
break;
}
case MESSAGE_TYPE_WATCHDOG_CLEAR: {
struct msg_watchdog_clear *msg = (struct msg_watchdog_clear *)umsg;
watchdog_clear(msg->id);
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_RPC_REQUEST: {
@ -398,12 +421,14 @@ static int process_kmsg(struct msg_base *umsg)
if(!send_rpc_request(msg->rpc_num, msg->args))
return 0;
user_kernel_state = USER_KERNEL_WAIT_RPC;
mailbox_acknowledge();
break;
}
case MESSAGE_TYPE_LOG: {
struct msg_log *msg = (struct msg_log *)umsg;
log(msg->fmt, msg->args);
mailbox_acknowledge();
break;
}
default: {
@ -421,6 +446,12 @@ void session_poll(void **data, int *len)
{
int l;
if((user_kernel_state == USER_KERNEL_RUNNING) && watchdog_expired()) {
log("Watchdog expired");
*len = -1;
return;
}
l = get_out_packet_len();
/* If the output buffer is available,
@ -435,7 +466,6 @@ void session_poll(void **data, int *len)
*len = -1;
return;
}
mailbox_acknowledge();
}
l = get_out_packet_len();
}

View File

@ -6,6 +6,7 @@ from mibuild.xilinx.vivado import XilinxVivadoToolchain
from misoclib.com import gpio
from misoclib.soc import mem_decoder
from misoclib.cpu.peripherals import timer
from targets.kc705 import MiniSoC
from artiq.gateware import amp, rtio, ad9858, nist_qc1
@ -46,7 +47,8 @@ class Top(MiniSoC):
def __init__(self, platform, cpu_type="or1k", **kwargs):
MiniSoC.__init__(self, platform,
cpu_type=cpu_type, **kwargs)
cpu_type=cpu_type, with_timer=False, **kwargs)
self.submodules.timer0 = timer.Timer(width=64)
platform.add_extension(nist_qc1.fmc_adapter_io)
self.submodules.leds = gpio.GPIOOut(Cat(

View File

@ -4,6 +4,7 @@ from migen.bank import wbgen
from misoclib.com import gpio
from misoclib.soc import mem_decoder
from misoclib.cpu.peripherals import timer
from targets.pipistrello import BaseSoC
from artiq.gateware import amp, rtio, ad9858, nist_qc1
@ -66,7 +67,9 @@ class Top(BaseSoC):
mem_map.update(BaseSoC.mem_map)
def __init__(self, platform, cpu_type="or1k", **kwargs):
BaseSoC.__init__(self, platform, cpu_type=cpu_type, **kwargs)
BaseSoC.__init__(self, platform,
cpu_type=cpu_type, with_timer=False, **kwargs)
self.submodules.timer0 = timer.Timer(width=64)
platform.toolchain.ise_commands += """
trce -v 12 -fastpaths -tsi {build_name}.tsi -o {build_name}.twr {build_name}.ncd {build_name}.pcf
"""