forked from M-Labs/artiq
Merge branch 'master' of github.com:m-labs/artiq
This commit is contained in:
commit
59b339462c
|
@ -43,9 +43,8 @@ class _D2HMsgType(Enum):
|
|||
RPC_REQUEST = 10
|
||||
|
||||
FLASH_READ_REPLY = 11
|
||||
FLASH_WRITE_REPLY = 12
|
||||
FLASH_OK_REPLY = 13
|
||||
FLASH_ERROR_REPLY = 14
|
||||
FLASH_OK_REPLY = 12
|
||||
FLASH_ERROR_REPLY = 13
|
||||
|
||||
|
||||
class UnsupportedDevice(Exception):
|
||||
|
@ -148,14 +147,11 @@ class CommGeneric:
|
|||
self.write(b"\x00")
|
||||
self.write(value)
|
||||
_, ty = self._read_header()
|
||||
if ty != _D2HMsgType.FLASH_WRITE_REPLY:
|
||||
if ty != _D2HMsgType.FLASH_OK_REPLY:
|
||||
if ty == _D2HMsgType.FLASH_ERROR_REPLY:
|
||||
raise IOError("Invalid key: not a null-terminated string")
|
||||
raise IOError("Flash storage is full")
|
||||
else:
|
||||
raise IOError("Incorrect reply from device: {}".format(ty))
|
||||
ret = self.read(1)
|
||||
if ret != b"\x01":
|
||||
raise IOError("Flash storage is full")
|
||||
|
||||
def flash_storage_erase(self):
|
||||
self._write_header(9, _H2DMsgType.FLASH_ERASE_REQUEST)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import unittest
|
||||
import asyncio
|
||||
import sys
|
||||
from time import sleep
|
||||
from time import time, sleep
|
||||
|
||||
from artiq import *
|
||||
from artiq.master.scheduler import Scheduler
|
||||
|
@ -27,11 +27,11 @@ def _get_expid(name):
|
|||
}
|
||||
|
||||
|
||||
def _get_basic_steps(rid, expid):
|
||||
def _get_basic_steps(rid, expid, priority=0, flush=False):
|
||||
return [
|
||||
{"action": "setitem", "key": rid, "value":
|
||||
{"pipeline": "main", "status": "pending", "priority": 0,
|
||||
"expid": expid, "due_date": None, "flush": False},
|
||||
{"pipeline": "main", "status": "pending", "priority": priority,
|
||||
"expid": expid, "due_date": None, "flush": flush},
|
||||
"path": []},
|
||||
{"action": "setitem", "key": "status", "value": "preparing",
|
||||
"path": [rid]},
|
||||
|
@ -59,7 +59,7 @@ class SchedulerCase(unittest.TestCase):
|
|||
scheduler = Scheduler(0, _handlers)
|
||||
expid = _get_expid("EmptyExperiment")
|
||||
|
||||
expect = _get_basic_steps(0, expid)
|
||||
expect = _get_basic_steps(1, expid)
|
||||
done = asyncio.Event()
|
||||
expect_idx = 0
|
||||
def notify(notifier, mod):
|
||||
|
@ -72,8 +72,22 @@ class SchedulerCase(unittest.TestCase):
|
|||
|
||||
loop = asyncio.get_event_loop()
|
||||
scheduler.start()
|
||||
|
||||
# Verify that a timed experiment far in the future does not
|
||||
# get run, even if it has high priority.
|
||||
late = time() + 100000
|
||||
expect.insert(0,
|
||||
{"action": "setitem", "key": 0, "value":
|
||||
{"pipeline": "main", "status": "pending", "priority": 99,
|
||||
"expid": expid, "due_date": late, "flush": False},
|
||||
"path": []})
|
||||
scheduler.submit("main", expid, 99, late, False)
|
||||
|
||||
# This one (RID 1) gets run instead.
|
||||
scheduler.submit("main", expid, 0, None, False)
|
||||
|
||||
loop.run_until_complete(done.wait())
|
||||
scheduler.notifier.publish = None
|
||||
loop.run_until_complete(scheduler.stop())
|
||||
|
||||
def test_pause(self):
|
||||
|
@ -106,3 +120,37 @@ class SchedulerCase(unittest.TestCase):
|
|||
scheduler.submit("main", expid, 0, None, False)
|
||||
loop.run_until_complete(done.wait())
|
||||
loop.run_until_complete(scheduler.stop())
|
||||
|
||||
def test_flush(self):
|
||||
scheduler = Scheduler(0, _handlers)
|
||||
expid = _get_expid("EmptyExperiment")
|
||||
|
||||
expect = _get_basic_steps(1, expid, 1, True)
|
||||
expect.insert(1, {"key": "status",
|
||||
"path": [1],
|
||||
"value": "flushing",
|
||||
"action": "setitem"})
|
||||
first_preparing = asyncio.Event()
|
||||
done = asyncio.Event()
|
||||
expect_idx = 0
|
||||
def notify(notifier, mod):
|
||||
nonlocal expect_idx
|
||||
if mod == {"path": [0],
|
||||
"value": "preparing",
|
||||
"key": "status",
|
||||
"action": "setitem"}:
|
||||
first_preparing.set()
|
||||
if mod["path"] == [1] or (mod["path"] == [] and mod["key"] == 1):
|
||||
self.assertEqual(mod, expect[expect_idx])
|
||||
expect_idx += 1
|
||||
if expect_idx >= len(expect):
|
||||
done.set()
|
||||
scheduler.notifier.publish = notify
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
scheduler.start()
|
||||
scheduler.submit("main", expid, 0, None, False)
|
||||
loop.run_until_complete(first_preparing.wait())
|
||||
scheduler.submit("main", expid, 1, None, True)
|
||||
loop.run_until_complete(done.wait())
|
||||
loop.run_until_complete(scheduler.stop())
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
Getting started
|
||||
===============
|
||||
|
||||
.. _connecting-to-the-core-device:
|
||||
|
||||
Connecting to the core device
|
||||
-----------------------------
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ The communication parameters are 115200 8-N-1.
|
|||
|
||||
* You can either set it by generating a flash storage image and then flash it: ::
|
||||
|
||||
$ ~/artiq-dev/artiq/frontend/artiq_mkfs.py flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
||||
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
||||
$ ~/artiq-dev/artiq/frontend/artiq_flash.sh -f flash_storage.img
|
||||
|
||||
* Or you can set it via the runtime test mode command line
|
||||
|
@ -168,6 +168,26 @@ The communication parameters are 115200 8-N-1.
|
|||
.. note:: The reset button of the KC705 board is the "CPU_RST" labeled button.
|
||||
.. warning:: Both those instructions will result in the flash storage being wiped out. However you can use the test mode to change the IP/MAC without erasing everything if you skip the "fserase" command.
|
||||
|
||||
* (optional) Flash the ``idle`` kernel
|
||||
|
||||
The ``idle`` kernel is the kernel (some piece of code running on the core device) which the core device runs whenever it is not connected to a PC via ethernet.
|
||||
This kernel is therefore stored in the :ref:`core device configuration flash storage <core-device-flash-storage>`.
|
||||
To flash the ``idle`` kernel:
|
||||
|
||||
* Compile the ``idle`` experiment:
|
||||
The ``idle`` experiment's ``run()`` method must be a kernel: it must be decorated with the ``@kernel`` decorator (see :ref:`next topic <connecting-to-the-core-device>` for more information about kernels).
|
||||
|
||||
Moreover, since the core device is not connected to the PC: RPC are forbidden in this ``idle`` experiment.
|
||||
::
|
||||
|
||||
$ artiq_compile idle.py
|
||||
|
||||
* Write it into the core device configuration flash storage: ::
|
||||
|
||||
$ artiq_coreconfig -f idle_kernel idle.elf
|
||||
|
||||
.. note:: You can find more information about how to use the ``artiq_coreconfig`` tool on the :ref:`Utilities <core-device-configuration-tool>` page.
|
||||
|
||||
Installing the host-side software
|
||||
---------------------------------
|
||||
|
||||
|
@ -197,31 +217,13 @@ Installing the host-side software
|
|||
.. note::
|
||||
Compilation of LLVM can take more than 30 min on some machines.
|
||||
|
||||
* Install ARTIQ (without the GUI): ::
|
||||
* Install ARTIQ: ::
|
||||
|
||||
$ cd ~/artiq-dev
|
||||
$ git clone https://github.com/m-labs/artiq # if not already done
|
||||
$ cd artiq
|
||||
$ python3 setup.py develop --user
|
||||
|
||||
* Install ARTIQ (with the GUI): ::
|
||||
|
||||
$ cd ~/artiq-dev
|
||||
$ git clone https://github.com/m-labs/cairoplot3
|
||||
$ cd cairoplot3
|
||||
$ python3 setup.py install --user
|
||||
$ cd -
|
||||
$ git clone https://github.com/m-labs/gbulb
|
||||
$ cd gbulb
|
||||
$ python3 setup.py install --user
|
||||
$ cd -
|
||||
$ git clone https://github.com/m-labs/artiq # if not already done
|
||||
$ cd artiq
|
||||
$ ARTIQ_GUI=1 python3 setup.py develop --user
|
||||
|
||||
.. note::
|
||||
Use ARTIQ_GUI=1 to install GUI dependencies which are only supported on Linux for now, to install ARTIQ on Windows do not set ARTIQ_GUI.
|
||||
|
||||
* Build the documentation: ::
|
||||
|
||||
$ cd ~/artiq-dev/artiq/doc/manual
|
||||
|
|
|
@ -117,12 +117,11 @@ To write the value ``test_value`` in the key ``my_key``::
|
|||
$ artiq_coreconfig -r my_key
|
||||
b'test_value'
|
||||
|
||||
You can also write entire files in a record using the ``-f`` parameter::
|
||||
You can also write entire files in a record using the ``-f`` parameter. This is useful for instance to write the ``idle`` kernel in the flash storage::
|
||||
|
||||
$ echo "this_is_a_test" > my_filename
|
||||
$ artiq_coreconfig -f my_key my_filename
|
||||
$ artiq_coreconfig -r my_key
|
||||
b'this_is_a_test\n'
|
||||
$ artiq_coreconfig -f idle_kernel idle.elf
|
||||
$ artiq_coreconfig -r idle_kernel | head -c9
|
||||
b'\x7fELF
|
||||
|
||||
You can write several records at once::
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ unsigned int fs_read(char *key, void *buffer, unsigned int buf_len, unsigned int
|
|||
memcpy(buffer, record.value, min(record.value_len, buf_len));
|
||||
read_length = min(record.value_len, buf_len);
|
||||
if(remain)
|
||||
*remain = max(0, (int)(record.value_len) - (int)buf_len);
|
||||
*remain = max(0, (int)record.value_len - (int)buf_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,6 @@ enum {
|
|||
REMOTEMSG_TYPE_RPC_REQUEST,
|
||||
|
||||
REMOTEMSG_TYPE_FLASH_READ_REPLY,
|
||||
REMOTEMSG_TYPE_FLASH_WRITE_REPLY,
|
||||
REMOTEMSG_TYPE_FLASH_OK_REPLY,
|
||||
REMOTEMSG_TYPE_FLASH_ERROR_REPLY
|
||||
};
|
||||
|
@ -259,9 +258,11 @@ static int process_input(void)
|
|||
value = key + key_len;
|
||||
ret = fs_write(key, value, value_len);
|
||||
|
||||
buffer_out[8] = REMOTEMSG_TYPE_FLASH_WRITE_REPLY;
|
||||
buffer_out[9] = ret;
|
||||
submit_output(10);
|
||||
if(ret)
|
||||
buffer_out[8] = REMOTEMSG_TYPE_FLASH_OK_REPLY;
|
||||
else
|
||||
buffer_out[8] = REMOTEMSG_TYPE_FLASH_ERROR_REPLY;
|
||||
submit_output(9);
|
||||
break;
|
||||
}
|
||||
case REMOTEMSG_TYPE_FLASH_ERASE_REQUEST: {
|
||||
|
|
Loading…
Reference in New Issue