/* * AVR emulator * Python interface * * Copyright (C) 2007 Michael Buesch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include "subprocess.h" #include "util.h" #define MODNAME "pyavr8emu" static PyObject *pyavr_except; static void * raise_errno_exception(int err) { int old_errno; if (err < 0) err = -err; old_errno = errno; errno = err; PyErr_SetFromErrno(pyavr_except); errno = old_errno; return NULL; } /***************************************************************************** * Instance-Object definitions * *****************************************************************************/ struct avremu_instance { PyObject_HEAD /* The host part of the emulator instance. */ struct avremu_host_instance host; }; static PyObject * method_instance_load_flash(PyObject *self, PyObject *args) { struct avremu_instance *in = (struct avremu_instance *)self; struct avrmsg_to_device msg; int err; const char *image; int image_size; if (!PyArg_ParseTuple(args, "s#", &image, &image_size)) return NULL; msg.msg = DEVMSG_LOADFLASH; msg.size = image_size; err = sendmsg_to_device(&in->host, &msg); if (err) return raise_errno_exception(err); err = ipc_payload_send(&in->host.msg_to_device, image, image_size); if (err) return raise_errno_exception(err); return Py_None; } static PyObject * method_instance_reset(PyObject *self, PyObject *args) { struct avremu_instance *in = (struct avremu_instance *)self; int err; err = sendnotify_to_device(&in->host, DEVMSG_RESET); if (err) return raise_errno_exception(err); return Py_None; } static PyObject * method_instance_poll_status_msg(PyObject *self, PyObject *args) { struct avremu_instance *in = (struct avremu_instance *)self; int err; char buf[1024]; err = ipc_raw_line_poll(&in->host.status_from_device, buf, sizeof(buf)); if (err == 0) return Py_None; if (err < 0) return raise_errno_exception(err); return PyString_FromString(buf); } static PyMethodDef avremu_instance_methods[] = { { "loadFlash", method_instance_load_flash, METH_VARARGS, "Load a binary flash image" }, { "reset", method_instance_reset, METH_NOARGS, "Reset the emulated microcontroller" }, { "pollStatusMsg", method_instance_poll_status_msg, METH_NOARGS, "Poll a status message line" }, { NULL, }, }; static PyObject * avremu_instance_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { struct avremu_instance *in; in = (struct avremu_instance *)type->tp_alloc(type, 0); if (!in) return NULL; return (PyObject *)in; } static int avremu_instance_init(PyObject *obj, PyObject *args, PyObject *kwds) { struct avremu_instance *in = (struct avremu_instance *)obj; int err, arch; static char *kwlist[] = {"arch", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &arch)) return -1; err = avremu_instance_create(&in->host, arch); if (err) { raise_errno_exception(err); return -1; } return 0; } static void avremu_instance_free(PyObject *obj) { struct avremu_instance *in = (struct avremu_instance *)obj; avremu_instance_destroy(&in->host); obj->ob_type->tp_free(obj); } static PyTypeObject avremu_instance_type = { PyObject_HEAD_INIT(NULL) .tp_name = MODNAME ".Instance", .tp_basicsize = sizeof(struct avremu_instance), .tp_methods = avremu_instance_methods, .tp_flags = Py_TPFLAGS_DEFAULT, .tp_new = avremu_instance_new, .tp_init = avremu_instance_init, .tp_dealloc = avremu_instance_free, .tp_doc = "An emulator instance object", }; /***************************************************************************** * Module API functions * *****************************************************************************/ static PyMethodDef pyavr_methods[] = { { NULL, }, }; /***************************************************************************** * Initialization * *****************************************************************************/ #define def_const(m, x) PyModule_AddIntConstant((m), stringify(x), (x)) PyMODINIT_FUNC initpyavr8emu(void) { PyObject *m; if (PyType_Ready(&avremu_instance_type) < 0) return; pyavr_except = PyErr_NewException(MODNAME ".AvrException", PyExc_Exception, NULL); if (!pyavr_except) return; Py_INCREF(pyavr_except); m = Py_InitModule(MODNAME, pyavr_methods); if (!m) { Py_DECREF(pyavr_except); return; } /* Define constants */ def_const(m, AVR_ATMEGA8); def_const(m, AVR_ATMEGA168); /* Build objects */ PyModule_AddObject(m, "AvrException", pyavr_except); Py_INCREF(&avremu_instance_type); PyModule_AddObject(m, "Instance", (PyObject *)&avremu_instance_type); }