2
0
mirror of https://github.com/m-labs/artiq.git synced 2024-12-29 21:23:34 +08:00

Merge commit 'd0b5c3ba7fb' into new-py2llvm

This commit is contained in:
whitequark 2015-11-07 09:41:34 +03:00
commit da622937f6
25 changed files with 325 additions and 148 deletions

View File

@ -166,9 +166,17 @@ fi
set +e set +e
xc3sprog -c $CABLE -R > /dev/null 2>&1 xc3sprog -c $CABLE -R > /dev/null 2>&1
if [ "$?" != "0" ] STATUS=$?
set -e
if [ "$STATUS" == "127" ]
then then
echo "Flashing failed. Maybe you do not have permission to access the USB device?" echo "xc3sprog not found. Please install it or check your PATH."
exit
fi
if [ "$STATUS" != "0" ]
then
echo "Failed to connect to FPGA."
echo "Maybe you do not have permission to access the USB device?"
echo "To fix this you might want to add a udev rule by doing:" echo "To fix this you might want to add a udev rule by doing:"
echo "$ sudo cp $ARTIQ_PREFIX/misc/$UDEV_RULES /etc/udev/rules.d" echo "$ sudo cp $ARTIQ_PREFIX/misc/$UDEV_RULES /etc/udev/rules.d"
echo "Then unplug/replug your device and try flashing again" echo "Then unplug/replug your device and try flashing again"
@ -177,7 +185,6 @@ then
echo "Please make sure you used the correct -t option (currently: $BOARD)" echo "Please make sure you used the correct -t option (currently: $BOARD)"
exit exit
fi fi
set -e
if [ ! -z "$FILENAME" ] if [ ! -z "$FILENAME" ]
then then

View File

@ -83,7 +83,12 @@ def main():
"log": log_worker "log": log_worker
} }
scheduler = Scheduler(get_last_rid() + 1, worker_handlers, repo_backend) scheduler = Scheduler(get_last_rid() + 1, worker_handlers, repo_backend)
worker_handlers["scheduler_submit"] = scheduler.submit worker_handlers.update({
"scheduler_submit": scheduler.submit,
"scheduler_delete": scheduler.delete,
"scheduler_request_termination": scheduler.request_termination,
"scheduler_get_status": scheduler.get_status
})
scheduler.start() scheduler.start()
atexit.register(lambda: loop.run_until_complete(scheduler.stop())) atexit.register(lambda: loop.run_until_complete(scheduler.stop()))

View File

@ -38,20 +38,28 @@ class ELFRunner(EnvExperiment):
class DummyScheduler: class DummyScheduler:
def __init__(self): def __init__(self):
self.next_rid = 0 self.rid = 0
self.pipeline_name = "main" self.pipeline_name = "main"
self.priority = 0 self.priority = 0
self.expid = None self.expid = None
self._next_rid = 1
def submit(self, pipeline_name, expid, priority, due_date, flush): def submit(self, pipeline_name, expid, priority, due_date, flush):
rid = self.next_rid rid = self._next_rid
self.next_rid += 1 self._next_rid += 1
logger.info("Submitting: %s, RID=%s", expid, rid) logger.info("Submitting: %s, RID=%s", expid, rid)
return rid return rid
def delete(self, rid): def delete(self, rid):
logger.info("Deleting RID %s", rid) logger.info("Deleting RID %s", rid)
def request_termination(self, rid):
logger.info("Requesting termination of RID %s", rid)
def get_status(self):
return dict()
def pause(self): def pause(self):
pass pass

View File

@ -58,7 +58,7 @@ class DatasetsDock(dockarea.Dock):
self.search = QtGui.QLineEdit() self.search = QtGui.QLineEdit()
self.search.setPlaceholderText("search...") self.search.setPlaceholderText("search...")
self.search.editingFinished.connect(self._search_datasets) self.search.editingFinished.connect(self._search_datasets)
grid.addWidget(self.search, 0, ) grid.addWidget(self.search, 0, 0)
self.table = QtGui.QTableView() self.table = QtGui.QTableView()
self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.table.setSelectionMode(QtGui.QAbstractItemView.NoSelection)

View File

@ -368,12 +368,9 @@ class ExplorerDock(dockarea.Dock):
arguments = self.argeditor_states[key]["argument_values"] arguments = self.argeditor_states[key]["argument_values"]
except KeyError: except KeyError:
arguments = dict() arguments = dict()
asyncio.ensure_future(self.submit_task(self.pipeline.text(), asyncio.ensure_future(self.submit_task(pipeline, expinfo["file"],
expinfo["file"],
expinfo["class_name"], expinfo["class_name"],
arguments, arguments, priority, due_date,
priority,
due_date,
flush)) flush))
def submit_clicked(self): def submit_clicked(self):

View File

@ -6,7 +6,6 @@ from quamash import QtGui, QtCore
from pyqtgraph import dockarea, LayoutWidget from pyqtgraph import dockarea, LayoutWidget
from artiq.protocols.sync_struct import Subscriber from artiq.protocols.sync_struct import Subscriber
from artiq.gui.tools import ListSyncModel
try: try:
QSortFilterProxyModel = QtCore.QSortFilterProxyModel QSortFilterProxyModel = QtCore.QSortFilterProxyModel
@ -26,11 +25,19 @@ def _level_to_name(level):
return "DEBUG" return "DEBUG"
class _LogModel(ListSyncModel): class _LogModel(QtCore.QAbstractTableModel):
def __init__(self, parent, init): def __init__(self, parent, init):
ListSyncModel.__init__(self, QtCore.QAbstractTableModel.__init__(self, parent)
["Level", "Source", "Time", "Message"],
parent, init) self.headers = ["Level", "Source", "Time", "Message"]
self.entries = init
self.pending_entries = []
self.depth = 1000
timer = QtCore.QTimer(self)
timer.timeout.connect(self.timer_tick)
timer.start(100)
self.fixed_font = QtGui.QFont() self.fixed_font = QtGui.QFont()
self.fixed_font.setFamily("Monospace") self.fixed_font.setFamily("Monospace")
@ -40,28 +47,67 @@ class _LogModel(ListSyncModel):
self.warning_bg = QtGui.QBrush(QtGui.QColor(255, 255, 180)) self.warning_bg = QtGui.QBrush(QtGui.QColor(255, 255, 180))
self.error_bg = QtGui.QBrush(QtGui.QColor(255, 150, 150)) self.error_bg = QtGui.QBrush(QtGui.QColor(255, 150, 150))
def headerData(self, col, orientation, role):
if (orientation == QtCore.Qt.Horizontal
and role == QtCore.Qt.DisplayRole):
return self.headers[col]
return None
def rowCount(self, parent):
return len(self.entries)
def columnCount(self, parent):
return len(self.headers)
def __delitem__(self, k):
pass
def append(self, v):
self.pending_entries.append(v)
def insertRows(self, position, rows=1, index=QtCore.QModelIndex()):
self.beginInsertRows(QtCore.QModelIndex(), position, position+rows-1)
self.endInsertRows()
def removeRows(self, position, rows=1, index=QtCore.QModelIndex()):
self.beginRemoveRows(QtCore.QModelIndex(), position, position+rows-1)
self.endRemoveRows()
def timer_tick(self):
if not self.pending_entries:
return
nrows = len(self.entries)
records = self.pending_entries
self.pending_entries = []
self.entries.extend(records)
self.insertRows(nrows, len(records))
if len(self.entries) > self.depth:
start = len(self.entries) - self.depth
self.entries = self.entries[start:]
self.removeRows(0, start)
def data(self, index, role): def data(self, index, role):
if (role == QtCore.Qt.FontRole and index.isValid() if index.isValid():
if (role == QtCore.Qt.FontRole
and index.column() == 3): and index.column() == 3):
return self.fixed_font return self.fixed_font
elif role == QtCore.Qt.BackgroundRole and index.isValid(): elif role == QtCore.Qt.BackgroundRole:
level = self.backing_store[index.row()][0] level = self.entries[index.row()][0]
if level >= logging.ERROR: if level >= logging.ERROR:
return self.error_bg return self.error_bg
elif level >= logging.WARNING: elif level >= logging.WARNING:
return self.warning_bg return self.warning_bg
else: else:
return self.white return self.white
elif role == QtCore.Qt.ForegroundRole and index.isValid(): elif role == QtCore.Qt.ForegroundRole:
level = self.backing_store[index.row()][0] level = self.entries[index.row()][0]
if level <= logging.DEBUG: if level <= logging.DEBUG:
return self.debug_fg return self.debug_fg
else: else:
return self.black return self.black
else: elif role == QtCore.Qt.DisplayRole:
return ListSyncModel.data(self, index, role) v = self.entries[index.row()]
column = index.column()
def convert(self, v, column):
if column == 0: if column == 0:
return _level_to_name(v[0]) return _level_to_name(v[0])
elif column == 1: elif column == 1:
@ -72,21 +118,39 @@ class _LogModel(ListSyncModel):
return v[3] return v[3]
class _LevelFilterProxyModel(QSortFilterProxyModel): class _LogFilterProxyModel(QSortFilterProxyModel):
def __init__(self, min_level): def __init__(self, min_level, freetext):
QSortFilterProxyModel.__init__(self) QSortFilterProxyModel.__init__(self)
self.min_level = min_level self.min_level = min_level
self.freetext = freetext
def filterAcceptsRow(self, sourceRow, sourceParent): def filterAcceptsRow(self, sourceRow, sourceParent):
model = self.sourceModel() model = self.sourceModel()
index = model.index(sourceRow, 0, sourceParent) index = model.index(sourceRow, 0, sourceParent)
data = model.data(index, QtCore.Qt.DisplayRole) data = model.data(index, QtCore.Qt.DisplayRole)
return getattr(logging, data) >= self.min_level accepted_level = getattr(logging, data) >= self.min_level
if self.freetext:
index = model.index(sourceRow, 1, sourceParent)
data_source = model.data(index, QtCore.Qt.DisplayRole)
index = model.index(sourceRow, 3, sourceParent)
data_message = model.data(index, QtCore.Qt.DisplayRole)
accepted_freetext = (self.freetext in data_source
or self.freetext in data_message)
else:
accepted_freetext = True
return accepted_level and accepted_freetext
def set_min_level(self, min_level): def set_min_level(self, min_level):
self.min_level = min_level self.min_level = min_level
self.invalidateFilter() self.invalidateFilter()
def set_freetext(self, freetext):
self.freetext = freetext
self.invalidateFilter()
class LogDock(dockarea.Dock): class LogDock(dockarea.Dock):
def __init__(self): def __init__(self):
@ -96,14 +160,17 @@ class LogDock(dockarea.Dock):
self.addWidget(grid) self.addWidget(grid)
grid.addWidget(QtGui.QLabel("Minimum level: "), 0, 0) grid.addWidget(QtGui.QLabel("Minimum level: "), 0, 0)
grid.layout.setColumnStretch(0, 0) self.filter_level = QtGui.QComboBox()
grid.layout.setColumnStretch(1, 0) self.filter_level.addItems(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"])
grid.layout.setColumnStretch(2, 1) self.filter_level.setToolTip("Display entries at or above this level")
self.filterbox = QtGui.QComboBox() grid.addWidget(self.filter_level, 0, 1)
self.filterbox.addItems(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]) self.filter_level.currentIndexChanged.connect(
self.filterbox.setToolTip("Display entries at or above this level") self.filter_level_changed)
grid.addWidget(self.filterbox, 0, 1) self.filter_freetext = QtGui.QLineEdit()
self.filterbox.currentIndexChanged.connect(self.filter_changed) self.filter_freetext.setPlaceholderText("freetext filter...")
self.filter_freetext.editingFinished.connect(
self.filter_freetext_changed)
grid.addWidget(self.filter_freetext, 0, 2)
self.log = QtGui.QTableView() self.log = QtGui.QTableView()
self.log.setSelectionMode(QtGui.QAbstractItemView.NoSelection) self.log.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
@ -113,7 +180,7 @@ class LogDock(dockarea.Dock):
QtGui.QAbstractItemView.ScrollPerPixel) QtGui.QAbstractItemView.ScrollPerPixel)
self.log.setShowGrid(False) self.log.setShowGrid(False)
self.log.setTextElideMode(QtCore.Qt.ElideNone) self.log.setTextElideMode(QtCore.Qt.ElideNone)
grid.addWidget(self.log, 1, 0, colspan=3) grid.addWidget(self.log, 1, 0, colspan=4)
self.scroll_at_bottom = False self.scroll_at_bottom = False
async def sub_connect(self, host, port): async def sub_connect(self, host, port):
@ -123,30 +190,49 @@ class LogDock(dockarea.Dock):
async def sub_close(self): async def sub_close(self):
await self.subscriber.close() await self.subscriber.close()
def filter_changed(self): def filter_level_changed(self):
self.table_model_filter.set_min_level( self.table_model_filter.set_min_level(
getattr(logging, self.filterbox.currentText())) getattr(logging, self.filter_level.currentText()))
def filter_freetext_changed(self):
self.table_model_filter.set_freetext(self.filter_freetext.text())
def rows_inserted_before(self): def rows_inserted_before(self):
scrollbar = self.log.verticalScrollBar() scrollbar = self.log.verticalScrollBar()
self.scroll_at_bottom = scrollbar.value() == scrollbar.maximum() self.scroll_value = scrollbar.value()
self.scroll_at_bottom = self.scroll_value == scrollbar.maximum()
def rows_inserted_after(self): def rows_inserted_after(self):
if self.scroll_at_bottom: if self.scroll_at_bottom:
self.log.scrollToBottom() self.log.scrollToBottom()
# HACK:
# Qt intermittently likes to scroll back to the top when rows are removed.
# Work around this by restoring the scrollbar to the previously memorized
# position, after the removal.
# Note that this works because _LogModel always does the insertion right
# before the removal.
def rows_removed(self):
if self.scroll_at_bottom:
self.log.scrollToBottom()
else:
scrollbar = self.log.verticalScrollBar()
scrollbar.setValue(self.scroll_value)
def init_log_model(self, init): def init_log_model(self, init):
table_model = _LogModel(self.log, init) self.table_model = _LogModel(self.log, init)
self.table_model_filter = _LevelFilterProxyModel( self.table_model_filter = _LogFilterProxyModel(
getattr(logging, self.filterbox.currentText())) getattr(logging, self.filter_level.currentText()),
self.table_model_filter.setSourceModel(table_model) self.filter_freetext.text())
self.table_model_filter.setSourceModel(self.table_model)
self.log.setModel(self.table_model_filter) self.log.setModel(self.table_model_filter)
self.table_model_filter.rowsAboutToBeInserted.connect(self.rows_inserted_before) self.table_model_filter.rowsAboutToBeInserted.connect(self.rows_inserted_before)
self.table_model_filter.rowsInserted.connect(self.rows_inserted_after) self.table_model_filter.rowsInserted.connect(self.rows_inserted_after)
return table_model self.table_model_filter.rowsRemoved.connect(self.rows_removed)
return self.table_model
def save_state(self): def save_state(self):
return {"min_level_idx": self.filterbox.currentIndex()} return {"min_level_idx": self.filter_level.currentIndex()}
def restore_state(self, state): def restore_state(self, state):
try: try:
@ -154,4 +240,4 @@ class LogDock(dockarea.Dock):
except KeyError: except KeyError:
pass pass
else: else:
self.filterbox.setCurrentIndex(idx) self.filter_level.setCurrentIndex(idx)

View File

@ -412,6 +412,7 @@ class Scheduler:
logger.warning("some pipelines were not garbage-collected") logger.warning("some pipelines were not garbage-collected")
def submit(self, pipeline_name, expid, priority, due_date, flush): def submit(self, pipeline_name, expid, priority, due_date, flush):
"""Submits a new run."""
# mutates expid to insert head repository revision if None # mutates expid to insert head repository revision if None
if self._terminated: if self._terminated:
return return
@ -427,9 +428,11 @@ class Scheduler:
return pipeline.pool.submit(expid, priority, due_date, flush, pipeline_name) return pipeline.pool.submit(expid, priority, due_date, flush, pipeline_name)
def delete(self, rid): def delete(self, rid):
"""Kills the run with the specified RID."""
self._deleter.delete(rid) self._deleter.delete(rid)
def request_termination(self, rid): def request_termination(self, rid):
"""Requests graceful termination of the run with the specified RID."""
for pipeline in self._pipelines.values(): for pipeline in self._pipelines.values():
if rid in pipeline.pool.runs: if rid in pipeline.pool.runs:
run = pipeline.pool.runs[rid] run = pipeline.pool.runs[rid]
@ -438,3 +441,8 @@ class Scheduler:
else: else:
self.delete(rid) self.delete(rid)
break break
def get_status(self):
"""Returns a dictionary containing information about the runs currently
tracked by the scheduler."""
return self.notifier.read

View File

@ -95,9 +95,13 @@ class Scheduler:
raise TerminationRequested raise TerminationRequested
submit = staticmethod(make_parent_action("scheduler_submit")) submit = staticmethod(make_parent_action("scheduler_submit"))
cancel = staticmethod(make_parent_action("scheduler_cancel")) delete = staticmethod(make_parent_action("scheduler_delete"))
request_termination = staticmethod(
make_parent_action("scheduler_request_termination"))
get_status = staticmethod(make_parent_action("scheduler_get_status"))
def set_run_info(self, pipeline_name, expid, priority): def set_run_info(self, rid, pipeline_name, expid, priority):
self.rid = rid
self.pipeline_name = pipeline_name self.pipeline_name = pipeline_name
self.expid = expid self.expid = expid
self.priority = priority self.priority = priority
@ -182,7 +186,7 @@ def main():
expf = expid["file"] expf = expid["file"]
exp = get_exp(expf, expid["class_name"]) exp = get_exp(expf, expid["class_name"])
device_mgr.virtual_devices["scheduler"].set_run_info( device_mgr.virtual_devices["scheduler"].set_run_info(
obj["pipeline_name"], expid, obj["priority"]) rid, obj["pipeline_name"], expid, obj["priority"])
exp_inst = exp(device_mgr, dataset_mgr, exp_inst = exp(device_mgr, dataset_mgr,
**expid["arguments"]) **expid["arguments"])
put_object({"action": "completed"}) put_object({"action": "completed"})

View File

@ -50,9 +50,14 @@ Then you can install the ARTIQ package, it will pull all the necessary dependenc
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-pipistrello-nist_qc1; \ $ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-pipistrello-nist_qc1; \
echo "Created environment $ENV for ARTIQ" echo "Created environment $ENV for ARTIQ"
* For the KC705 board:: * For the KC705 board with SCSI cables and AD9858 DDS chips::
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_qc1 artiq-kc705-nist_qc2; \ $ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_qc1; \
echo "Created environment $ENV for ARTIQ"
* For the KC705 board with the FMC backplane and AD9914 DDS chips::
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_qc2; \
echo "Created environment $ENV for ARTIQ" echo "Created environment $ENV for ARTIQ"
This creates a new Conda "environment" (i.e. an isolated installation) and prints its name. This creates a new Conda "environment" (i.e. an isolated installation) and prints its name.

View File

@ -111,8 +111,18 @@ Push commits containing experiments to the bare repository using e.g. Git over S
The GUI always runs experiments from the repository. The command-line client, by default, runs experiment from the raw filesystem (which is useful for iterating rapidly without creating many disorganized commits). If you want to use the repository instead, simply pass the ``-R`` option. The GUI always runs experiments from the repository. The command-line client, by default, runs experiment from the raw filesystem (which is useful for iterating rapidly without creating many disorganized commits). If you want to use the repository instead, simply pass the ``-R`` option.
Reference Scheduler API reference
********* ***********************
The scheduler is exposed to the experiments via a virtual device called ``scheduler``. It can be requested like any regular device, and then the methods below can be called on the returned object.
The scheduler virtual device also contains the attributes ``rid``, ``pipeline_name``, ``priority`` and ``expid`` that contain the corresponding information about the current run.
.. autoclass:: artiq.master.scheduler.Scheduler
:members:
Front-end tool reference
************************
.. argparse:: .. argparse::
:ref: artiq.frontend.artiq_master.get_argparser :ref: artiq.frontend.artiq_master.get_argparser

View File

@ -0,0 +1,13 @@
from artiq import *
class BlinkForever(EnvExperiment):
def build(self):
self.setattr_device("core")
self.setattr_device("led")
@kernel
def run(self):
while True:
self.led.pulse(100*ms)
delay(100*ms)

View File

@ -0,0 +1,17 @@
from artiq import *
class TerminateAll(EnvExperiment):
def build(self):
self.setattr_device("scheduler")
self.setattr_argument("graceful_termination", BooleanValue(True))
def run(self):
if self.graceful_termination:
terminate = self.scheduler.request_termination
else:
terminate = self.scheduler.delete
for rid in self.scheduler.get_status().keys():
if rid != self.scheduler.rid:
terminate(rid)

View File

@ -66,10 +66,6 @@ void bridge_main(void)
mailbox_acknowledge(); mailbox_acknowledge();
break; break;
} }
case MESSAGE_TYPE_BRG_DDS_INITALL:
dds_init_all();
mailbox_acknowledge();
break;
case MESSAGE_TYPE_BRG_DDS_SEL: { case MESSAGE_TYPE_BRG_DDS_SEL: {
struct msg_brg_dds_sel *msg; struct msg_brg_dds_sel *msg;

View File

@ -23,11 +23,6 @@ void brg_start(void)
} }
} }
void brg_stop(void)
{
kloader_stop();
}
void brg_ttloe(int n, int value) void brg_ttloe(int n, int value)
{ {
struct msg_brg_ttl_out msg; struct msg_brg_ttl_out msg;
@ -48,14 +43,6 @@ void brg_ttlo(int n, int value)
mailbox_send_and_wait(&msg); mailbox_send_and_wait(&msg);
} }
void brg_ddsinitall(void)
{
struct msg_base msg;
msg.type = MESSAGE_TYPE_BRG_DDS_INITALL;
mailbox_send_and_wait(&msg);
}
void brg_ddssel(int channel) void brg_ddssel(int channel)
{ {
struct msg_brg_dds_sel msg; struct msg_brg_dds_sel msg;

View File

@ -2,12 +2,10 @@
#define __BRIDGE_CTL_H #define __BRIDGE_CTL_H
void brg_start(void); void brg_start(void);
void brg_stop(void);
void brg_ttloe(int n, int value); void brg_ttloe(int n, int value);
void brg_ttlo(int n, int value); void brg_ttlo(int n, int value);
void brg_ddsinitall(void);
void brg_ddssel(int channel); void brg_ddssel(int channel);
void brg_ddsreset(void); void brg_ddsreset(void);
unsigned int brg_ddsread(unsigned int address); unsigned int brg_ddsread(unsigned int address);

View File

@ -62,7 +62,7 @@ int watchdog_set(int ms)
break; break;
} }
if(id < 0) { if(id < 0) {
log("Failed to add watchdog"); log("WARNING: Failed to add watchdog");
return id; return id;
} }

View File

@ -33,19 +33,6 @@
now += DURATION_WRITE; \ now += DURATION_WRITE; \
} while(0) } while(0)
void dds_init_all(void)
{
int i;
long long int now;
now = rtio_get_counter() + 10000;
for(i=0;i<DDS_CHANNEL_COUNT;i++) {
dds_init(now, i);
now += DURATION_INIT + DURATION_WRITE; /* + FUD time */
}
while(rtio_get_counter() < now);
}
void dds_init(long long int timestamp, int channel) void dds_init(long long int timestamp, int channel)
{ {
long long int now; long long int now;

View File

@ -54,7 +54,6 @@ enum {
PHASE_MODE_TRACKING = 2 PHASE_MODE_TRACKING = 2
}; };
void dds_init_all(void);
void dds_init(long long int timestamp, int channel); void dds_init(long long int timestamp, int channel);
void dds_batch_enter(long long int timestamp); void dds_batch_enter(long long int timestamp);
void dds_batch_exit(void); void dds_batch_exit(void);

View File

@ -5,6 +5,7 @@
#include "kloader.h" #include "kloader.h"
#include "log.h" #include "log.h"
#include "clock.h"
#include "flash_storage.h" #include "flash_storage.h"
#include "mailbox.h" #include "mailbox.h"
#include "messages.h" #include "messages.h"
@ -87,22 +88,37 @@ void kloader_start_kernel()
load_or_start_kernel(NULL, 1); load_or_start_kernel(NULL, 1);
} }
int kloader_start_idle_kernel(void) static int kloader_start_flash_kernel(char *key)
{ {
#if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE) #if (defined CSR_SPIFLASH_BASE && defined SPIFLASH_PAGE_SIZE)
char buffer[32*1024]; char buffer[32*1024];
int length; int length, remain;
length = fs_read("idle_kernel", buffer, sizeof(buffer), NULL); length = fs_read(key, buffer, sizeof(buffer), &remain);
if(length <= 0) if(length <= 0)
return 0; return 0;
if(remain) {
log("ERROR: kernel %s is too large", key);
return 0;
}
return load_or_start_kernel(buffer, 1); return load_or_start_kernel(buffer, 1);
#else #else
return 0; return 0;
#endif #endif
} }
int kloader_start_startup_kernel(void)
{
return kloader_start_flash_kernel("startup_kernel");
}
int kloader_start_idle_kernel(void)
{
return kloader_start_flash_kernel("idle_kernel");
}
void kloader_stop(void) void kloader_stop(void)
{ {
kernel_cpu_reset_write(1); kernel_cpu_reset_write(1);
@ -125,6 +141,8 @@ int kloader_is_essential_kmsg(int msgtype)
case MESSAGE_TYPE_NOW_INIT_REQUEST: case MESSAGE_TYPE_NOW_INIT_REQUEST:
case MESSAGE_TYPE_NOW_SAVE: case MESSAGE_TYPE_NOW_SAVE:
case MESSAGE_TYPE_LOG: case MESSAGE_TYPE_LOG:
case MESSAGE_TYPE_WATCHDOG_SET_REQUEST:
case MESSAGE_TYPE_WATCHDOG_CLEAR:
return 1; return 1;
default: default:
return 0; return 0;
@ -168,6 +186,22 @@ void kloader_service_essential_kmsg(void)
mailbox_acknowledge(); mailbox_acknowledge();
break; 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;
}
default: default:
/* handled elsewhere */ /* handled elsewhere */
break; break;

View File

@ -15,6 +15,7 @@ void kloader_filter_backtrace(struct artiq_backtrace_item *backtrace,
size_t *backtrace_size); size_t *backtrace_size);
void kloader_start_bridge(void); void kloader_start_bridge(void);
int kloader_start_startup_kernel(void);
int kloader_start_idle_kernel(void); int kloader_start_idle_kernel(void);
void kloader_start_kernel(void); void kloader_start_kernel(void);
void kloader_stop(void); void kloader_stop(void);

View File

@ -30,13 +30,6 @@
#include "session.h" #include "session.h"
#include "moninj.h" #include "moninj.h"
static void common_init(void)
{
brg_start();
brg_ddsinitall();
kloader_stop();
}
#ifdef CSR_ETHMAC_BASE #ifdef CSR_ETHMAC_BASE
u32_t sys_now(void) u32_t sys_now(void)
@ -261,7 +254,7 @@ int main(void)
test_main(); test_main();
} else { } else {
puts("Entering regular mode."); puts("Entering regular mode.");
common_init(); session_startup_kernel();
regular_main(); regular_main();
} }
return 0; return 0;

View File

@ -22,7 +22,6 @@ enum {
MESSAGE_TYPE_BRG_READY, MESSAGE_TYPE_BRG_READY,
MESSAGE_TYPE_BRG_TTL_O, MESSAGE_TYPE_BRG_TTL_O,
MESSAGE_TYPE_BRG_TTL_OE, MESSAGE_TYPE_BRG_TTL_OE,
MESSAGE_TYPE_BRG_DDS_INITALL,
MESSAGE_TYPE_BRG_DDS_SEL, MESSAGE_TYPE_BRG_DDS_SEL,
MESSAGE_TYPE_BRG_DDS_RESET, MESSAGE_TYPE_BRG_DDS_RESET,
MESSAGE_TYPE_BRG_DDS_READ_REQUEST, MESSAGE_TYPE_BRG_DDS_READ_REQUEST,

View File

@ -1,6 +1,6 @@
#include <stdio.h>
#include <generated/csr.h> #include <generated/csr.h>
#include "log.h"
#include "clock.h" #include "clock.h"
#include "flash_storage.h" #include "flash_storage.h"
#include "rtiocrg.h" #include "rtiocrg.h"
@ -17,17 +17,17 @@ void rtiocrg_init(void)
clk = 0; clk = 0;
fs_read("startup_clock", &b, 1, NULL); fs_read("startup_clock", &b, 1, NULL);
if(b == 'i') if(b == 'i')
printf("Startup RTIO clock: internal\n"); log("Startup RTIO clock: internal");
else if(b == 'e') { else if(b == 'e') {
printf("Startup RTIO clock: external\n"); log("Startup RTIO clock: external");
clk = 1; clk = 1;
} else } else
printf("WARNING: unknown startup_clock entry in flash storage\n"); log("ERROR: unrecognized startup_clock entry in flash storage");
if(!rtiocrg_switch_clock(clk)) { if(!rtiocrg_switch_clock(clk)) {
printf("WARNING: startup RTIO clock failed\n"); log("ERROR: startup RTIO clock failed");
printf("WARNING: this may cause the system initialization to fail\n"); log("WARNING: this may cause the system initialization to fail");
printf("WARNING: fix clocking and reset the device\n"); log("WARNING: fix clocking and reset the device");
} }
} }

View File

@ -290,6 +290,44 @@ enum {
USER_KERNEL_WAIT_RPC /* < must come after _RUNNING */ USER_KERNEL_WAIT_RPC /* < must come after _RUNNING */
}; };
void session_startup_kernel(void)
{
struct msg_base *umsg;
now = -1;
watchdog_init();
if(!kloader_start_startup_kernel())
return;
while(1) {
kloader_service_essential_kmsg();
umsg = mailbox_receive();
if(umsg) {
if(!kloader_validate_kpointer(umsg))
break;
if(kloader_is_essential_kmsg(umsg->type))
continue;
if(umsg->type == MESSAGE_TYPE_FINISHED)
break;
else if(umsg->type == MESSAGE_TYPE_EXCEPTION) {
log("WARNING: startup kernel ended with exception");
break;
} else {
log("ERROR: received invalid message type from kernel CPU");
break;
}
}
if(watchdog_expired()) {
log("WARNING: watchdog expired in startup kernel");
break;
}
}
kloader_stop();
log("Startup kernel terminated");
}
void session_start(void) void session_start(void)
{ {
in_packet_reset(); in_packet_reset();
@ -304,6 +342,7 @@ void session_end(void)
{ {
kloader_stop(); kloader_stop();
now = -1; now = -1;
watchdog_init();
kloader_start_idle_kernel(); kloader_start_idle_kernel();
} }
@ -914,24 +953,6 @@ static int process_kmsg(struct msg_base *umsg)
break; 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_SEND: { case MESSAGE_TYPE_RPC_SEND: {
struct msg_rpc_send *msg = (struct msg_rpc_send *)umsg; struct msg_rpc_send *msg = (struct msg_rpc_send *)umsg;
@ -946,11 +967,12 @@ static int process_kmsg(struct msg_base *umsg)
break; break;
} }
default: default: {
log("Received invalid message type %d from kernel CPU", log("Received invalid message type %d from kernel CPU",
umsg->type); umsg->type);
return 0; return 0;
} }
}
return 1; return 1;
} }

View File

@ -1,6 +1,7 @@
#ifndef __SESSION_H #ifndef __SESSION_H
#define __SESSION_H #define __SESSION_H
void session_startup_kernel(void);
void session_start(void); void session_start(void);
void session_end(void); void session_end(void);