From: Manfred Steiner Date: Sun, 27 Nov 2022 17:49:11 +0000 (+0100) Subject: debian packet fails created by make removed from repositoy X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=52f4c0ed3c8d0718f40062ab927f208af0fd656f;p=sx%2Fsimavr.git debian packet fails created by make removed from repositoy --- diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/DEBIAN/control b/examples/simuc/dpkg/htl-simuc_version_arch/DEBIAN/control deleted file mode 100644 index 6b155e4..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/DEBIAN/control +++ /dev/null @@ -1,10 +0,0 @@ -Package: htl-simuc -Version: 0.0.1~1 -Section: devel -Architecture: amd64 -Depends: libelf1 -Recommends: gcc-avr, avr-libc, gdb-avr, binutils-avr, avrdude -Installed-Size: 4328 -Priority: optional -Maintainer: Manfred Steiner -Description: megaavr microcontroller simulation diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/readme b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/readme deleted file mode 120000 index bf9863d..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/readme +++ /dev/null @@ -1 +0,0 @@ -../doc/htl-simuc/readme \ No newline at end of file diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr/avr_mcu_section.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr/avr_mcu_section.h deleted file mode 100644 index 3deae7b..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr/avr_mcu_section.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - avr_mcu_section.h - - Copyright 2008-2013 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_MCU_SECTION_H__ -#define __AVR_MCU_SECTION_H__ - -/* - * This header is used to pass "parameters" to the programmer or the simulator, - * it tags the ELF file with a section that contains parameters about the physical - * AVR this was compiled for, including the speed, model, and signature bytes. - * - * A programmer software can read this and verify fuses values for example, and a - * simulator can instantiate the proper "model" of AVR, the speed and so on without - * command line parameters. - * - * Example of use: - * - * #include "avr_mcu_section.h" - * AVR_MCU(F_CPU, "atmega88"); - * - */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - AVR_MMCU_TAG = 0, - AVR_MMCU_TAG_NAME, - AVR_MMCU_TAG_FREQUENCY, - AVR_MMCU_TAG_VCC, - AVR_MMCU_TAG_AVCC, - AVR_MMCU_TAG_AREF, - AVR_MMCU_TAG_LFUSE, - AVR_MMCU_TAG_HFUSE, - AVR_MMCU_TAG_EFUSE, - AVR_MMCU_TAG_SIGNATURE, - AVR_MMCU_TAG_SIMAVR_COMMAND, - AVR_MMCU_TAG_SIMAVR_CONSOLE, - AVR_MMCU_TAG_VCD_FILENAME, - AVR_MMCU_TAG_VCD_PERIOD, - AVR_MMCU_TAG_VCD_TRACE, - AVR_MMCU_TAG_VCD_PORTPIN, - AVR_MMCU_TAG_VCD_IRQ, - AVR_MMCU_TAG_PORT_EXTERNAL_PULL, -}; - -enum { - SIMAVR_CMD_NONE = 0, - SIMAVR_CMD_VCD_START_TRACE, - SIMAVR_CMD_VCD_STOP_TRACE, - SIMAVR_CMD_UART_LOOPBACK, -}; - -#if __AVR__ -/* - * WARNING. Due to newer GCC being stupid, they introduced a bug that - * prevents us introducing variable length strings in the declaration - * of structs. Worked for a million years, and no longer. - * So the new method declares the string as fixed size, and the parser - * is forced to skip the zeroes in padding. Dumbo. - */ -#define _MMCU_ __attribute__((section(".mmcu"))) __attribute__((used)) -struct avr_mmcu_long_t { - uint8_t tag; - uint8_t len; - uint32_t val; -} __attribute__((__packed__)); - -struct avr_mmcu_string_t { - uint8_t tag; - uint8_t len; - char string[64]; -} __attribute__((__packed__)); - -struct avr_mmcu_addr_t { - uint8_t tag; - uint8_t len; - void * what; -} __attribute__((__packed__)); - -struct avr_mmcu_vcd_trace_t { - uint8_t tag; - uint8_t len; - uint8_t mask; - void * what; - char name[32]; -} __attribute__((__packed__)); - -#define AVR_MCU_STRING(_tag, _str) \ - const struct avr_mmcu_string_t _##_tag _MMCU_ = {\ - .tag = _tag,\ - .len = sizeof(struct avr_mmcu_string_t) - 2,\ - .string = _str,\ - } -/* - * This trick allows concatenation of tokens. We need a macro redirection - * for it to work. - * The goal is to make unique variable names (they don't matter anyway) - */ -#define DO_CONCAT2(_a, _b) _a##_b -#define DO_CONCAT(_a, _b) DO_CONCAT2(_a,_b) - -#define AVR_MCU_LONG(_tag, _val) \ - const struct avr_mmcu_long_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\ - .tag = _tag,\ - .len = sizeof(struct avr_mmcu_long_t) - 2,\ - .val = _val,\ - } - -#define AVR_MCU_BYTE(_tag, _val) \ - const uint8_t _##_tag _MMCU_ = { _tag, 1, _val } - -/*! - * This Macro allows you to specify traces for the VCD file output - * engine. This specifies a default header, and let you fill in the - * relevant bits. - * Example: - * const struct avr_mmcu_vcd_trace_t _mytrace[] _MMCU_ = { - * { AVR_MCU_VCD_SYMBOL("UDR0"), .what = (void*)&UDR0, }, - * { AVR_MCU_VCD_SYMBOL("UDRE0"), .mask = (1 << UDRE0), .what = (void*)&UCSR0A, }, - * }; - * This structure will automatically tell simavr to add a VCD trace - * for the UART register, and the UDRE0 bit, so you can trace exactly - * the timing of the changed using gtkwave. - */ -#define AVR_MCU_VCD_SYMBOL(_name) \ - .tag = AVR_MMCU_TAG_VCD_TRACE, \ - .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ - .name = _name - -/*! - * Specifies the name and wanted period (in usec) for a VCD file - * this is not mandatory for the VCD output to work, if this tag - * is not used, a VCD file will still be created with default values - */ -#define AVR_MCU_VCD_FILE(_name, _period) \ - AVR_MCU_STRING(AVR_MMCU_TAG_VCD_FILENAME, _name);\ - AVR_MCU_LONG(AVR_MMCU_TAG_VCD_PERIOD, _period) - -/*! - * It is possible to send "commands" to simavr from the - * firmware itself. For this to work you need to specify - * an IO register that is to be used for a write-only - * bridge. A favourite is one of the usual "GPIO register" - * that most (all ?) AVR have. - * See definition of SIMAVR_CMD_* to see what commands can - * be used from your firmware. - */ -#define AVR_MCU_SIMAVR_COMMAND(_register) \ - const struct avr_mmcu_addr_t _simavr_command_register _MMCU_ = {\ - .tag = AVR_MMCU_TAG_SIMAVR_COMMAND,\ - .len = sizeof(void *),\ - .what = (void*)_register, \ - } -/*! - * Similar to AVR_MCU_SIMAVR_COMMAND, The CONSOLE allows the AVR code - * to declare a register (typically a GPIO register, but any unused - * register can work...) that will allow printing on the host's console - * without using a UART to do debug. - */ -#define AVR_MCU_SIMAVR_CONSOLE(_register) \ - const struct avr_mmcu_addr_t _simavr_console_register _MMCU_ = {\ - .tag = AVR_MMCU_TAG_SIMAVR_CONSOLE,\ - .len = sizeof(void *),\ - .what = (void*)_register, \ - } -/*! - * Allows the firmware to hint simavr as to wether there are external - * pullups/down on PORT pins. It helps if the firmware uses "open drain" - * pins by toggling the DDR pins to switch between an output state and - * a "default" state. - * The value passed here will be output on the PORT IRQ when the DDR - * pin is set to input again - */ -#define AVR_MCU_EXTERNAL_PORT_PULL(_port, _mask, _val) \ - AVR_MCU_LONG(AVR_MMCU_TAG_PORT_EXTERNAL_PULL, \ - (((unsigned long)((_port)&0xff) << 16) | \ - ((unsigned long)((_mask)&0xff) << 8) | \ - ((_val)&0xff))); -/*! - * Add this port/pin to the VCD file. The syntax uses the name of the - * port as a character, and not a pointer to a register. - * AVR_MCU_VCD_PORT_PIN('B', 5); - */ -#define AVR_MCU_VCD_PORT_PIN(_port, _pin, _name) \ - const struct avr_mmcu_vcd_trace_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\ - .tag = AVR_MMCU_TAG_VCD_PORTPIN, \ - .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ - .mask = _port, \ - .what = (void*)_pin, \ - .name = _name, \ - } - -/*! - * These allows you to add a trace showing how long an IRQ vector is pending, - * and also how long it is running. You can specify the IRQ as a vector name - * straight from the firmware file, and it will be named properly in the trace - */ - -#define AVR_MCU_VCD_IRQ_TRACE(_vect_number, __what, _trace_name) \ - const struct avr_mmcu_vcd_trace_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\ - .tag = AVR_MMCU_TAG_VCD_IRQ, \ - .len = sizeof(struct avr_mmcu_vcd_trace_t) - 2,\ - .mask = _vect_number, \ - .what = (void*)__what, \ - .name = _trace_name, \ - }; -#define AVR_MCU_VCD_IRQ(_irq_name) \ - AVR_MCU_VCD_IRQ_TRACE(_irq_name##_vect_num, 1, #_irq_name) -#define AVR_MCU_VCD_IRQ_PENDING(_irq_name) \ - AVR_MCU_VCD_IRQ_TRACE(_irq_name##_vect_num, 0, #_irq_name "_pend") -#define AVR_MCU_VCD_ALL_IRQ() \ - AVR_MCU_VCD_IRQ_TRACE(0xff, 1, "IRQ") -#define AVR_MCU_VCD_ALL_IRQ_PENDING() \ - AVR_MCU_VCD_IRQ_TRACE(0xff, 0, "IRQ_PENDING") - -/*! - * This tag allows you to specify the voltages used by your board - * It is optional in most cases, but you will need it if you use - * ADC module's IRQs. Not specifying it in this case might lead - * to a divide-by-zero crash. - * The units are Volts*1000 (millivolts) - */ -#define AVR_MCU_VOLTAGES(_vcc, _avcc, _aref) \ - AVR_MCU_LONG(AVR_MMCU_TAG_VCC, (_vcc));\ - AVR_MCU_LONG(AVR_MMCU_TAG_AVCC, (_avcc));\ - AVR_MCU_LONG(AVR_MMCU_TAG_AREF, (_aref)); - -/*! - * This the has to be used if you want to add other tags to the .mmcu section - * the _mmcu symbol is used as an anchor to make sure it stays linked in. - */ -#define AVR_MCU(_speed, _name) \ - AVR_MCU_STRING(AVR_MMCU_TAG_NAME, _name);\ - AVR_MCU_LONG(AVR_MMCU_TAG_FREQUENCY, _speed);\ - const uint8_t _mmcu[2] _MMCU_ = { AVR_MMCU_TAG, 0 } - -/* - * The following MAP macros where copied from - * https://github.com/swansontec/map-macro/blob/master/map.h - * - * The license header for that file is reproduced below: - * - * Copyright (C) 2012 William Swanson - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the names of the authors or - * their institutions shall not be used in advertising or otherwise to - * promote the sale, use or other dealings in this Software without - * prior written authorization from the authors. - */ - -#define _EVAL0(...) __VA_ARGS__ -#define _EVAL1(...) _EVAL0 (_EVAL0 (_EVAL0 (__VA_ARGS__))) -#define _EVAL2(...) _EVAL1 (_EVAL1 (_EVAL1 (__VA_ARGS__))) -#define _EVAL3(...) _EVAL2 (_EVAL2 (_EVAL2 (__VA_ARGS__))) -#define _EVAL4(...) _EVAL3 (_EVAL3 (_EVAL3 (__VA_ARGS__))) -#define _EVAL(...) _EVAL4 (_EVAL4 (_EVAL4 (__VA_ARGS__))) - -#define _MAP_END(...) -#define _MAP_OUT - -#define _MAP_GET_END() 0, _MAP_END -#define _MAP_NEXT0(test, next, ...) next _MAP_OUT -#define _MAP_NEXT1(test, next) _MAP_NEXT0 (test, next, 0) -#define _MAP_NEXT(test, next) _MAP_NEXT1 (_MAP_GET_END test, next) - -#define _MAP0(f, x, peek, ...) f(x) _MAP_NEXT (peek, _MAP1) (f, peek, __VA_ARGS__) -#define _MAP1(f, x, peek, ...) f(x) _MAP_NEXT (peek, _MAP0) (f, peek, __VA_ARGS__) -#define _MAP(f, ...) _EVAL (-MAP1 (f, __VA_ARGS__, (), 0)) - -/* End of original MAP macros. */ - -// Define MAP macros with one additional argument -#define _MAP0_1(f, a, x, peek, ...) f(a, x) _MAP_NEXT (peek, _MAP1_1) (f, a, peek, __VA_ARGS__) -#define _MAP1_1(f, a, x, peek, ...) f(a, x) _MAP_NEXT (peek, _MAP0_1) (f, a, peek, __VA_ARGS__) -#define _MAP_1(f, a, ...) _EVAL (_MAP1_1 (f, a, __VA_ARGS__, (), 0)) - -#define _SEND_SIMAVR_CMD_BYTE(reg, b) reg = b; - -// A helper macro for sending multi-byte commands -#define SEND_SIMAVR_CMD(reg, ...) \ - do { \ - _MAP_1(_SEND_SIMAVR_CMD_BYTE, reg, __VA_ARGS__) \ - } while(0) - -#endif /* __AVR__ */ - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.c deleted file mode 100644 index f3e14e1..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - avr_acomp.c - - Copyright 2017 Konstantin Begun - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "avr_acomp.h" -#include "avr_timer.h" - -static uint8_t -avr_acomp_get_state( - struct avr_t * avr, - avr_acomp_t *ac) -{ - if (avr_regbit_get(avr, ac->disabled)) - return 0; - - // get positive voltage - uint16_t positive_v; - - if (avr_regbit_get(avr, ac->acbg)) { // if bandgap - positive_v = ACOMP_BANDGAP; - } else { - positive_v = ac->ain_values[0]; // AIN0 - } - - // get negative voltage - uint16_t negative_v = 0; - - // multiplexer is enabled if acme is set and adc is off - if (avr_regbit_get(avr, ac->acme) && !avr_regbit_get(avr, ac->aden)) { - if (!avr_regbit_get(avr, ac->pradc)) { - uint8_t adc_i = avr_regbit_get_array(avr, ac->mux, ARRAY_SIZE(ac->mux)); - if (adc_i < ac->mux_inputs && adc_i < ARRAY_SIZE(ac->adc_values)) { - negative_v = ac->adc_values[adc_i]; - } - } - - } else { - negative_v = ac->ain_values[1]; // AIN1 - } - - return positive_v > negative_v; -} - -static avr_cycle_count_t -avr_acomp_sync_state( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_acomp_t * p = (avr_acomp_t *)param; - if (!avr_regbit_get(avr, p->disabled)) { - - uint8_t cur_state = avr_regbit_get(avr, p->aco); - uint8_t new_state = avr_acomp_get_state(avr, p); - - if (new_state != cur_state) { - avr_regbit_setto(avr, p->aco, new_state); // set ACO - - uint8_t acis0 = avr_regbit_get(avr, p->acis[0]); - uint8_t acis1 = avr_regbit_get(avr, p->acis[1]); - - if ((acis0 == 0 && acis1 == 0) || (acis1 == 1 && acis0 == new_state)) { - avr_raise_interrupt(avr, &p->ac); - } - - avr_raise_irq(p->io.irq + ACOMP_IRQ_OUT, new_state); - } - - } - - return 0; -} - -static inline void -avr_schedule_sync_state( - struct avr_t * avr, - void *param) -{ - avr_cycle_timer_register(avr, 1, avr_acomp_sync_state, param); -} - -static void -avr_acomp_write_acsr( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_acomp_t * p = (avr_acomp_t *)param; - - avr_core_watch_write(avr, addr, v); - - if (avr_regbit_get(avr, p->acic) != (p->timer_irq ? 1:0)) { - if (p->timer_irq) { - avr_unconnect_irq(p->io.irq + ACOMP_IRQ_OUT, p->timer_irq); - p->timer_irq = NULL; - } - else { - avr_irq_t *irq = avr_io_getirq(avr, AVR_IOCTL_TIMER_GETIRQ(p->timer_name), TIMER_IRQ_IN_ICP); - if (irq) { - avr_connect_irq(p->io.irq + ACOMP_IRQ_OUT, irq); - p->timer_irq = irq; - } - } - } - - avr_schedule_sync_state(avr, param); -} - -static void -avr_acomp_dependencies_changed( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_acomp_t * p = (avr_acomp_t *)param; - avr_schedule_sync_state(p->io.avr, param); -} - -static void -avr_acomp_irq_notify( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_acomp_t * p = (avr_acomp_t *)param; - - switch (irq->irq) { - case ACOMP_IRQ_AIN0 ... ACOMP_IRQ_AIN1: { - p->ain_values[irq->irq - ACOMP_IRQ_AIN0] = value; - avr_schedule_sync_state(p->io.avr, param); - } break; - case ACOMP_IRQ_ADC0 ... ACOMP_IRQ_ADC15: { - p->adc_values[irq->irq - ACOMP_IRQ_ADC0] = value; - avr_schedule_sync_state(p->io.avr, param); - } break; - } -} - -static void -avr_acomp_register_dependencies( - avr_acomp_t *p, - avr_regbit_t rb) -{ - if (rb.reg) { - avr_irq_register_notify( - avr_iomem_getirq(p->io.avr, rb.reg, NULL, rb.bit), - avr_acomp_dependencies_changed, - p); - } -} - -static void -avr_acomp_reset(avr_io_t * port) -{ - avr_acomp_t * p = (avr_acomp_t *)port; - - for (int i = 0; i < ACOMP_IRQ_COUNT; i++) - avr_irq_register_notify(p->io.irq + i, avr_acomp_irq_notify, p); - - // register notification for changes of registers comparator does not own - // avr_register_io_write is tempting instead, but it requires that the handler - // updates the actual memory too. Given this is for the registers this module - // does not own, it is tricky to know whether it should write to the actual memory. - // E.g., if there is already a native handler for it then it will do the writing - // (possibly even omitting some bits etc). IInterefering would probably be wrong. - // On the other hand if there isn't a handler already, then this hadnler would have to, - // as otherwise nobody will. - // This write notification mechanism should probably need reviewing and fixing - // For now using IRQ mechanism, as it is not intrusive - - avr_acomp_register_dependencies(p, p->pradc); - avr_acomp_register_dependencies(p, p->aden); - avr_acomp_register_dependencies(p, p->acme); - - // mux - for (int i = 0; i < ARRAY_SIZE(p->mux); ++i) { - avr_acomp_register_dependencies(p, p->mux[i]); - } -} - -static const char * irq_names[ACOMP_IRQ_COUNT] = { - [ACOMP_IRQ_AIN0] = "16io = _io; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->ac); - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_COUNT, NULL); - - avr_register_io_write(avr, p->r_acsr, avr_acomp_write_acsr, p); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.h deleted file mode 100644 index caa3c4e..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_acomp.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - avr_acomp.h - - Copyright 2017 Konstantin Begun - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_COMP_H___ -#define __AVR_COMP_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -/* - * simavr Analog Comparator allows external code to feed real voltages to the - * simulator, and the simulator uses it's 'real' reference voltage - * to set comparator output accordingly and trigger in interrupt, if set up this way - * - */ - -enum { - // input IRQ values. Values are /always/ volts * 1000 (millivolts) - ACOMP_IRQ_AIN0 = 0, ACOMP_IRQ_AIN1, - ACOMP_IRQ_ADC0, ACOMP_IRQ_ADC1, ACOMP_IRQ_ADC2, ACOMP_IRQ_ADC3, - ACOMP_IRQ_ADC4, ACOMP_IRQ_ADC5, ACOMP_IRQ_ADC6, ACOMP_IRQ_ADC7, - ACOMP_IRQ_ADC8, ACOMP_IRQ_ADC9, ACOMP_IRQ_ADC10, ACOMP_IRQ_ADC11, - ACOMP_IRQ_ADC12, ACOMP_IRQ_ADC13, ACOMP_IRQ_ADC14, ACOMP_IRQ_ADC15, - ACOMP_IRQ_OUT, // output has changed - ACOMP_IRQ_COUNT -}; - -// Get the internal IRQ corresponding to the INT -#define AVR_IOCTL_ACOMP_GETIRQ AVR_IOCTL_DEF('a','c','m','p') - -enum { - ACOMP_BANDGAP = 1100 -}; - -typedef struct avr_acomp_t { - avr_io_t io; - - uint8_t mux_inputs; // number of inputs (not mux bits!) in multiplexer. Other bits in mux below would be expected to be zero - avr_regbit_t mux[4]; - avr_regbit_t pradc; // ADC power reduction, this impacts on ability to use adc multiplexer - avr_regbit_t aden; // ADC Enabled, this impacts on ability to use adc multiplexer - avr_regbit_t acme; // AC multiplexed input enabled - - avr_io_addr_t r_acsr; // control & status register - avr_regbit_t acis[2]; // - avr_regbit_t acic; // input capture enable - avr_regbit_t aco; // output - avr_regbit_t acbg; // bandgap select - avr_regbit_t disabled; - - char timer_name; // connected timer for incput capture triggering - - // use ACI and ACIE bits - avr_int_vector_t ac; - - // runtime data - uint16_t adc_values[16]; // current values on the ADCs inputs - uint16_t ain_values[2]; // current values on AIN inputs - avr_irq_t* timer_irq; -} avr_acomp_t; - -void avr_acomp_init(avr_t * avr, avr_acomp_t * port); - -#ifdef __cplusplus -}; -#endif - -#endif // __AVR_COMP_H___ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.c deleted file mode 100644 index 6adf1f2..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - avr_adc.c - - Copyright 2008, 2010 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "sim_time.h" -#include "avr_adc.h" - -static avr_cycle_count_t -avr_adc_int_raise( - struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_adc_t * p = (avr_adc_t *)param; - if (avr_regbit_get(avr, p->aden)) { - // if the interrupts are not used, still raised the UDRE and TXC flag - avr_raise_interrupt(avr, &p->adc); - avr_regbit_clear(avr, p->adsc); - if( p->adts_mode == avr_adts_free_running ) - avr_raise_irq(p->io.irq + ADC_IRQ_IN_TRIGGER, 1); - if (!p->read_status) { - /* Update I/O registers. */ - - avr->data[p->r_adcl] = p->result & 0xff; - avr->data[p->r_adch] = p->result >> 8; - } - } - return 0; -} - -static avr_cycle_count_t -avr_adc_convert(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_adc_t *p = (avr_adc_t *)param; - - p->first = 0; // Converter initialised - - /* Ask the calling program for inputs. */ - - avr_adc_mux_t mux = p->muxmode[p->current_muxi]; - union { - avr_adc_mux_t mux; - uint32_t v; - } e = { .mux = mux }; - avr_raise_irq(p->io.irq + ADC_IRQ_OUT_TRIGGER, e.v); - - // optional shift left/right - uint8_t shift = p->current_extras.adjust ? 6 : 0; // shift LEFT - - int32_t reg = 0, clipped = 0; - switch (mux.kind) { - case ADC_MUX_SINGLE: - reg = p->adc_values[mux.src]; - break; - case ADC_MUX_DIFF: - if (mux.gain == 0) - mux.gain = 1; - reg = ((uint32_t)p->adc_values[mux.src] * mux.gain) - - ((uint32_t)p->adc_values[mux.diff] * mux.gain); - break; - case ADC_MUX_TEMP: - reg = p->temp; // assumed to be already calibrated somehow - break; - case ADC_MUX_REF: - reg = mux.src; // reference voltage - break; - case ADC_MUX_VCC4: - if ( !avr->vcc) { - AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n"); - } else - reg = avr->vcc / 4; - break; - } - - int32_t vref = 3300; - uint16_t ref = p->ref_values[p->current_refi]; - - switch (ref) { - case ADC_VREF_VCC: - if (!avr->vcc) - AVR_LOG(avr, LOG_WARNING, "ADC: missing VCC analog voltage\n"); - else - vref = avr->vcc; - break; - case ADC_VREF_AREF: - if (!avr->aref) - AVR_LOG(avr, LOG_WARNING, "ADC: missing AREF analog voltage\n"); - else - vref = avr->aref; - break; - case ADC_VREF_AVCC: - if (!avr->avcc) - AVR_LOG(avr, LOG_WARNING, "ADC: missing AVCC analog voltage\n"); - else - vref = avr->avcc; - break; - default: - vref = ref; - } -// printf("ADCL %d:%3d:%3d read %4d vref %d:%d=%d\n", -// mux.kind, mux.diff, mux.src, -// reg, refi, ref, vref); - - if (mux.kind == ADC_MUX_DIFF) { - if (p->current_extras.negate) - reg = -reg; - if (p->current_extras.bipolar) { - reg = (reg * (int32_t)0x1ff) / vref; // scale to 9 bits - if (reg > (int32_t)0x1ff) { - clipped = 0x1ff; - } else if (reg < -(int32_t)0x1ff) { - clipped = 0x200; - } - } else { - reg = (reg * (int32_t)0x3ff) / vref; // scale to 10 bit - if (reg < 0 || reg > (int32_t)0x3ff) - clipped = 0x1ff; - } - } else { - reg = (reg * (int32_t)0x3ff) / vref; // scale to 10 bits - if (reg < 0 || reg > (int32_t)0x3ff) - clipped = 0x3ff; - } -// printf("ADC to 9/10 bits 0x%x %d\n", reg, reg); - if (clipped) { - AVR_LOG(avr, LOG_WARNING, - "ADC: channel %d clipped %u/%u VREF %d\n", - p->current_muxi, reg, clipped, vref); - reg = clipped; - } - reg &= 0x3ff; - reg <<= shift; -// printf("ADC to 9/10 bits %x shifted %d\n", reg, shift); - p->result = reg; - - /* Schedule the interrupt in 11 ADC cycles. */ - - avr_cycle_timer_register(avr, p->current_prescale * 11, - avr_adc_int_raise, p); - return 0; -} - -/* - * From Datasheet: - * "When ADCL is read, the ADC Data Register is not updated until ADCH is read. - * Consequently, if the result is left adjusted and no more than 8-bit - * precision is required, it is sufficient to read ADCH. - * Otherwise, ADCL must be read first, then ADCH." - */ - -static uint8_t -avr_adc_read_l( - struct avr_t * avr, avr_io_addr_t addr, void * param) -{ - avr_adc_t * p = (avr_adc_t *)param; - - p->read_status = 1; // Set the update interlock. - return avr_core_watch_read(avr, addr); -} - -static uint8_t -avr_adc_read_h( - struct avr_t * avr, avr_io_addr_t addr, void * param) -{ - avr_adc_t * p = (avr_adc_t *)param; - - p->read_status = 0; // Clear the update interlock. - return avr_core_watch_read(avr, addr); -} - -static void -avr_adc_configure_trigger( - struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_adc_t * p = (avr_adc_t *)param; - - uint8_t adate = avr_regbit_get(avr, p->adate); - uint8_t old_adts = p->adts_mode; - - static char * auto_trigger_names[] = { - "none", - "free_running", - "analog_comparator_0", - "analog_comparator_1", - "analog_comparator_2", - "analog_comparator_3", - "external_interrupt_0", - "timer_0_compare_match_a", - "timer_0_compare_match_b", - "timer_0_overflow", - "timer_1_compare_match_b", - "timer_1_overflow", - "timer_1_capture_event", - "pin_change_interrupt", - "psc_module_0_sync_signal", - "psc_module_1_sync_signal", - "psc_module_2_sync_signal", - }; - - if( adate ) { - uint8_t adts = avr_regbit_get_array(avr, p->adts, ARRAY_SIZE(p->adts)); - p->adts_mode = p->adts_op[adts]; - - switch(p->adts_mode) { - case avr_adts_free_running: { - // do nothing at free running mode - } break; - // TODO: implement the other auto trigger modes - default: { - AVR_LOG(avr, LOG_WARNING, - "ADC: unimplemented auto trigger mode: %s\n", - auto_trigger_names[p->adts_mode]); - p->adts_mode = avr_adts_none; - } break; - } - } else { - // TODO: remove previously configured auto triggers - p->adts_mode = avr_adts_none; - } - - if( old_adts != p->adts_mode ) - AVR_LOG(avr, LOG_TRACE, "ADC: auto trigger configured: %s\n", - auto_trigger_names[p->adts_mode]); -} - -static void -avr_adc_write_adcsra( - struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - - avr_adc_t * p = (avr_adc_t *)param; - uint8_t adsc = avr_regbit_get(avr, p->adsc); - uint8_t aden = avr_regbit_get(avr, p->aden); - uint8_t new_aden; - - if (p->adc.raised.reg == addr) { - uint8_t mask; - - mask = 1 << p->adc.raised.bit; - if (mask & v) { - // Clear interrupt flag on bit set. - - avr_clear_interrupt(avr, &p->adc); - v &= ~mask; - } else { - v |= (mask & avr->data[p->adsc.reg]); - } - } - - avr->data[p->adsc.reg] = v; - new_aden = avr_regbit_get(avr, p->aden); - - // can't write zero to adsc - if (adsc && !avr_regbit_get(avr, p->adsc)) { - avr_regbit_set(avr, p->adsc); - v = avr->data[p->adsc.reg]; - } - if (!aden && new_aden) { - // first conversion - p->first = 1; - AVR_LOG(avr, LOG_TRACE, "ADC: Start AREF %d AVCC %d\n", avr->aref, avr->avcc); - } - if (aden && !avr_regbit_get(avr, p->aden)) { - // stop ADC - - avr_cycle_timer_cancel(avr, avr_adc_convert, p); - avr_cycle_timer_cancel(avr, avr_adc_int_raise, p); - avr_regbit_clear(avr, p->adsc); - v = avr->data[p->adsc.reg]; // Peter Ross pross@xvid.org - } - if (new_aden && !adsc && avr_regbit_get(avr, p->adsc)) { - // start one! - - /* Copy mux, prescaler and ADSRB settings, as they may change - * before conversion. - */ - - p->current_muxi = avr_regbit_get_array(avr, p->mux, - ARRAY_SIZE(p->mux)); - p->current_refi = avr_regbit_get_array(avr, p->ref, - ARRAY_SIZE(p->ref)); - - // clock prescaler are just a bit shift.. and 0 means 1 - - uint32_t div = avr_regbit_get_array(avr, p->adps, - ARRAY_SIZE(p->adps)); - if (!div) div++; - - if (p->first) - AVR_LOG(avr, LOG_TRACE, "ADC: starting at %uKHz\n", - (avr->frequency >> div) / 13 / 100); - div = (1 << div); - div *= (p->first ? 14 : 2); // first conversion is longer - p->current_prescale = div; - avr_cycle_timer_register(avr, div, avr_adc_convert, p); - p->current_extras.bipolar = - p->bin.reg && avr_regbit_get(avr, p->bin); - p->current_extras.negate = - p->ipr.reg && avr_regbit_get(avr, p->ipr); - p->current_extras.adjust = avr_regbit_get(avr, p->adlar); - } - avr_core_watch_write(avr, addr, v); - avr_adc_configure_trigger(avr, addr, v, param); -} - -static void -avr_adc_write_adcsrb( - struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_core_watch_write(avr, addr, v); - avr_adc_configure_trigger(avr, addr, v, param); -} - -static void -avr_adc_irq_notify( - struct avr_irq_t * irq, uint32_t value, void * param) -{ - avr_adc_t * p = (avr_adc_t *)param; - avr_t * avr = p->io.avr; - - switch (irq->irq) { - case ADC_IRQ_ADC0 ... ADC_IRQ_ADC15: { - p->adc_values[irq->irq] = value; - } break; - case ADC_IRQ_TEMP: { - p->temp = value; - } break; - case ADC_IRQ_IN_TRIGGER: { - if (avr_regbit_get(avr, p->adate)) { - // start a conversion only if it's not running - // otherwise ignore the trigger - if(!avr_regbit_get(avr, p->adsc) ) { - uint8_t addr = p->adsc.reg; - if (addr) { - uint8_t val = avr->data[addr] | (1 << p->adsc.bit); - if (p->adc.raised.reg == addr) { - uint8_t mask; - - mask = 1 << p->adc.raised.bit; - val &= ~mask; - } - - // write ADSC to ADCSRA - - avr_adc_write_adcsra(avr, addr, val, param); - } - } - } - } - break; - } -} - -static void avr_adc_reset(avr_io_t * port) -{ - avr_adc_t * p = (avr_adc_t *)port; - - // stop ADC - avr_cycle_timer_cancel(p->io.avr, avr_adc_int_raise, p); - avr_regbit_clear(p->io.avr, p->adsc); - - for (int i = 0; i < ADC_IRQ_COUNT; i++) - avr_irq_register_notify(p->io.irq + i, avr_adc_irq_notify, p); -} - -static const char * irq_names[ADC_IRQ_COUNT] = { - [ADC_IRQ_ADC0] = "16io = _io; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->adc); - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_ADC_GETIRQ, ADC_IRQ_COUNT, NULL); - - avr_register_io_write(avr, p->r_adcsra, avr_adc_write_adcsra, p); - // some ADCs don't have ADCSRB (atmega8/16/32) - if (p->r_adcsrb) - avr_register_io_write(avr, p->r_adcsrb, avr_adc_write_adcsrb, p); - avr_register_io_read(avr, p->r_adcl, avr_adc_read_l, p); - avr_register_io_read(avr, p->r_adch, avr_adc_read_h, p); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.h deleted file mode 100644 index c9dbfa0..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_adc.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - avr_adc.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_ADC_H___ -#define __AVR_ADC_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -/* - * simavr ADC allows external code to feed real voltages to the - * simulator, and the simulator uses it's 'real' reference voltage - * to do the right thing and return the 'proper' 10 bits ADC value - * to the AVR firmware. - * - * To send values to the ADC, register your code to wait for the - * ADC_IRQ_OUT_TRIGGER irq, and at that point send any of the - * ADC_IRQ_ADC* with Millivolts as value. - * - * External trigger is not done yet. - */ - -enum { - // input IRQ values. Values are /always/ volts * 1000 (millivolts) - ADC_IRQ_ADC0 = 0, ADC_IRQ_ADC1, ADC_IRQ_ADC2, ADC_IRQ_ADC3, - ADC_IRQ_ADC4, ADC_IRQ_ADC5, ADC_IRQ_ADC6, ADC_IRQ_ADC7, - ADC_IRQ_ADC8, ADC_IRQ_ADC9, ADC_IRQ_ADC10, ADC_IRQ_ADC11, - ADC_IRQ_ADC12, ADC_IRQ_ADC13, ADC_IRQ_ADC14, ADC_IRQ_ADC15, - ADC_IRQ_TEMP, // see the datasheet - ADC_IRQ_IN_TRIGGER, - ADC_IRQ_OUT_TRIGGER, // sends a avr_adc_mux_t - ADC_IRQ_COUNT -}; - -// Get the internal IRQ corresponding to the INT -#define AVR_IOCTL_ADC_GETIRQ AVR_IOCTL_DEF('a','d','c','0') - -/* - * Definition of a ADC mux mode. - */ -enum { - ADC_MUX_NONE = 0, // Nothing. return 0 - ADC_MUX_NOISE, // Nothing. return something random - ADC_MUX_SINGLE, // Normal ADC pin reading - ADC_MUX_DIFF, // differential channels (src-diff) - ADC_MUX_TEMP, // internal temp sensor - ADC_MUX_REF, // reference voltage (in src * 100) - ADC_MUX_VCC4, // VCC/4 -}; -typedef struct avr_adc_mux_t { - unsigned long kind : 3, gain : 8, diff : 8, src : 13; -} avr_adc_mux_t; - -enum { - ADC_VREF_AREF = 0, // default mode - ADC_VREF_VCC, - ADC_VREF_AVCC, - ADC_VREF_V110 = 1100, - ADC_VREF_V256 = 2560, -}; - -// ADC trigger sources -typedef enum { - avr_adts_none = 0, - avr_adts_free_running, - avr_adts_analog_comparator_0, - avr_adts_analog_comparator_1, - avr_adts_analog_comparator_2, - avr_adts_analog_comparator_3, - avr_adts_external_interrupt_0, - avr_adts_timer_0_compare_match_a, - avr_adts_timer_0_compare_match_b, - avr_adts_timer_0_overflow, - avr_adts_timer_1_compare_match_b, - avr_adts_timer_1_overflow, - avr_adts_timer_1_capture_event, - avr_adts_pin_change_interrupt, - avr_adts_psc_module_0_sync_signal, - avr_adts_psc_module_1_sync_signal, - avr_adts_psc_module_2_sync_signal, -} avr_adts_type; - -typedef struct avr_adc_t { - avr_io_t io; - - uint8_t r_admux; - // if the last bit exists in the mux, we are an extended ADC - avr_regbit_t mux[6]; - avr_regbit_t ref[3]; // reference voltages bits - uint16_t ref_values[8]; // ADC_VREF_* - - avr_regbit_t adlar; // left/right adjustment bit - - uint8_t r_adcsra; // ADC Control and Status Register A - avr_regbit_t aden; // ADC Enabled - avr_regbit_t adsc; // ADC Start Conversion - avr_regbit_t adate; // ADC Auto Trigger Enable - - avr_regbit_t adps[3]; // Prescaler bits. Note that it's a frequency bit shift - - uint8_t r_adcl, r_adch; // Data Registers - - uint8_t r_adcsrb; // ADC Control and Status Register B - avr_regbit_t adts[4]; // Timing Source - avr_adts_type adts_op[16]; // ADTS type - uint8_t adts_mode; // the extracted ADTS mode - avr_regbit_t bin; // Bipolar Input Mode (tinyx5 have it) - avr_regbit_t ipr; // Input Polarity Reversal (tinyx5 have it) - - // use ADIF and ADIE bits - avr_int_vector_t adc; - - avr_adc_mux_t muxmode[64]; // maximum 6 bits of mux modes - - /* - * runtime bits - */ - - uint16_t adc_values[16]; // current values on the ADCs - uint16_t temp; // temp sensor reading - uint8_t first; - uint8_t read_status; // marked one when adcl is read - - /* Conversion parameters saved at start (ADSC is set). */ - - uint8_t current_muxi; - uint8_t current_refi; - uint8_t current_prescale; - struct { - unsigned int bipolar : 1; // BIN bit. - unsigned int negate : 1; // IPR bit. - unsigned int adjust : 1; // ADLAR bit. - } current_extras; - - /* Buffered conversion result. */ - - uint16_t result; -} avr_adc_t; - -void avr_adc_init(avr_t * avr, avr_adc_t * port); - - -/* - * Helper macros for the Cores definition of muxes - */ -#define AVR_ADC_SINGLE(_chan) { \ - .kind = ADC_MUX_SINGLE, \ - .src = (_chan), \ - } -#define AVR_ADC_DIFF(_a,_b,_g) { \ - .kind = ADC_MUX_DIFF, \ - .src = (_a), \ - .diff = (_b), \ - .gain = (_g), \ - } -#define AVR_ADC_REF(_t) { \ - .kind = ADC_MUX_REF, \ - .src = (_t), \ - } -#define AVR_ADC_TEMP() { \ - .kind = ADC_MUX_TEMP, \ - } - -#define AVR_ADC_VCC4() { \ - .kind = ADC_MUX_VCC4, \ - } - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_ADC_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.c deleted file mode 100644 index e34aab2..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - avr_bitbang.c - - Copyright 2008, 2009 Michel Pollet - 2011 Stephan Veigl - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_BITBANG_H__ -#define __AVR_BITBANG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "avr_bitbang.h" - -#include "sim_regbit.h" -#include "sim_core.h" -#include "avr_ioport.h" - -///@todo refactor SPI to bitbang - -#define BITBANG_MASK 0xFFFFFFFFUL - -/** - * read (sample) data from input pin - * - * @param p internal bitbang structure - */ -static void avr_bitbang_read_bit(avr_bitbang_t *p) -{ - avr_ioport_state_t iostate; - uint8_t bit = 0; - - if ( !p->enabled ) - return; - - // read from HW pin - if ( p->p_in.port ) { - avr_ioctl(p->avr, AVR_IOCTL_IOPORT_GETSTATE( p->p_in.port ), &iostate); - bit = ( iostate.pin >> p->p_in.pin ) & 1; - - if ( p->data_order ) { - // data order: shift right - p->data = (p->data >> 1) | ( bit << (p->buffer_size-1)); - } else { - // data order: shift left - p->data = (p->data << 1) | bit; - } - - } - - // module callback - if ( p->callback_bit_read ) { - p->callback_bit_read(bit, p->callback_param); - } - - // data sanitary - p->data = p->data & ~(BITBANG_MASK << p->buffer_size); -} - -/** - * write data to output pin - * - * @param p bitbang structure - */ -static void avr_bitbang_write_bit(avr_bitbang_t *p) -{ - uint8_t bit = 0; - - if ( !p->enabled ) - return; - - if ( p->data_order ) { - // data order: shift right - bit = p->data & 1; - } else { - // data order: shift left - bit = (p->data >> (p->buffer_size-1)) & 1; - } - - // output to HW pin - if ( p->p_out.port ) { - avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin), bit); - } - - // module callback - if ( p->callback_bit_write ) { - p->callback_bit_write(bit, p->callback_param); - } -} - - -/** - * process clock edges (both: positive and negative edges) - * - * @param p bitbang structure - * - */ -static void avr_bitbang_clk_edge(avr_bitbang_t *p) -{ - uint8_t phase = (p->clk_count & 1) ^ p->clk_phase; - uint8_t clk = (p->clk_count & 1) ^ p->clk_pol; - - if ( !p->enabled ) - return; - - // increase clock - p->clk_count++; - clk ^= 1; - phase ^= 1; - - // generate clock output on HW pin - if ( p->clk_generate && p->p_clk.port ) { - avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), clk); - } - - if ( phase ) { - // read data in - avr_bitbang_read_bit(p); - - } else { - // write data out - avr_bitbang_write_bit(p); - } - - if ( p->clk_count >= (p->buffer_size*2) ) { - // transfer finished - if ( p->callback_transfer_finished ) { - p->data = p->callback_transfer_finished(p->data, p->callback_param); - } - p->clk_count = 0; - } -} - -static avr_cycle_count_t avr_bitbang_clk_timer(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_bitbang_t * p = (avr_bitbang_t *)param; - - avr_bitbang_clk_edge(p); - - if ( p->enabled ) - return when + p->clk_cycles/2; - else - return 0; -} - -static void avr_bitbang_clk_hook(struct avr_irq_t * irq, uint32_t value, void * param) -{ - avr_bitbang_t * p = (avr_bitbang_t *)param; - uint8_t clk = (p->clk_count & 1) ^ p->clk_pol; - - // no clock change - if ( clk == value ) - return; - - avr_bitbang_clk_edge(p); -} - -/** - * reset bitbang sub-module - * - * @param avr avr attached to - * @param p bitbang structure - */ -void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p) -{ - p->avr = avr; - p->enabled = 0; - p->clk_count = 0; - p->data = 0; - - if ( p->buffer_size < 1 || p->buffer_size > 32 ) { - AVR_LOG(avr, LOG_ERROR, - "Error: bitbang buffer size should be between 1 and 32. set value: %d\n", p->buffer_size); - abort(); - } - -} - -/** - * start bitbang transfer - * - * buffers should be written / cleared in advanced - * timers and interrupts are connected - * - * @param p bitbang structure - */ -void avr_bitbang_start(avr_bitbang_t * p) -{ - p->enabled = 1; - p->clk_count = 0; - - if ( p->clk_phase == 0 ) { - // write first bit - avr_bitbang_write_bit(p); - } - - if ( p->clk_generate ) { - // master mode, generate clock -> set timer - avr_cycle_timer_register(p->avr, (p->clk_cycles/2), avr_bitbang_clk_timer, p); - } else { - // slave mode -> attach clock function to clock pin - ///@todo test - avr_irq_register_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p); - } - -} - - -/** - * stop bitbang transfer - * - * timers and interrupts are disabled - * - * @param p bitbang structure - */ -void avr_bitbang_stop(avr_bitbang_t * p) -{ - - p->enabled = 0; - avr_cycle_timer_cancel(p->avr, avr_bitbang_clk_timer, p); - avr_irq_unregister_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p); -} - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_BITBANG_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.h deleted file mode 100644 index 3d8832f..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_bitbang.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - avr_bitbang.h - - Copyright 2008, 2009 Michel Pollet - 2011 Stephan Veigl - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -/** - @defgroup avr_bitbang Generic BitBang Module - @{ - - Generic BitBang Module of simavr AVR simulator. - - @par Features / Implementation Status - - easy buffer access with push() / pop() functions - - one input and one output pin (can be the same HW pin for I2C) - - @todo - - one input and one output pin (can be the same HW pin for I2C) - - one clock pin which can be configured as input or output - when the clock is output, the clock signal is generated with a - configured frequency (master / slave mode) - - 2x 32-bit buffers (input / output) (allows start, stop bits for UART, etc.) - - on each read / write a callback is executed to notify the master module - -*/ - - -#ifndef AVR_BITBANG_H_ -#define AVR_BITBANG_H_ - -#include "sim_avr.h" -#include "avr_ioport.h" - - - - -/// SPI Module initialization and state structure -typedef struct avr_bitbang_t { - avr_t * avr; ///< avr we are attached to - - uint8_t enabled; ///< bit-bang enabled flag - uint8_t clk_generate; ///< generate clock and write to clock pin (if available) -> master / slave mode - uint8_t clk_pol; ///< clock polarity, base (inactive) value of clock - uint8_t clk_phase; ///< clock phase / data sampling edge - /// - 0: data are sampled at first clock edge - /// - 1: data are sampled at second clock edge - uint32_t clk_cycles; ///< cycles per clock period - must be multiple of 2! (used if clk_generate is enabled) - uint8_t data_order; ///< data order / shift - /// - 0: shift left - /// - 1: shift right - - uint8_t buffer_size; ///< size of buffer in bits (1...32) - - void *callback_param; /// anonymous parameter for callback functions - void (*callback_bit_read)(uint8_t bit, void *param); ///< callback function to notify about bit read - void (*callback_bit_write)(uint8_t bit, void *param); ///< callback function to notify about bit write - uint32_t (*callback_transfer_finished)(uint32_t data, void *param); ///< callback function to notify about a complete transfer - /// (read received data and write new output data) - - avr_iopin_t p_clk; ///< clock pin (optional) - avr_iopin_t p_in; ///< data in pin - avr_iopin_t p_out; ///< data out pin - -// private data - uint32_t data; ///< data buffer - /// - latest received bit the is lowest / most right one, bit number: 0 - /// - next bit to be written is the highest one, bit number: (buffer_size-1) - int8_t clk_count; ///< internal clock edge count -} avr_bitbang_t; - -/** - * reset bitbang sub-module - * - * @param avr avr attached to - * @param p bitbang structure - */ -void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p); - -/** - * start bitbang transfer - * - * buffers should be written / cleared in advanced - * timers and interrupts are connected - * - * @param p bitbang structure - */ -void avr_bitbang_start(avr_bitbang_t * p); - - -/** - * stop bitbang transfer - * - * timers and interrupts are disabled - * - * @param p bitbang structure - */ -void avr_bitbang_stop(avr_bitbang_t * p); - - -#endif /* AVR_BITBANG_H_ */ -/// @} end of avr_bitbang group diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.c deleted file mode 100644 index c348f3f..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - avr_eeprom.c - - IO module that simulates the AVR EEProm - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "avr_eeprom.h" - -static avr_cycle_count_t avr_eempe_clear(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_eeprom_t * p = (avr_eeprom_t *)param; - avr_regbit_clear(p->io.avr, p->eempe); - return 0; -} - -static avr_cycle_count_t avr_eei_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_eeprom_t * p = (avr_eeprom_t *)param; - avr_raise_interrupt(p->io.avr, &p->ready); - return 0; -} - -static void avr_eeprom_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_eeprom_t * p = (avr_eeprom_t *)param; - uint8_t eempe = avr_regbit_get(avr, p->eempe); - - avr_core_watch_write(avr, addr, v); - - if (!eempe && avr_regbit_get(avr, p->eempe)) { - avr_cycle_timer_register(avr, 4, avr_eempe_clear, p); - } - - uint16_t ee_addr; - if (p->r_eearh) - ee_addr = avr->data[p->r_eearl] | (avr->data[p->r_eearh] << 8); - else - ee_addr = avr->data[p->r_eearl]; - if (((eempe && avr_regbit_get(avr, p->eepe)) || avr_regbit_get(avr, p->eere)) && - ee_addr >= p->size) { - AVR_LOG(avr, LOG_ERROR, "EEPROM: *** %s address out of bounds: %04x > %04x," - " wrapping to %04x (PC=%04x)\n", - eempe ? "Write" : "Read", - ee_addr, p->size-1, ee_addr & (p->size-1), - avr->pc); - ee_addr = ee_addr & (p->size-1); - } - if (eempe && avr_regbit_get(avr, p->eepe)) { // write operation - // printf("eeprom write %04x <- %02x\n", addr, avr->data[p->r_eedr]); - p->eeprom[ee_addr] = avr->data[p->r_eedr]; - // Automatically clears that bit (?) - avr_regbit_clear(avr, p->eempe); - - avr_cycle_timer_register_usec(avr, 3400, avr_eei_raise, p); // 3.4ms here - } - if (avr_regbit_get(avr, p->eere)) { // read operation - avr->data[p->r_eedr] = p->eeprom[ee_addr]; - // printf("eeprom read %04x : %02x\n", addr, p->eeprom[addr]); - } - - // autocleared - avr_regbit_clear(avr, p->eepe); - avr_regbit_clear(avr, p->eere); -} - -static int avr_eeprom_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param) -{ - avr_eeprom_t * p = (avr_eeprom_t *)port; - int res = -1; - - switch(ctl) { - case AVR_IOCTL_EEPROM_SET: { - avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param; - if (!desc || !desc->size || !desc->ee || (desc->offset + desc->size) > p->size) { - AVR_LOG(port->avr, LOG_WARNING, "EEPROM: %s: AVR_IOCTL_EEPROM_SET Invalid argument\n", - __FUNCTION__); - return -2; - } - memcpy(p->eeprom + desc->offset, desc->ee, desc->size); - AVR_LOG(port->avr, LOG_TRACE, "EEPROM: %s: AVR_IOCTL_EEPROM_SET Loaded %d at offset %d\n", - __FUNCTION__, desc->size, desc->offset); - } break; - case AVR_IOCTL_EEPROM_GET: { - avr_eeprom_desc_t * desc = (avr_eeprom_desc_t*)io_param; - if (!desc || (desc->offset + desc->size) > p->size) { - AVR_LOG(port->avr, LOG_WARNING, "EEPROM: %s: AVR_IOCTL_EEPROM_GET Invalid argument\n", - __FUNCTION__); - return -2; - } - if (desc->ee) - memcpy(desc->ee, p->eeprom + desc->offset, desc->size); - else // allow to get access to the read data, for gdb support - desc->ee = p->eeprom + desc->offset; - } break; - } - - return res; -} - -static void avr_eeprom_dealloc(struct avr_io_t * port) -{ - avr_eeprom_t * p = (avr_eeprom_t *)port; - if (p->eeprom) - free(p->eeprom); - p->eeprom = NULL; -} - -static avr_io_t _io = { - .kind = "eeprom", - .ioctl = avr_eeprom_ioctl, - .dealloc = avr_eeprom_dealloc, -}; - -void avr_eeprom_init(avr_t * avr, avr_eeprom_t * p) -{ - p->io = _io; -// printf("%s init (%d bytes) EEL/H:%02x/%02x EED=%02x EEC=%02x\n", -// __FUNCTION__, p->size, p->r_eearl, p->r_eearh, p->r_eedr, p->r_eecr); - - p->eeprom = malloc(p->size); - memset(p->eeprom, 0xff, p->size); - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->ready); - - avr_register_io_write(avr, p->r_eecr, avr_eeprom_write, p); -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.h deleted file mode 100644 index 9ad1c5a..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_eeprom.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - avr_eeprom.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_EEPROM_H__ -#define __AVR_EEPROM_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -typedef struct avr_eeprom_t { - avr_io_t io; - - uint8_t * eeprom; // actual bytes - uint16_t size; // size for this MCU - - uint8_t r_eearh; - uint8_t r_eearl; - uint8_t r_eedr; - - // eepm -- eeprom write mode - uint8_t r_eecr; // shortcut, assumes these bits fit in that register - avr_regbit_t eepm[4]; - avr_regbit_t eempe; // eeprom master program enable - avr_regbit_t eepe; // eeprom program enable - avr_regbit_t eere; // eeprom read enable - - avr_int_vector_t ready; // EERIE vector -} avr_eeprom_t; - -void avr_eeprom_init(avr_t * avr, avr_eeprom_t * port); - -typedef struct avr_eeprom_desc_t { - uint8_t * ee; - uint16_t offset; - uint32_t size; -} avr_eeprom_desc_t; - -#define AVR_IOCTL_EEPROM_GET AVR_IOCTL_DEF('e','e','g','p') -#define AVR_IOCTL_EEPROM_SET AVR_IOCTL_DEF('e','e','s','p') - - -/* - * the eeprom block seems to be very similar across AVRs, - * so here is a macro to declare a "typical" one in a core. - */ - -#define AVR_EEPROM_DECLARE(_vector) \ - .eeprom = {\ - .size = E2END+1,\ - .r_eearh = EEARH,\ - .r_eearl = EEARL,\ - .r_eedr = EEDR,\ - .r_eecr = EECR,\ - .eepm = { AVR_IO_REGBIT(EECR, EEPM0), AVR_IO_REGBIT(EECR, EEPM1) },\ - .eempe = AVR_IO_REGBIT(EECR, EEMPE),\ - .eepe = AVR_IO_REGBIT(EECR, EEPE),\ - .eere = AVR_IO_REGBIT(EECR, EERE),\ - .ready = {\ - .enable = AVR_IO_REGBIT(EECR, EERIE),\ - .vector = _vector,\ - },\ - } - -/* - * no EEPM registers in atmega128 - */ -#define AVR_EEPROM_DECLARE_NOEEPM(_vector) \ - .eeprom = {\ - .size = E2END+1,\ - .r_eearh = EEARH,\ - .r_eearl = EEARL,\ - .r_eedr = EEDR,\ - .r_eecr = EECR,\ - .eepm = { }, \ - .eempe = AVR_IO_REGBIT(EECR, EEMWE),\ - .eepe = AVR_IO_REGBIT(EECR, EEWE),\ - .eere = AVR_IO_REGBIT(EECR, EERE),\ - .ready = {\ - .enable = AVR_IO_REGBIT(EECR, EERIE),\ - .vector = _vector,\ - },\ - } - - -/* - * macro definition without a high address bit register, - * which is not implemented in some tiny AVRs. - */ - -#define AVR_EEPROM_DECLARE_8BIT(_vector) \ - .eeprom = {\ - .size = E2END+1,\ - .r_eearl = EEAR,\ - .r_eedr = EEDR,\ - .r_eecr = EECR,\ - .eepm = { AVR_IO_REGBIT(EECR, EEPM0), AVR_IO_REGBIT(EECR, EEPM1) },\ - .eempe = AVR_IO_REGBIT(EECR, EEMPE),\ - .eepe = AVR_IO_REGBIT(EECR, EEPE),\ - .eere = AVR_IO_REGBIT(EECR, EERE),\ - .ready = {\ - .enable = AVR_IO_REGBIT(EECR, EERIE),\ - .vector = _vector,\ - },\ - } - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_EEPROM_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.c deleted file mode 100644 index 6f85660..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - avr_extint.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include -#include -#include -#include "avr_extint.h" -#include "avr_ioport.h" - -typedef struct avr_extint_poll_context_t { - uint32_t eint_no; // index of particular interrupt source we are monitoring - avr_extint_t *extint; -} avr_extint_poll_context_t; - -static avr_cycle_count_t avr_extint_poll_level_trig( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_extint_poll_context_t *poll = (avr_extint_poll_context_t *)param; - avr_extint_t * p = poll->extint; - - /* Check for change of interrupt mode. */ - - if (avr_regbit_get_array(avr, p->eint[poll->eint_no].isc, 2)) - goto terminate_poll; - - uint8_t port = p->eint[poll->eint_no].port_ioctl & 0xFF; - avr_ioport_state_t iostate; - if (avr_ioctl(avr, AVR_IOCTL_IOPORT_GETSTATE( port ), &iostate) < 0) - goto terminate_poll; - uint8_t bit = ( iostate.pin >> p->eint[poll->eint_no].port_pin ) & 1; - if (bit) - goto terminate_poll; // Only poll while pin level remains low - - if (avr->sreg[S_I]) { - uint8_t raised = avr_regbit_get(avr, p->eint[poll->eint_no].vector.raised) || p->eint[poll->eint_no].vector.pending; - if (!raised) - avr_raise_interrupt(avr, &p->eint[poll->eint_no].vector); - } - - return when+1; - -terminate_poll: - free(poll); - return 0; -} - -static avr_extint_t * avr_extint_get(avr_t * avr) -{ - if (!avr) - return NULL; - avr_io_t * periferal = avr->io_port; - while (periferal) { - if (!strcmp(periferal->kind, "extint")) { - return (avr_extint_t *)periferal; - } - periferal = periferal->next; - } - return NULL; -} - -static inline uint8_t avr_extint_exists(avr_extint_t *extint, int8_t extint_no) -{ - return (extint_no < EXTINT_COUNT) && (extint->eint[extint_no].port_ioctl); -} - -/** - * @brief avr_extint_is_strict_lvl_trig - * @param avr - * @param extint_no: an ext interrupt number, e.g. 0 or 1 (corresponds to INT0 or INT1) - * @return -1 if irrelevant extint_no given, strict - * level triggering flag otherwise. - */ -int avr_extint_is_strict_lvl_trig(avr_t * avr, uint8_t extint_no) -{ - avr_extint_t *p = avr_extint_get(avr); - if (!p || !avr_extint_exists(p, extint_no)) - return -1; - if (!p->eint[extint_no].isc[1].reg) - return -1; // this is edge-only triggered interrupt - return p->eint[extint_no].strict_lvl_trig; -} - -/** - * @brief avr_extint_set_strict_lvl_trig - * @param avr - * @param extint_no: an ext interrupt number, e.g. 0 or 1 (corresponds to INT0 or INT1) - * @param strict: new value for level triggering flag - */ -void avr_extint_set_strict_lvl_trig(avr_t * avr, uint8_t extint_no, uint8_t strict) -{ - avr_extint_t *p = avr_extint_get(avr); - if (!p || !avr_extint_exists(p, extint_no)) - return; - if (!p->eint[extint_no].isc[1].reg) - return; // this is edge-only triggered interrupt - p->eint[extint_no].strict_lvl_trig = strict; -} - -static void avr_extint_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param) -{ - avr_extint_t * p = (avr_extint_t *)param; - avr_t * avr = p->io.avr; - - int up = !irq->value && value; - int down = irq->value && !value; - - // ?? uint8_t isc_bits = p->eint[irq->irq + 1].isc->reg ? 2 : 1; - uint8_t isc_bits = p->eint[irq->irq].isc[1].reg ? 2 : 1; - uint8_t mode = avr_regbit_get_array(avr, p->eint[irq->irq].isc, isc_bits); - - // Asynchronous interrupts, eg int2 in m16, m32 etc. support only down/up - if (isc_bits == 1) - mode +=2; - - switch (mode) { - case 0: // Level triggered (low level) interrupt - { - /** - Datasheet excerpt: - >When the external interrupt is enabled and is configured as level triggered (only INT0/INT1), - >the interrupt will trigger as long as the pin is held low. - Thus we have to query the pin value continiously while it's held low and try to trigger the interrupt. - This can be expensive, so avr_extint_set_strict_lvl_trig function provisioned to allow the user - to turn this feature off. In this case bahaviour will be similar to the falling edge interrupt. - */ - if (!value) { - if (avr->sreg[S_I]) { - uint8_t raised = avr_regbit_get(avr, p->eint[irq->irq].vector.raised) || p->eint[irq->irq].vector.pending; - if (!raised) - avr_raise_interrupt(avr, &p->eint[irq->irq].vector); - } - if (p->eint[irq->irq].strict_lvl_trig) { - avr_extint_poll_context_t *poll = malloc(sizeof(avr_extint_poll_context_t)); - if (poll) { - poll->eint_no = irq->irq; - poll->extint = p; - avr_cycle_timer_register(avr, 1, avr_extint_poll_level_trig, poll); - } - } - } - } - break; - case 1: // Toggle-triggered interrupt - if (up || down) - avr_raise_interrupt(avr, &p->eint[irq->irq].vector); - break; - case 2: // Falling edge triggered - if (down) - avr_raise_interrupt(avr, &p->eint[irq->irq].vector); - break; - case 3: // Rising edge trigggerd - if (up) - avr_raise_interrupt(avr, &p->eint[irq->irq].vector); - break; - } -} - -static void avr_extint_reset(avr_io_t * port) -{ - avr_extint_t * p = (avr_extint_t *)port; - - for (int i = 0; i < EXTINT_COUNT; i++) { - if (p->eint[i].port_ioctl) { - avr_irq_register_notify(p->io.irq + i, avr_extint_irq_notify, p); - - if (p->eint[i].isc[1].reg) // level triggering available - p->eint[i].strict_lvl_trig = 1; // turn on repetitive level triggering by default - avr_irq_t * irq = avr_io_getirq(p->io.avr, - p->eint[i].port_ioctl, p->eint[i].port_pin); - - avr_connect_irq(irq, p->io.irq + i); - } - } -} - -static const char * irq_names[EXTINT_COUNT] = { - [EXTINT_IRQ_OUT_INT0] = "io = _io; - - avr_register_io(avr, &p->io); - for (int i = 0; i < EXTINT_COUNT; i++) { - if (!p->eint[i].port_ioctl) - break; - avr_register_vector(avr, &p->eint[i].vector); - } - // allocate this module's IRQ - - avr_io_setirqs(&p->io, AVR_IOCTL_EXTINT_GETIRQ(), EXTINT_COUNT, NULL); -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.h deleted file mode 100644 index 62aa154..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_extint.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - avr_extint.h - - External Interrupt Handling (for INT0-3) - - Copyright 2008, 2009 Michel Pollet - Copyright 2014 Doug Szumski - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_EXTINT_H__ -#define __AVR_EXTINT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - - -enum { - EXTINT_IRQ_OUT_INT0 = 0, - EXTINT_IRQ_OUT_INT1, EXTINT_IRQ_OUT_INT2, EXTINT_IRQ_OUT_INT3, - EXTINT_IRQ_OUT_INT4, EXTINT_IRQ_OUT_INT5, EXTINT_IRQ_OUT_INT6, - EXTINT_IRQ_OUT_INT7, - EXTINT_COUNT -}; - -// Get the internal IRQ corresponding to the INT -#define AVR_IOCTL_EXTINT_GETIRQ() AVR_IOCTL_DEF('i','n','t',' ') - -/* - * This module is just a "relay" for the pin change IRQ in the IO port - * module. We hook up to their IRQ and raise out interrupt vectors as needed - * - * "isc" is handled, apart from the "level" mode that doesn't make sense here (?) - */ -typedef struct avr_extint_t { - avr_io_t io; - - struct { - avr_regbit_t isc[2]; // interrupt sense control bits - avr_int_vector_t vector; // interrupt vector - - uint32_t port_ioctl; // ioctl to use to get port - uint8_t port_pin; // pin number in said port - uint8_t strict_lvl_trig;// enforces a repetitive interrupt triggering while the pin is held low - } eint[EXTINT_COUNT]; - -} avr_extint_t; - -void avr_extint_init(avr_t * avr, avr_extint_t * p); -int avr_extint_is_strict_lvl_trig(avr_t * avr, uint8_t extint_no); -void avr_extint_set_strict_lvl_trig(avr_t * avr, uint8_t extint_no, uint8_t strict); - - -// Declares a typical INT into a avr_extint_t in a core. -// this is a shortcut since INT declarations are pretty standard. -// The Tinies as well as the atmega1280 are slightly different. -// See sim_tinyx5.h and sim_mega1280.h -#define AVR_EXTINT_DECLARE(_index, _portname, _portpin) \ - .eint[_index] = { \ - .port_ioctl = AVR_IOCTL_IOPORT_GETIRQ(_portname), \ - .port_pin = _portpin, \ - .isc = { AVR_IO_REGBIT(EICRA, ISC##_index##0), AVR_IO_REGBIT(EICRA, ISC##_index##1) },\ - .vector = { \ - .enable = AVR_IO_REGBIT(EIMSK, INT##_index), \ - .raised = AVR_IO_REGBIT(EIFR, INTF##_index), \ - .vector = INT##_index##_vect, \ - },\ - } - -// Asynchronous External Interrupt, for example INT2 on the m16 and m32 -// Uses only 1 interrupt sense control bit -#define AVR_ASYNC_EXTINT_DECLARE(_index, _portname, _portpin) \ - .eint[_index] = { \ - .port_ioctl = AVR_IOCTL_IOPORT_GETIRQ(_portname), \ - .port_pin = _portpin, \ - .isc = { AVR_IO_REGBIT(MCUCSR, ISC##_index) },\ - .vector = { \ - .enable = AVR_IO_REGBIT(GICR, INT##_index), \ - .raised = AVR_IO_REGBIT(GIFR, INTF##_index), \ - .vector = INT##_index##_vect, \ - },\ - } - -#define AVR_EXTINT_MEGA_DECLARE(_index, _portname, _portpin, _EICR) \ - .eint[_index] = { \ - .port_ioctl = AVR_IOCTL_IOPORT_GETIRQ(_portname), \ - .port_pin = _portpin, \ - .isc = { AVR_IO_REGBIT(EICR##_EICR, ISC##_index##0), AVR_IO_REGBIT(EICR##_EICR, ISC##_index##1) },\ - .vector = { \ - .enable = AVR_IO_REGBIT(EIMSK, INT##_index), \ - .raised = AVR_IO_REGBIT(EIFR, INTF##_index), \ - .vector = INT##_index##_vect, \ - },\ - } - -#define AVR_EXTINT_TINY_DECLARE(_index, _portname, _portpin, _IFR) \ - .eint[_index] = { \ - .port_ioctl = AVR_IOCTL_IOPORT_GETIRQ(_portname), \ - .port_pin = _portpin, \ - .isc = { AVR_IO_REGBIT(MCUCR, ISC##_index##0), AVR_IO_REGBIT(MCUCR, ISC##_index##1) }, \ - .vector = { \ - .enable = AVR_IO_REGBIT(GIMSK, INT##_index), \ - .raised = AVR_IO_REGBIT(_IFR, INTF##_index), \ - .vector = INT##_index##_vect, \ - }, \ - } - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_EXTINT_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.c deleted file mode 100644 index cc1fd96..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - avr_flash.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "avr_flash.h" - -static avr_cycle_count_t avr_progen_clear(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_flash_t * p = (avr_flash_t *)param; - avr_regbit_clear(p->io.avr, p->selfprgen); - AVR_LOG(avr, LOG_WARNING, "FLASH: avr_progen_clear - SPM not received, clearing PRGEN bit\n"); - return 0; -} - - -static void avr_flash_write(avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_flash_t * p = (avr_flash_t *)param; - - avr_core_watch_write(avr, addr, v); - -// printf("** avr_flash_write %02x\n", v); - - if (avr_regbit_get(avr, p->selfprgen)) - avr_cycle_timer_register(avr, 4, avr_progen_clear, p); // 4 cycles is very little! -} - -static void avr_flash_clear_temppage(avr_flash_t *p) -{ - for (int i = 0; i < p->spm_pagesize / 2; i++) { - p->tmppage[i] = 0xff; - p->tmppage_used[i] = 0; - } -} - -static int avr_flash_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param) -{ - if (ctl != AVR_IOCTL_FLASH_SPM) - return -1; - - avr_flash_t * p = (avr_flash_t *)port; - avr_t * avr = p->io.avr; - - avr_flashaddr_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - if (avr->rampz) - z |= avr->data[avr->rampz] << 16; - uint16_t r01 = avr->data[0] | (avr->data[1] << 8); - -// printf("AVR_IOCTL_FLASH_SPM %02x Z:%04x R01:%04x\n", avr->data[p->r_spm], z,r01); - if (avr_regbit_get(avr, p->selfprgen)) { - avr_cycle_timer_cancel(avr, avr_progen_clear, p); - - if (avr_regbit_get(avr, p->pgers)) { - z &= ~1; - AVR_LOG(avr, LOG_TRACE, "FLASH: Erasing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize); - for (int i = 0; i < p->spm_pagesize; i++) - avr->flash[z++] = 0xff; - } else if (avr_regbit_get(avr, p->pgwrt)) { - z &= ~(p->spm_pagesize - 1); - AVR_LOG(avr, LOG_TRACE, "FLASH: Writing page %04x (%d)\n", (z / p->spm_pagesize), p->spm_pagesize); - for (int i = 0; i < p->spm_pagesize / 2; i++) { - avr->flash[z++] = p->tmppage[i]; - avr->flash[z++] = p->tmppage[i] >> 8; - } - avr_flash_clear_temppage(p); - } else if (avr_regbit_get(avr, p->blbset)) { - AVR_LOG(avr, LOG_TRACE, "FLASH: Setting lock bits (ignored)\n"); - } else if (p->flags & AVR_SELFPROG_HAVE_RWW && avr_regbit_get(avr, p->rwwsre)) { - avr_flash_clear_temppage(p); - } else { - AVR_LOG(avr, LOG_TRACE, "FLASH: Writing temppage %08x (%04x)\n", z, r01); - z >>= 1; - if (!p->tmppage_used[z % (p->spm_pagesize / 2)]) { - p->tmppage[z % (p->spm_pagesize / 2)] = r01; - p->tmppage_used[z % (p->spm_pagesize / 2)] = 1; - } - } - } - avr_regbit_clear(avr, p->selfprgen); - return 0; -} - -static void -avr_flash_reset(avr_io_t * port) -{ - avr_flash_t * p = (avr_flash_t *) port; - - avr_flash_clear_temppage(p); -} - -static void -avr_flash_dealloc(struct avr_io_t * port) -{ - avr_flash_t * p = (avr_flash_t *) port; - - if (p->tmppage) - free(p->tmppage); - - if (p->tmppage_used) - free(p->tmppage_used); -} - -static avr_io_t _io = { - .kind = "flash", - .ioctl = avr_flash_ioctl, - .reset = avr_flash_reset, - .dealloc = avr_flash_dealloc, -}; - -void avr_flash_init(avr_t * avr, avr_flash_t * p) -{ - p->io = _io; -// printf("%s init SPM %04x\n", __FUNCTION__, p->r_spm); - - if (!p->tmppage) - p->tmppage = malloc(p->spm_pagesize); - - if (!p->tmppage_used) - p->tmppage_used = malloc(p->spm_pagesize / 2); - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->flash); - - avr_register_io_write(avr, p->r_spm, avr_flash_write, p); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.h deleted file mode 100644 index 07747fc..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_flash.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - avr_flash.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __AVR_FLASH_H___ -#define __AVR_FLASH_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -/* - * Handles self-programming subsystem if the core - * supports it. - */ -typedef struct avr_flash_t { - avr_io_t io; - - uint16_t flags; - uint16_t *tmppage; - uint8_t *tmppage_used; - uint16_t spm_pagesize; - uint8_t r_spm; - avr_regbit_t selfprgen; - avr_regbit_t pgers; // page erase - avr_regbit_t pgwrt; // page write - avr_regbit_t blbset; // lock bit set - avr_regbit_t rwwsre; // read while write section read enable - avr_regbit_t rwwsb; // read while write section busy - - avr_int_vector_t flash; // Interrupt vector -} avr_flash_t; - -/* Set if the flash supports a Read While Write section */ -#define AVR_SELFPROG_HAVE_RWW (1 << 0) - -void avr_flash_init(avr_t * avr, avr_flash_t * p); - - -#define AVR_IOCTL_FLASH_SPM AVR_IOCTL_DEF('f','s','p','m') - -#define AVR_SELFPROG_DECLARE_INTERNAL(_spmr, _spen, _vector) \ - .r_spm = _spmr,\ - .spm_pagesize = SPM_PAGESIZE,\ - .selfprgen = AVR_IO_REGBIT(_spmr, _spen),\ - .pgers = AVR_IO_REGBIT(_spmr, PGERS),\ - .pgwrt = AVR_IO_REGBIT(_spmr, PGWRT),\ - .blbset = AVR_IO_REGBIT(_spmr, BLBSET),\ - .flash = {\ - .enable = AVR_IO_REGBIT(_spmr, SPMIE),\ - .vector = _vector,\ - }\ - -#define AVR_SELFPROG_DECLARE_NORWW(_spmr, _spen, _vector) \ - .selfprog = {\ - .flags = 0,\ - AVR_SELFPROG_DECLARE_INTERNAL(_spmr, _spen, _vector),\ - } - -#define AVR_SELFPROG_DECLARE(_spmr, _spen, _vector) \ - .selfprog = {\ - .flags = AVR_SELFPROG_HAVE_RWW,\ - AVR_SELFPROG_DECLARE_INTERNAL(_spmr, _spen, _vector),\ - .rwwsre = AVR_IO_REGBIT(_spmr, RWWSRE),\ - .rwwsb = AVR_IO_REGBIT(_spmr, RWWSB),\ - } - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_FLASH_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.c deleted file mode 100644 index 91cf106..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - avr_ioport.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "avr_ioport.h" - -#define D(_w) - -static void -avr_ioport_flag_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - - // Clear interrupt if 1 is written to flag. - - if (avr_regbit_from_value(avr, p->pcint.raised, v)) - avr_clear_interrupt(avr, &p->pcint); -} - -static uint8_t -avr_ioport_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - uint8_t ddr = avr->data[p->r_ddr]; - uint8_t v = (avr->data[p->r_pin] & ~ddr) | (avr->data[p->r_port] & ddr); - avr->data[addr] = v; - avr_raise_irq(p->io.irq + IOPORT_IRQ_REG_PIN, v); - D(if (avr->data[addr] != v) printf("** PIN%c(%02x) = %02x\r\n", p->name, addr, v);) - - // made to trigger potential watchpoints - v = avr_core_watch_read(avr, addr); - return v; -} - -static void -avr_ioport_update_irqs( - avr_ioport_t * p) -{ - avr_t * avr = p->io.avr; - uint8_t ddr = avr->data[p->r_ddr]; - // Set the PORT value if the pin is marked as output - // otherwise, if there is an 'external' pullup, set it - // otherwise, if the PORT pin was 1 to indicate an - // internal pullup, set that. - for (int i = 0; i < 8; i++) { - if (ddr & (1 << i)) - avr_raise_irq(p->io.irq + i, (avr->data[p->r_port] >> i) & 1); - else if (p->external.pull_mask & (1 << i)) - avr_raise_irq(p->io.irq + i, (p->external.pull_value >> i) & 1); - else if ((avr->data[p->r_port] >> i) & 1) - avr_raise_irq(p->io.irq + i, 1); - } - uint8_t pin = (avr->data[p->r_pin] & ~ddr) | (avr->data[p->r_port] & ddr); - pin = (pin & ~p->external.pull_mask) | p->external.pull_value; - avr_raise_irq(p->io.irq + IOPORT_IRQ_PIN_ALL, pin); - - // if IRQs are registered on the PORT register (for example, VCD dumps) send - // those as well - avr_io_addr_t port_io = AVR_DATA_TO_IO(p->r_port); - if (avr->io[port_io].irq) { - avr_raise_irq(avr->io[port_io].irq + AVR_IOMEM_IRQ_ALL, avr->data[p->r_port]); - for (int i = 0; i < 8; i++) - avr_raise_irq(avr->io[port_io].irq + i, (avr->data[p->r_port] >> i) & 1); - } -} - -static void -avr_ioport_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - - D(if (avr->data[addr] != v) printf("** PORT%c(%02x) = %02x\r\n", p->name, addr, v);) - avr_core_watch_write(avr, addr, v); - avr_raise_irq(p->io.irq + IOPORT_IRQ_REG_PORT, v); - avr_ioport_update_irqs(p); -} - -/* - * This is a reasonably new behaviour for the io-ports. Writing 1's to the PIN register - * toggles the PORT equivalent bit (regardless of direction - */ -static void -avr_ioport_pin_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - - avr_ioport_write(avr, p->r_port, avr->data[p->r_port] ^ v, param); -} - -/* - * This is a the callback for the DDR register. There is nothing much to do here, apart - * from triggering an IRQ in case any 'client' code is interested in the information, - * and restoring all PIN bits marked as output to PORT values. - */ -static void -avr_ioport_ddr_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - - D(if (avr->data[addr] != v) printf("** DDR%c(%02x) = %02x\r\n", p->name, addr, v);) - avr_raise_irq(p->io.irq + IOPORT_IRQ_DIRECTION_ALL, v); - avr_core_watch_write(avr, addr, v); - avr_ioport_update_irqs(p); -} - -/* - * this is our "main" pin change callback, it can be triggered by either the - * AVR code, or any external piece of code that see fit to do it. - * Either way, this will raise pin change interrupts, if needed - */ -void -avr_ioport_irq_notify( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_ioport_t * p = (avr_ioport_t *)param; - avr_t * avr = p->io.avr; - - int output = value & AVR_IOPORT_OUTPUT; - value &= 0xff; - uint8_t mask = 1 << irq->irq; - uint8_t ddr = avr->data[p->r_ddr]; - - if (output) { - if ((mask & ddr) == 0) - return; // TODO: stop further processing of IRQ. - - // If the IRQ was marked as Output, also do the IO write. - - avr_ioport_write(avr, - p->r_port, - (avr->data[p->r_port] & ~mask) | - (value ? mask : 0), - p); - } else { - // Set the real PIN bit. Ignore DDR as it's masked when read. - - avr_core_watch_write(avr, p->r_pin, - (avr->data[p->r_pin] & ~mask) | - (value ? mask : 0)); - - /* BUG: If DDR bit is set here, there should be no - * interrupt. But a spurious IRQ call by the user - * is indistinguishable from an internal one - * caused by writing the output port register and - * that should cause an interrupt. Doh! - */ - } - - if (p->r_pcint) { - // Ignore lingering copy of AVR_IOPORT_OUTPUT, or - // differing non-zero values. - - if (!value == !(irq->value & 0xff)) - return; - - // if the pcint bit is on, try to raise it - - int raisedata = avr->data[p->r_pcint]; - uint8_t uiRegMask = p->mask; - int8_t iShift = p->shift; - - if (uiRegMask) // If mask is 0, do nothing (backwards compat) - raisedata &= uiRegMask; // Mask off - - if (iShift>0) // Shift data if necessary for alignment. - raisedata <<= iShift; - else if (iShift<0) - raisedata >>= -iShift; - - int raise = raisedata & mask; - if (raise) - avr_raise_interrupt(avr, &p->pcint); - } -} - -static void -avr_ioport_reset( - avr_io_t * port) -{ - avr_ioport_t * p = (avr_ioport_t *)port; - for (int i = 0; i < IOPORT_IRQ_PIN_ALL; i++) - avr_irq_register_notify(p->io.irq + i, avr_ioport_irq_notify, p); -} - -static int -avr_ioport_ioctl( - struct avr_io_t * port, - uint32_t ctl, - void * io_param) -{ - avr_ioport_t * p = (avr_ioport_t *)port; - avr_t * avr = p->io.avr; - int res = -1; - - // all IOCTls require some sort of valid parameter, bail if not - if (!io_param) - return -1; - - switch(ctl) { - case AVR_IOCTL_IOPORT_GETIRQ_REGBIT: { - avr_ioport_getirq_t * r = (avr_ioport_getirq_t*)io_param; - - if (r->bit.reg == p->r_port || r->bit.reg == p->r_pin || r->bit.reg == p->r_ddr) { - // it's us ! check the special case when the "all pins" irq is requested - int o = 0; - if (r->bit.mask == 0xff) - r->irq[o++] = &p->io.irq[IOPORT_IRQ_PIN_ALL]; - else { - // otherwise fill up the ones needed - for (int bi = 0; bi < 8; bi++) - if (r->bit.mask & (1 << bi)) - r->irq[o++] = &p->io.irq[r->bit.bit + bi]; - } - if (o < 8) - r->irq[o] = NULL; - return o; - } - } break; - default: { - /* - * Return the port state if the IOCTL matches us. - */ - if (ctl == AVR_IOCTL_IOPORT_GETSTATE(p->name)) { - avr_ioport_state_t state = { - .name = p->name, - .port = avr->data[p->r_port], - .ddr = avr->data[p->r_ddr], - .pin = avr->data[p->r_pin], - }; - if (io_param) - *((avr_ioport_state_t*)io_param) = state; - res = 0; - } - /* - * Set the default IRQ values when pin is set as input - */ - if (ctl == AVR_IOCTL_IOPORT_SET_EXTERNAL(p->name)) { - avr_ioport_external_t * m = (avr_ioport_external_t*)io_param; - p->external.pull_mask = m->mask; - p->external.pull_value = m->value; - res = 0; - } - } - } - - return res; -} - -static const char * irq_names[IOPORT_IRQ_COUNT] = { - [IOPORT_IRQ_PIN0] = "=pin0", - [IOPORT_IRQ_PIN1] = "=pin1", - [IOPORT_IRQ_PIN2] = "=pin2", - [IOPORT_IRQ_PIN3] = "=pin3", - [IOPORT_IRQ_PIN4] = "=pin4", - [IOPORT_IRQ_PIN5] = "=pin5", - [IOPORT_IRQ_PIN6] = "=pin6", - [IOPORT_IRQ_PIN7] = "=pin7", - [IOPORT_IRQ_PIN_ALL] = "8>all", - [IOPORT_IRQ_DIRECTION_ALL] = "8>ddr", - [IOPORT_IRQ_REG_PORT] = "8>port", - [IOPORT_IRQ_REG_PIN] = "8>pin", -}; - -static avr_io_t _io = { - .kind = "port", - .reset = avr_ioport_reset, - .ioctl = avr_ioport_ioctl, - .irq_names = irq_names, -}; - -void avr_ioport_init(avr_t * avr, avr_ioport_t * p) -{ - if (!p->r_port) { - printf("skipping PORT%c for core %s\n", p->name, avr->mmcu); - return; - } - p->io = _io; -// printf("%s PIN%c 0x%02x DDR%c 0x%02x PORT%c 0x%02x\n", __FUNCTION__, -// p->name, p->r_pin, -// p->name, p->r_ddr, -// p->name, p->r_port); - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->pcint); - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_IOPORT_GETIRQ(p->name), IOPORT_IRQ_COUNT, NULL); - - for (int i = 0; i < IOPORT_IRQ_REG_PIN; i++) { - p->io.irq[i].flags |= IRQ_FLAG_FILTERED; - if (i < IOPORT_IRQ_PIN_ALL) - p->io.irq[i].flags &= ~IRQ_FLAG_INIT; - } - avr_register_io_write(avr, p->r_port, avr_ioport_write, p); - avr_register_io_read(avr, p->r_pin, avr_ioport_read, p); - avr_register_io_write(avr, p->r_pin, avr_ioport_pin_write, p); - avr_register_io_write(avr, p->r_ddr, avr_ioport_ddr_write, p); - if (p->pcint.raised.reg) { - avr_register_io_write(avr, p->pcint.raised.reg, - avr_ioport_flag_write, p); - } -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.h deleted file mode 100644 index 024b695..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_ioport.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - avr_ioport.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_IOPORT_H__ -#define __AVR_IOPORT_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -enum { - IOPORT_IRQ_PIN0 = 0, - IOPORT_IRQ_PIN1,IOPORT_IRQ_PIN2,IOPORT_IRQ_PIN3,IOPORT_IRQ_PIN4, - IOPORT_IRQ_PIN5,IOPORT_IRQ_PIN6,IOPORT_IRQ_PIN7, - IOPORT_IRQ_PIN_ALL, - IOPORT_IRQ_DIRECTION_ALL, - IOPORT_IRQ_REG_PORT, - IOPORT_IRQ_REG_PIN, - IOPORT_IRQ_COUNT -}; - -#define AVR_IOPORT_OUTPUT 0x100 - -// add port name (uppercase) to get the real IRQ -#define AVR_IOCTL_IOPORT_GETIRQ(_name) AVR_IOCTL_DEF('i','o','g',(_name)) - - -// this ioctl takes a avr_regbit_t, compares the register address -// to PORT/PIN/DDR and return the corresponding IRQ(s) if it matches -typedef struct avr_ioport_getirq_t { - avr_regbit_t bit; // bit wanted - avr_irq_t * irq[8]; // result, terminated by NULL if < 8 -} avr_ioport_getirq_t; - -#define AVR_IOCTL_IOPORT_GETIRQ_REGBIT AVR_IOCTL_DEF('i','o','g','r') - -/* - * ioctl used to get a port state. - * - * for (int i = 'A'; i <= 'F'; i++) { - * avr_ioport_state_t state; - * if (avr_ioctl(AVR_IOCTL_IOPORT_GETSTATE(i), &state) == 0) - * printf("PORT%c %02x DDR %02x PIN %02x\n", - * state.name, state.port, state.ddr, state.pin); - * } - */ -typedef struct avr_ioport_state_t { - unsigned long name : 7, - port : 8, ddr : 8, pin : 8; -} avr_ioport_state_t; - -// add port name (uppercase) to get the port state -#define AVR_IOCTL_IOPORT_GETSTATE(_name) AVR_IOCTL_DEF('i','o','s',(_name)) - -/* - * ioctl used to set default port state when set as input. - * - */ -typedef struct avr_ioport_external_t { - unsigned long name : 7, - mask : 8, value : 8; -} avr_ioport_external_t; - -// add port name (uppercase) to set default input pin IRQ values -#define AVR_IOCTL_IOPORT_SET_EXTERNAL(_name) AVR_IOCTL_DEF('i','o','p',(_name)) - -/** - * pin structure - */ -typedef struct avr_iopin_t { - uint16_t port : 8; ///< port e.g. 'B' - uint16_t pin : 8; ///< pin number -} avr_iopin_t; -#define AVR_IOPIN(_port, _pin) { .port = _port, .pin = _pin } - -/* - * Definition for an IO port - */ -typedef struct avr_ioport_t { - avr_io_t io; - char name; - avr_io_addr_t r_port; - avr_io_addr_t r_ddr; - avr_io_addr_t r_pin; - - avr_int_vector_t pcint; // PCINT vector - avr_io_addr_t r_pcint; // pcint 8 pins mask - - // Mask and shift for PCINTs. This is needed for chips like the 2560 - // where PCINT do not align with IRQs. - - uint8_t mask; - int8_t shift; - - // This represent the default IRQ value when - // the port is set as input. - // If the mask is not set, no output value is sent - // on the output IRQ. If the mask is set, the specified - // value is sent. - struct { - uint8_t pull_mask, pull_value; - } external; -} avr_ioport_t; - -void avr_ioport_init(avr_t * avr, avr_ioport_t * port); - -#define AVR_IOPORT_DECLARE(_lname, _cname, _uname) \ - .port ## _lname = { \ - .name = _cname, .r_port = PORT ## _uname, .r_ddr = DDR ## _uname, .r_pin = PIN ## _uname, \ - } - -#define AVR_IOPORT_DECLARE_PC(_lname, _cname, _uname, _pcnum) \ - .port ## _lname = { \ - .name = _cname, .r_port = PORT ## _uname, \ - .r_ddr = DDR ## _uname, .r_pin = PIN ## _uname, \ - .pcint = { \ - .enable = AVR_IO_REGBIT(PCICR, PCIE ## _pcnum), \ - .raised = AVR_IO_REGBIT(PCIFR, PCIF ## _pcnum), \ - .vector = PCINT ## _pcnum ## _vect, \ - }, \ - .r_pcint = PCMSK ## _pcnum, \ - } - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_IOPORT_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.c deleted file mode 100644 index 001b34c..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - avr_lin.h - - Copyright 2008, 2011 Michel Pollet - Copyright 2011 Markus Lampert - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "avr_lin.h" -#include "sim_time.h" - - -static void -avr_lin_baud_write( - struct avr_t *avr, - avr_io_addr_t addr, - uint8_t v, - void *param) -{ - avr_lin_t *p = (avr_lin_t*) param; - - if (p->r_linbtr != p->ldisr.reg || p->r_linbtr != p->lbt.reg) { // sanity check - AVR_LOG(avr, LOG_ERROR, "LIN: LDISR and LBT[x] register different!\n"); - return; - } - - AVR_LOG(avr, LOG_TRACE, "LIN: addr[%04x] = %02x\n", addr, v); - if (addr == p->ldisr.reg) { - if (avr_regbit_get(avr, p->lena)) { - AVR_LOG(avr, LOG_WARNING, "LIN: LENA bit set on changing LBTR\n"); - return; - } - if ((v >> p->ldisr.bit) & p->ldisr.mask) { - uint8_t lbt = (v >> p->lbt.bit) & p->lbt.mask; - uint8_t ov = v; - v = (1 << p->ldisr.bit) | (lbt << p->lbt.bit); - AVR_LOG(avr, LOG_TRACE, "LIN: v=%02x -> LBT = %02x -> LINBT = %02x\n", ov, lbt, v); - } else { - v = 0x20; - } - } - avr_core_watch_write(avr, addr, v); // actually set the value - - uint32_t lbt = avr_regbit_get(avr, p->lbt); // Min value CANNOT be zero - uint32_t lbrr = (avr->data[p->r_linbrrh] << 8) | avr->data[p->r_linbrrl]; - AVR_LOG(avr, LOG_TRACE, "LIN: UART LBT/LBRR to %04x/%04x\n", lbt, lbrr); - // there is no division by zero case here, lbt is >= 8 - //uint32_t baud = avr->frequency / (lbt * (lbrr + 1)); - uint32_t word_size = 1 /*start*/+ 8 /*data bits*/+ 1 /*parity*/+ 1 /*stop*/; - int cycles_per_bit = lbt * (lbrr + 1); - double baud = ((double)avr->frequency) / cycles_per_bit; // can be less than 1 - p->uart.cycles_per_byte = cycles_per_bit * word_size; - - AVR_LOG(avr, LOG_TRACE, "LIN: UART configured to %04x/%04x = %.4f bps, 8 data 1 stop\n", lbt, - lbrr, baud); - - //p->uart.cycles_per_byte = 1000000 / (baud / word_size); - AVR_LOG(avr, LOG_TRACE, "LIN: Roughly %d usec per byte\n", - avr_cycles_to_usec(avr, p->uart.cycles_per_byte)); -} - -static void -avr_lin_reset( - avr_io_t *port) -{ - avr_lin_t *p = (avr_lin_t*) port; - avr_t * avr = p->io.avr; - - AVR_LOG(avr, LOG_TRACE, "LIN: UART: reset\n"); - - p->uart.io.reset(&p->uart.io); - avr->data[p->r_linbtr] = 0x20; -} - -static avr_io_t _io = { - .kind = "lin", - .reset = avr_lin_reset, -}; - -void -avr_lin_init( - avr_t *avr, - avr_lin_t *p) -{ - // init uart part - avr_uart_init(avr, &p->uart); - - p->io = _io; - avr_register_io_write(avr, p->r_linbtr, avr_lin_baud_write, p); - avr_register_io_write(avr, p->r_linbrrl, avr_lin_baud_write, p); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.h deleted file mode 100644 index b1ecadf..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_lin.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - avr_lin.h - - Copyright 2008, 2011 Michel Pollet - Copyright 2011 Markus Lampert - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_LIN_H__ -#define __AVR_LIN_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" -#include "avr_uart.h" - -typedef struct avr_lin_t { - avr_io_t io; - - avr_io_addr_t r_linbtr; - avr_io_addr_t r_linbrrh, r_linbrrl; - - avr_regbit_t lena; - avr_regbit_t ldisr; - avr_regbit_t lbt; - - avr_uart_t uart; // used when LIN controller is setup as a UART -} avr_lin_t; - -void -avr_lin_init( - avr_t *avr, - avr_lin_t *port); - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_LIN_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.c deleted file mode 100644 index bb602ac..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - avr_spi.c - - Copyright 2008, 2009 Michel Pollet - Modified 2020 by VintagePC to support clock divisors - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "avr_spi.h" - -static avr_cycle_count_t avr_spi_raise(struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_spi_t * p = (avr_spi_t *)param; - - if (avr_regbit_get(avr, p->spe)) { - // in master mode, any byte is sent as it comes.. - if (avr_regbit_get(avr, p->mstr)) { - avr_raise_interrupt(avr, &p->spi); - avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]); - } - } - return 0; -} - -static uint8_t avr_spi_read(struct avr_t * avr, avr_io_addr_t addr, void * param) -{ - avr_spi_t * p = (avr_spi_t *)param; - uint8_t v = p->input_data_register; - p->input_data_register = 0; - avr_regbit_clear(avr, p->spi.raised); -// printf("avr_spi_read = %02x\n", v); - return v; -} - -static void avr_spi_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - - static const uint8_t _avr_spi_clkdiv[4] = {4,16,64,128}; - avr_spi_t * p = (avr_spi_t *)param; - - if (addr == p->r_spdr) { - /* Clear the SPIF bit. See ATmega164/324/644 manual, Section 18.5.2. */ - avr_regbit_clear(avr, p->spi.raised); - - avr_core_watch_write(avr, addr, v); - uint16_t clock_shift = _avr_spi_clkdiv[avr->data[p->r_spcr]&0b11]; - // If master && 2X, double rate (half divisor) - if (avr_regbit_get(avr, p->mstr) && avr_regbit_get(avr, p->spr[2])) - clock_shift>>=1; - - // We can wait directly in clockshifts, it is a divisor, so /4 means 4 avr cycles to clock out one bit. - avr_cycle_timer_register(avr, clock_shift<<3, avr_spi_raise, p); // *8 since 8 clocks to a byte. - } -} - -static void avr_spi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param) -{ - avr_spi_t * p = (avr_spi_t *)param; - avr_t * avr = p->io.avr; - - // check to see if receiver is enabled - if (!avr_regbit_get(avr, p->spe)) - return; - - // double buffer the input.. ? - p->input_data_register = value; - avr_raise_interrupt(avr, &p->spi); - - // if in slave mode, - // 'output' the byte only when we received one... - if (!avr_regbit_get(avr, p->mstr)) { - avr_raise_irq(p->io.irq + SPI_IRQ_OUTPUT, avr->data[p->r_spdr]); - } -} - -void avr_spi_reset(struct avr_io_t *io) -{ - avr_spi_t * p = (avr_spi_t *)io; - avr_irq_register_notify(p->io.irq + SPI_IRQ_INPUT, avr_spi_irq_input, p); -} - -static const char * irq_names[SPI_IRQ_COUNT] = { - [SPI_IRQ_INPUT] = "8io = _io; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->spi); - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_SPI_GETIRQ(p->name), SPI_IRQ_COUNT, NULL); - - avr_register_io_write(avr, p->r_spdr, avr_spi_write, p); - avr_register_io_read(avr, p->r_spdr, avr_spi_read, p); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.h deleted file mode 100644 index c676adb..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_spi.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - avr_spi.h - - Copyright 2008, 2009 Michel Pollet - Modified 2020 by VintagePC to support clock divisors - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_SPI_H__ -#define __AVR_SPI_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -enum { - SPI_IRQ_INPUT = 0, - SPI_IRQ_OUTPUT, - SPI_IRQ_COUNT -}; - -// add port number to get the real IRQ -#define AVR_IOCTL_SPI_GETIRQ(_name) AVR_IOCTL_DEF('s','p','i',(_name)) - -typedef struct avr_spi_t { - avr_io_t io; - char name; - avr_regbit_t disabled; // bit in the PRR - - avr_io_addr_t r_spdr; // data register - avr_io_addr_t r_spcr; // control register - avr_io_addr_t r_spsr; // status register - - avr_regbit_t spe; // spi enable - avr_regbit_t mstr; // master/slave - avr_regbit_t spr[4]; // clock divider - - avr_int_vector_t spi; // spi interrupt - - uint8_t input_data_register; -} avr_spi_t; - -void avr_spi_init(avr_t * avr, avr_spi_t * port); - -#define AVR_SPIX_DECLARE(_name, _prr, _prspi) \ - .spi = { \ - .name = '0' + _name,\ - .disabled = AVR_IO_REGBIT(_prr, _prspi), \ - \ - .r_spdr = SPDR ## _name, \ - .r_spcr = SPCR ## _name, \ - .r_spsr = SPSR ## _name, \ - \ - .spe = AVR_IO_REGBIT(SPCR ## _name, SPE ## _name), \ - .mstr = AVR_IO_REGBIT(SPCR ## _name, MSTR ## _name), \ - \ - .spr = { AVR_IO_REGBIT(SPCR ## _name, SPR0 ## _name), \ - AVR_IO_REGBIT(SPCR ## _name, SPR1 ## _name), \ - AVR_IO_REGBIT(SPSR ## _name, SPI2X ## _name) }, \ - .spi = { \ - .enable = AVR_IO_REGBIT(SPCR ## _name, SPIE ## _name), \ - .raised = AVR_IO_REGBIT(SPSR ## _name, SPIF ## _name), \ - .vector = SPI_STC_vect, \ - }, \ - } - - -#define AVR_SPI_DECLARE(_prr, _prspi) \ - .spi = { \ - .disabled = AVR_IO_REGBIT(_prr, _prspi), \ - \ - .r_spdr = SPDR, \ - .r_spcr = SPCR, \ - .r_spsr = SPSR, \ - \ - .spe = AVR_IO_REGBIT(SPCR, SPE), \ - .mstr = AVR_IO_REGBIT(SPCR, MSTR), \ - \ - .spr = { AVR_IO_REGBIT(SPCR, SPR0), AVR_IO_REGBIT(SPCR, SPR1), AVR_IO_REGBIT(SPSR, SPI2X) }, \ - .spi = { \ - .enable = AVR_IO_REGBIT(SPCR, SPIE), \ - .raised = AVR_IO_REGBIT(SPSR, SPIF), \ - .vector = SPI_STC_vect, \ - }, \ - } - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_SPI_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.c deleted file mode 100644 index 39a46bd..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - avr_timer.c - - Handles the 8 bits and 16 bits AVR timer. - Handles - + CDC - + Fast PWM - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include - -#include "avr_timer.h" -#include "avr_ioport.h" -#include "sim_time.h" - -/* - * The timers are /always/ 16 bits here, if the higher byte register - * is specified it's just added. - */ -static uint16_t -_timer_get_ocr( - avr_timer_t * p, - int compi) -{ - return p->io.avr->data[p->comp[compi].r_ocr] | - (p->comp[compi].r_ocrh ? - (p->io.avr->data[p->comp[compi].r_ocrh] << 8) : 0); -} - -static uint16_t -_timer_get_comp_ocr( - struct avr_t * avr, - avr_timer_comp_p comp) -{ - int ocrh = comp->r_ocrh; - return avr->data[comp->r_ocr] | - (ocrh ? (avr->data[ocrh] << 8) : 0); -} - -static uint16_t -_timer_get_tcnt( - avr_timer_t * p) -{ - return p->io.avr->data[p->r_tcnt] | - (p->r_tcnth ? (p->io.avr->data[p->r_tcnth] << 8) : 0); -} - -static uint16_t -_timer_get_icr( - avr_timer_t * p) -{ - return p->io.avr->data[p->r_icr] | - (p->r_tcnth ? (p->io.avr->data[p->r_icrh] << 8) : 0); -} -static avr_cycle_count_t -avr_timer_comp( - avr_timer_t *p, - avr_cycle_count_t when, - uint8_t comp, - uint8_t raise_interrupt) -{ - avr_t * avr = p->io.avr; - if (raise_interrupt) { - avr_raise_interrupt(avr, &p->comp[comp].interrupt); - } - - // check output compare mode and set/clear pins - uint8_t mode = avr_regbit_get(avr, p->comp[comp].com); - avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp]; - - uint32_t flags = 0; - if (p->comp[comp].com_pin.reg) // we got a physical pin - flags |= AVR_IOPORT_OUTPUT; - AVR_LOG(avr, LOG_TRACE, "Timer comp: irq %p, mode %d @%d\n", irq, mode, when); - switch (mode) { - case avr_timer_com_normal: // Normal mode OCnA disconnected - break; - case avr_timer_com_toggle: // Toggle OCnA on compare match - if (p->comp[comp].com_pin.reg) // we got a physical pin - avr_raise_irq(irq, - flags | - (avr_regbit_get(avr, p->comp[comp].com_pin) ? 0 : 1)); - else // no pin, toggle the IRQ anyway - avr_raise_irq(irq, - p->io.irq[TIMER_IRQ_OUT_COMP + comp].value ? 0 : 1); - break; - case avr_timer_com_clear: - avr_raise_irq(irq, flags | 0); - break; - case avr_timer_com_set: - avr_raise_irq(irq, flags | 1); - break; - } - - return p->tov_cycles ? 0 : - p->comp[comp].comp_cycles ? - when + p->comp[comp].comp_cycles : 0; -} - -static void -avr_timer_comp_on_tov( - avr_timer_t *p, - avr_cycle_count_t when, - uint8_t comp) -{ - avr_t * avr = p->io.avr; - - // check output compare mode and set/clear pins - uint8_t mode = avr_regbit_get(avr, p->comp[comp].com); - avr_irq_t * irq = &p->io.irq[TIMER_IRQ_OUT_COMP + comp]; - - // only PWM modes have special behaviour on overflow - if((p->wgm_op_mode_kind != avr_timer_wgm_pwm) && - (p->wgm_op_mode_kind != avr_timer_wgm_fast_pwm)) - return; - - switch (mode) { - case avr_timer_com_normal: // Normal mode - break; - case avr_timer_com_toggle: // toggle on compare match => on tov do nothing - break; - case avr_timer_com_clear: // clear on compare match => set on tov - avr_raise_irq(irq, 1); - break; - case avr_timer_com_set: // set on compare match => clear on tov - avr_raise_irq(irq, 0); - break; - } -} - -static avr_cycle_count_t -avr_timer_compa( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPA, 1); -} - -static avr_cycle_count_t -avr_timer_compb( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPB, 1); -} - -static avr_cycle_count_t -avr_timer_compc( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - return avr_timer_comp((avr_timer_t*)param, when, AVR_TIMER_COMPC, 1); -} - -static void -avr_timer_irq_ext_clock( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - avr_t * avr = p->io.avr; - - if ((p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_VIRT) || !p->tov_top) - return; // we are clocked internally (actually should never come here) - - int bing = 0; - if (p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_EDGE) { // clock on rising edge - if (!irq->value && value) - bing++; - } else { // clock on falling edge - if (irq->value && !value) - bing++; - } - if (!bing) - return; - - //AVR_LOG(avr, LOG_TRACE, "%s Timer%c tick, tcnt=%i\n", __func__, p->name, p->tov_base); - - p->ext_clock_flags |= AVR_TIMER_EXTCLK_FLAG_STARTED; - - static const avr_cycle_timer_t dispatch[AVR_TIMER_COMP_COUNT] = - { avr_timer_compa, avr_timer_compb, avr_timer_compc }; - - int overflow = 0; - /** - * - * Datasheet excerpt (Compare Match Output Unit): - * "The 16-bit comparator continuously compares TCNT1 with the Output Compare Regis- - ter (OCR1x). If TCNT equals OCR1x the comparator signals a match. A match will set - the Output Compare Flag (OCF1x) at the next timer clock cycle. If enabled (OCIE1x = - 1), the Output Compare Flag generates an output compare interrupt." - Thus, comparators should go before incementing the counter to use counter value - from the previous cycle. - */ - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if (p->wgm_op_mode_kind != avr_timer_wgm_ctc) { - if ((p->mode.top == avr_timer_wgm_reg_ocra) && (compi == 0)) - continue; // ocra used to define TOP - } - if (p->comp[compi].comp_cycles && (p->tov_base == p->comp[compi].comp_cycles)) { - dispatch[compi](avr, avr->cycle, param); - if (p->wgm_op_mode_kind == avr_timer_wgm_ctc) - p->tov_base = 0; - } - } - - switch (p->wgm_op_mode_kind) { - case avr_timer_wgm_fc_pwm: // in the avr_timer_write_ocr comment "OCR is not used here" - why? - case avr_timer_wgm_pwm: - if ((p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_REVDIR) != 0) { - --p->tov_base; - if (p->tov_base == 0) { - // overflow occured - p->ext_clock_flags &= ~AVR_TIMER_EXTCLK_FLAG_REVDIR; // restore forward count direction - overflow = 1; - } - } - else { - if (++p->tov_base >= p->tov_top) { - p->ext_clock_flags |= AVR_TIMER_EXTCLK_FLAG_REVDIR; // prepare to count down - } - } - break; - case avr_timer_wgm_fast_pwm: - if (++p->tov_base == p->tov_top) { - overflow = 1; - if (p->mode.top == avr_timer_wgm_reg_icr) - avr_raise_interrupt(avr, &p->icr); - else if (p->mode.top == avr_timer_wgm_reg_ocra) - avr_raise_interrupt(avr, &p->comp[0].interrupt); - } - else if (p->tov_base > p->tov_top) { - p->tov_base = 0; - } - break; - case avr_timer_wgm_ctc: - { - int max = (1 << p->wgm_op[0].size)-1; - if (++p->tov_base > max) { - // overflow occured - p->tov_base = 0; - overflow = 1; - } - } - break; - default: - if (++p->tov_base > p->tov_top) { - // overflow occured - p->tov_base = 0; - overflow = 1; - } - break; - } - - if (overflow) { - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if (p->comp[compi].comp_cycles) { - if (p->mode.top == avr_timer_wgm_reg_ocra && compi == 0) - continue; - avr_timer_comp_on_tov(p, 0, compi); - } - } - avr_raise_interrupt(avr, &p->overflow); - } - -} - -// timer overflow -static avr_cycle_count_t -avr_timer_tov( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - int start = p->tov_base == 0; - - avr_cycle_count_t next = when; - if (((p->ext_clock_flags & (AVR_TIMER_EXTCLK_FLAG_AS2 | AVR_TIMER_EXTCLK_FLAG_TN)) != 0) - && (p->tov_cycles_fract != 0.0f)) { - p->phase_accumulator += p->tov_cycles_fract; - if (p->phase_accumulator >= 1.0f) { - ++next; - p->phase_accumulator -= 1.0f; - } else if (p->phase_accumulator <= -1.0f) { - --next; - p->phase_accumulator += 1.0f; - } - } - - if (!start) - avr_raise_interrupt(avr, &p->overflow); - p->tov_base = when; - - static const avr_cycle_timer_t dispatch[AVR_TIMER_COMP_COUNT] = - { avr_timer_compa, avr_timer_compb, avr_timer_compc }; - - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if (p->comp[compi].comp_cycles) { - if (p->comp[compi].comp_cycles < p->tov_cycles && p->comp[compi].comp_cycles >= (avr->cycle - when)) { - avr_timer_comp_on_tov(p, when, compi); - avr_cycle_timer_register(avr, - p->comp[compi].comp_cycles - (avr->cycle - next), - dispatch[compi], p); - } else if (p->tov_cycles == p->comp[compi].comp_cycles && !start) - dispatch[compi](avr, when, param); - } - } - - return next + p->tov_cycles; -} - -static uint16_t -_avr_timer_get_current_tcnt( - avr_timer_t * p) -{ - avr_t * avr = p->io.avr; - if (!(p->ext_clock_flags & (AVR_TIMER_EXTCLK_FLAG_TN | AVR_TIMER_EXTCLK_FLAG_AS2)) || - (p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_VIRT) - ) { - if (p->tov_cycles) { - uint64_t when = avr->cycle - p->tov_base; - - return (when * (((uint32_t)p->tov_top)+1)) / p->tov_cycles; - } - } - else { - if (p->tov_top) - return p->tov_base; - } - return 0; -} - -static uint8_t -avr_timer_tcnt_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - // made to trigger potential watchpoints - - uint16_t tcnt = _avr_timer_get_current_tcnt(p); - - avr->data[p->r_tcnt] = tcnt; - if (p->r_tcnth) - avr->data[p->r_tcnth] = tcnt >> 8; - - return avr_core_watch_read(avr, addr); -} - -static inline void -avr_timer_cancel_all_cycle_timers( - struct avr_t * avr, - avr_timer_t *timer, - const uint8_t clear_timers) -{ - if(clear_timers) { - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) - timer->comp[compi].comp_cycles = 0; - timer->tov_cycles = 0; - } - - - avr_cycle_timer_cancel(avr, avr_timer_tov, timer); - avr_cycle_timer_cancel(avr, avr_timer_compa, timer); - avr_cycle_timer_cancel(avr, avr_timer_compb, timer); - avr_cycle_timer_cancel(avr, avr_timer_compc, timer); -} - -static void -avr_timer_tcnt_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - avr_core_watch_write(avr, addr, v); - uint16_t tcnt = _timer_get_tcnt(p); - - if (!p->tov_top) - return; - - if (tcnt >= p->tov_top) - tcnt = 0; - - if (!(p->ext_clock_flags & (AVR_TIMER_EXTCLK_FLAG_TN | AVR_TIMER_EXTCLK_FLAG_AS2)) || - (p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_VIRT) - ) { - // internal or virtual clock - - // this involves some magicking - // cancel the current timers, recalculate the "base" we should be at, reset the - // timer base as it should, and re-schedule the timers using that base. - - avr_timer_cancel_all_cycle_timers(avr, p, 0); - - uint64_t cycles = (tcnt * p->tov_cycles) / p->tov_top; - - // printf("%s-%c %d/%d -- cycles %d/%d\n", __FUNCTION__, p->name, tcnt, p->tov_top, (uint32_t)cycles, (uint32_t)p->tov_cycles); - - // this reset the timers bases to the new base - if (p->tov_cycles > 1) { - avr_cycle_timer_register(avr, p->tov_cycles - cycles, avr_timer_tov, p); - p->tov_base = 0; - avr_timer_tov(avr, avr->cycle - cycles, p); - } - - // tcnt = ((avr->cycle - p->tov_base) * p->tov_top) / p->tov_cycles; - // printf("%s-%c new tnt derive to %d\n", __FUNCTION__, p->name, tcnt); - } - else { - // clocked externally - p->tov_base = tcnt; - } -} - -static void -avr_timer_configure( - avr_timer_t * p, - uint32_t prescaler, - uint32_t top, - uint8_t reset) -{ - p->tov_top = top; - - avr_t * avr = p->io.avr; - float resulting_clock = 0.0f; // used only for trace - float tov_cycles_exact = 0; - - uint8_t as2 = p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_AS2; - uint8_t use_ext_clock = as2 || (p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_TN); - uint8_t virt_ext_clock = use_ext_clock && (p->ext_clock_flags & AVR_TIMER_EXTCLK_FLAG_VIRT); - - if (!use_ext_clock) { - if (prescaler != 0) - resulting_clock = (float)avr->frequency / prescaler; - p->tov_cycles = prescaler * (top+1); - p->tov_cycles_fract = 0.0f; - tov_cycles_exact = p->tov_cycles; - } else { - if (!virt_ext_clock) { - p->tov_cycles = 0; - p->tov_cycles_fract = 0.0f; - } else { - if (prescaler != 0) - resulting_clock = p->ext_clock / prescaler; - tov_cycles_exact = (float)avr->frequency / p->ext_clock * prescaler * (top+1); - // p->tov_cycles = round(tov_cycles_exact); -- don't want libm! - p->tov_cycles = tov_cycles_exact + .5f; // Round to integer - p->tov_cycles_fract = tov_cycles_exact - p->tov_cycles; - } - } - - if (p->trace) { - if (!use_ext_clock || virt_ext_clock) { - // clocked internally - AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c TOP %.2fHz = %d cycles = %dusec\n", // TOP there means Timer Overflows Persec ? - __FUNCTION__, p->name, ((float)avr->frequency / tov_cycles_exact), - (int)p->tov_cycles, (int)avr_cycles_to_usec(avr, p->tov_cycles)); - } else { - // clocked externally from the Tn pin - AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c use ext clock, TOP=%d\n", - __FUNCTION__, p->name, (int)p->tov_top - ); - } - } - - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if (!p->comp[compi].r_ocr) - continue; - uint32_t ocr = _timer_get_ocr(p, compi); - //uint32_t comp_cycles = clock * (ocr + 1); - uint32_t comp_cycles; - if (virt_ext_clock) - comp_cycles = (uint32_t)((float)avr->frequency / p->ext_clock * prescaler * (ocr+1)); - else - comp_cycles = prescaler * (ocr + 1); - - p->comp[compi].comp_cycles = 0; - - if (p->trace & (avr_timer_trace_compa << compi)) { - if (!use_ext_clock || virt_ext_clock) { - printf("%s-%c clock %f top %d OCR%c %d\n", __FUNCTION__, p->name, - resulting_clock, top, 'A'+compi, ocr); - } else { - AVR_LOG(avr, LOG_TRACE, "%s timer%c clock via ext pin, TOP=%d OCR%c=%d\n", - __FUNCTION__, p->name, top, 'A'+compi, ocr); - } - } - if (ocr <= top) { - p->comp[compi].comp_cycles = comp_cycles; - - if (p->trace & (avr_timer_trace_compa << compi)) printf( - "TIMER: %s-%c %c %.2fHz = %d cycles\n", - __FUNCTION__, p->name, - 'A'+compi, resulting_clock / (ocr+1), - (int)comp_cycles); - } - } - - if (!use_ext_clock || virt_ext_clock) { - if (p->tov_cycles > 1) { - if (reset) { - avr_cycle_timer_register(avr, p->tov_cycles, avr_timer_tov, p); - // calling it once, with when == 0 tells it to arm the A/B/C timers if needed - p->tov_base = 0; - avr_timer_tov(avr, avr->cycle, p); - p->phase_accumulator = 0.0f; - } else { - uint64_t orig_tov_base = p->tov_base; - avr_cycle_timer_register(avr, p->tov_cycles - (avr->cycle - orig_tov_base), avr_timer_tov, p); - // calling it once, with when == 0 tells it to arm the A/B/C timers if needed - p->tov_base = 0; - avr_timer_tov(avr, orig_tov_base, p); - } - } - } else { - if (reset) - p->tov_base = 0; - } - - if (reset) { - avr_ioport_getirq_t req = { - .bit = p->ext_clock_pin - }; - if (avr_ioctl(p->io.avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) { - // got an IRQ for the Tn input clock pin - if (use_ext_clock && !virt_ext_clock) { - if (p->trace) - AVR_LOG(p->io.avr, LOG_TRACE, "%s: timer%c connecting T%c pin IRQ %d\n", __FUNCTION__, p->name, p->name, req.irq[0]->irq); - avr_irq_register_notify(req.irq[0], avr_timer_irq_ext_clock, p); - } else { - if (p->trace) - AVR_LOG(p->io.avr, LOG_TRACE, "%s: timer%c disconnecting T%c pin IRQ %d\n", __FUNCTION__, p->name, p->name, req.irq[0]->irq); - avr_irq_unregister_notify(req.irq[0], avr_timer_irq_ext_clock, p); - } - } - } - -} - -static void -avr_timer_reconfigure( - avr_timer_t * p, uint8_t reset) -{ - avr_t * avr = p->io.avr; - - // cancel everything - avr_timer_cancel_all_cycle_timers(avr, p, 1); - - switch (p->wgm_op_mode_kind) { - case avr_timer_wgm_normal: - avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset); - break; - case avr_timer_wgm_fc_pwm: - avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset); - break; - case avr_timer_wgm_ctc: { - avr_timer_configure(p, p->cs_div_value, _timer_get_ocr(p, AVR_TIMER_COMPA), reset); - } break; - case avr_timer_wgm_pwm: { - uint16_t top = (p->mode.top == avr_timer_wgm_reg_ocra) ? - _timer_get_ocr(p, AVR_TIMER_COMPA) : _timer_get_icr(p); - avr_timer_configure(p, p->cs_div_value, top, reset); - } break; - case avr_timer_wgm_fast_pwm: { - uint16_t top = - (p->mode.top == avr_timer_wgm_reg_icr) ? _timer_get_icr(p) : - p->wgm_op_mode_size; - avr_timer_configure(p, p->cs_div_value, top, reset); - } break; - case avr_timer_wgm_none: - avr_timer_configure(p, p->cs_div_value, p->wgm_op_mode_size, reset); - break; - default: { - uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)); - AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c unsupported timer mode wgm=%d (%d)\n", - __FUNCTION__, p->name, mode, p->mode.kind); - } - } -} - -static void -avr_timer_write_ocr( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_timer_comp_p comp = (avr_timer_comp_p)param; - avr_timer_t *timer = comp->timer; - uint16_t oldv; - - /* check to see if the OCR values actually changed */ - oldv = _timer_get_comp_ocr(avr, comp); - avr_core_watch_write(avr, addr, v); - - switch (timer->wgm_op_mode_kind) { - case avr_timer_wgm_normal: - avr_timer_reconfigure(timer, 0); - break; - case avr_timer_wgm_fc_pwm: // OCR is not used here - avr_timer_reconfigure(timer, 0); - break; - case avr_timer_wgm_ctc: - avr_timer_reconfigure(timer, 0); - break; - case avr_timer_wgm_pwm: - if (timer->mode.top != avr_timer_wgm_reg_ocra) { - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, _timer_get_ocr(timer, AVR_TIMER_COMPA)); - } else { - avr_timer_reconfigure(timer, 0); // if OCRA is the top, reconfigure needed - } - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, _timer_get_ocr(timer, AVR_TIMER_COMPB)); - if (sizeof(timer->comp)>2) - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM2, _timer_get_ocr(timer, AVR_TIMER_COMPC)); - break; - case avr_timer_wgm_fast_pwm: - if (oldv != _timer_get_comp_ocr(avr, comp)) - avr_timer_reconfigure(timer, 0); - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM0, - _timer_get_ocr(timer, AVR_TIMER_COMPA)); - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM1, - _timer_get_ocr(timer, AVR_TIMER_COMPB)); - if (sizeof(timer->comp)>2) - avr_raise_irq(timer->io.irq + TIMER_IRQ_OUT_PWM2, - _timer_get_ocr(timer, AVR_TIMER_COMPC)); - break; - default: - AVR_LOG(avr, LOG_WARNING, "TIMER: %s-%c mode %d UNSUPPORTED\n", - __FUNCTION__, timer->name, timer->mode.kind); - avr_timer_reconfigure(timer, 0); - break; - } -} - -static void -avr_timer_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - - uint8_t as2 = avr_regbit_get(avr, p->as2); - uint8_t cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs)); - uint8_t mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)); - - avr_core_watch_write(avr, addr, v); - - uint8_t new_as2 = avr_regbit_get(avr, p->as2); - uint8_t new_cs = avr_regbit_get_array(avr, p->cs, ARRAY_SIZE(p->cs)); - uint8_t new_mode = avr_regbit_get_array(avr, p->wgm, ARRAY_SIZE(p->wgm)); - - // only reconfigure the timer if "relevant" bits have changed - // this prevent the timer reset when changing the edge detector - // or other minor bits - if (new_cs != cs || new_mode != mode || new_as2 != as2) { - /* cs */ - if (new_cs == 0) { - p->cs_div_value = 0; // reset prescaler - // cancel everything - avr_timer_cancel_all_cycle_timers(avr, p, 1); - - AVR_LOG(avr, LOG_TRACE, "TIMER: %s-%c clock turned off\n", - __func__, p->name); - return; - } - - p->ext_clock_flags &= ~(AVR_TIMER_EXTCLK_FLAG_TN | AVR_TIMER_EXTCLK_FLAG_EDGE - | AVR_TIMER_EXTCLK_FLAG_AS2 | AVR_TIMER_EXTCLK_FLAG_STARTED); - if (p->ext_clock_pin.reg - && (p->cs_div[new_cs] == AVR_TIMER_EXTCLK_CHOOSE)) { - // Special case: external clock source chosen, prescale divider irrelevant. - p->cs_div_value = 1; - p->ext_clock_flags |= AVR_TIMER_EXTCLK_FLAG_TN | (new_cs & AVR_TIMER_EXTCLK_FLAG_EDGE); - } else { - p->cs_div_value = 1 << p->cs_div[new_cs]; - if (new_as2) { - //p->cs_div_value = (uint32_t)((uint64_t)avr->frequency * (1 << p->cs_div[new_cs]) / 32768); - p->ext_clock_flags |= AVR_TIMER_EXTCLK_FLAG_AS2 | AVR_TIMER_EXTCLK_FLAG_EDGE; - } - } - - /* mode */ - p->mode = p->wgm_op[new_mode]; - p->wgm_op_mode_kind = p->mode.kind; - p->wgm_op_mode_size = (1 << p->mode.size) - 1; - - avr_timer_reconfigure(p, 1); - } -} - -/* - * write to the "force output compare" bits - */ -static void avr_timer_write_foc(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - - /* These are strobe writes, so just decode them, don't store them */ - - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if ((addr == p->comp[compi].foc.reg) && - (v & (1 << p->comp[compi].foc.bit))) { - avr_timer_comp(p, avr->cycle, compi, 0); - } - } -} - -/* - * write to the TIFR register. Watch for code that writes "1" to clear - * pending interrupts. - */ -static void -avr_timer_write_pending( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - - // All bits in this register are assumed to be write-1-to-clear. - - if (addr == p->overflow.raised.reg && - avr_regbit_from_value(avr, p->overflow.raised, v)) { - avr_clear_interrupt(avr, &p->overflow); - } - if (addr == p->icr.raised.reg && - avr_regbit_from_value(avr, p->icr.raised, v)) { - avr_clear_interrupt(avr, &p->icr); - } - - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - if (addr == p->comp[compi].interrupt.raised.reg && - avr_regbit_from_value(avr, p->comp[compi].interrupt.raised, - v)) { - avr_clear_interrupt(avr, &p->comp[compi].interrupt); - } - } -} - -static void -avr_timer_irq_icp( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_timer_t * p = (avr_timer_t *)param; - avr_t * avr = p->io.avr; - - // input capture disabled when ICR is used as top - if (p->mode.top == avr_timer_wgm_reg_icr) - return; - int bing = 0; - if (avr_regbit_get(avr, p->ices)) { // rising edge - if (!irq->value && value) - bing++; - } else { // default, falling edge - if (irq->value && !value) - bing++; - } - if (!bing) - return; - // get current TCNT, copy it to ICR, and raise interrupt - uint16_t tcnt = _avr_timer_get_current_tcnt(p); - avr->data[p->r_icr] = tcnt; - if (p->r_icrh) - avr->data[p->r_icrh] = tcnt >> 8; - avr_raise_interrupt(avr, &p->icr); -} - -static int -avr_timer_ioctl( - avr_io_t * port, - uint32_t ctl, - void * io_param) -{ - avr_timer_t * p = (avr_timer_t *)port; - int res = -1; - - if (ctl == AVR_IOCTL_TIMER_SET_TRACE(p->name)) { - /* Allow setting individual trace flags */ - p->trace = *((uint32_t*)io_param); - res = 0; - } else if (ctl == AVR_IOCTL_TIMER_SET_FREQCLK(p->name)) { - float new_freq = *((float*)io_param); - if (new_freq >= 0.0f) { - if (p->as2.reg) { - if (new_freq <= port->avr->frequency/4) { - p->ext_clock = new_freq; - res = 0; - } - } else if (p->ext_clock_pin.reg) { - if (new_freq <= port->avr->frequency/2) { - p->ext_clock = new_freq; - res = 0; - } - } - } - } else if (ctl == AVR_IOCTL_TIMER_SET_VIRTCLK(p->name)) { - uint8_t new_val = *((uint8_t*)io_param); - if (!new_val) { - avr_ioport_getirq_t req_timer_clock_pin = { - .bit = p->ext_clock_pin - }; - if (avr_ioctl(p->io.avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req_timer_clock_pin) > 0) { - p->ext_clock_flags &= ~AVR_TIMER_EXTCLK_FLAG_VIRT; - res = 0; - } - } else { - p->ext_clock_flags |= AVR_TIMER_EXTCLK_FLAG_VIRT; - res = 0; - } - } - if (res >= 0) - avr_timer_reconfigure(p, 0); // virtual clock: attempt to follow frequency change preserving the phase - return res; -} - -static void -avr_timer_reset( - avr_io_t * port) -{ - avr_timer_t * p = (avr_timer_t *)port; - avr_timer_cancel_all_cycle_timers(p->io.avr, p, 0); - - // check to see if the comparators have a pin output. If they do, - // (try) to get the ioport corresponding IRQ and connect them - // they will automagically be triggered when the comparator raises - // it's own IRQ - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - p->comp[compi].comp_cycles = 0; - - avr_ioport_getirq_t req = { - .bit = p->comp[compi].com_pin - }; - if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) { - // cool, got an IRQ - //printf("%s-%c COMP%c Connecting PIN IRQ %d\n", - // __func__, p->name, 'A'+compi, req.irq[0]->irq); - avr_connect_irq(&port->irq[TIMER_IRQ_OUT_COMP + compi], req.irq[0]); - } - } - - avr_irq_register_notify(port->irq + TIMER_IRQ_IN_ICP, avr_timer_irq_icp, p); - - avr_ioport_getirq_t req = { - .bit = p->icp - }; - if (avr_ioctl(port->avr, AVR_IOCTL_IOPORT_GETIRQ_REGBIT, &req) > 0) { - // cool, got an IRQ for the input capture pin - //printf("%s-%c ICP Connecting PIN IRQ %d\n", __func__, p->name, req.irq[0]->irq); - avr_connect_irq(req.irq[0], port->irq + TIMER_IRQ_IN_ICP); - } - p->ext_clock_flags &= ~(AVR_TIMER_EXTCLK_FLAG_STARTED | AVR_TIMER_EXTCLK_FLAG_TN | - AVR_TIMER_EXTCLK_FLAG_AS2 | AVR_TIMER_EXTCLK_FLAG_REVDIR); - -} - -static const char * irq_names[TIMER_IRQ_COUNT] = { - [TIMER_IRQ_OUT_PWM0] = "8>pwm0", - [TIMER_IRQ_OUT_PWM1] = "8>pwm1", - [TIMER_IRQ_OUT_PWM2] = "8>pwm2", - [TIMER_IRQ_IN_ICP] = "io = _io; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->overflow); - avr_register_vector(avr, &p->icr); - - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_TIMER_GETIRQ(p->name), TIMER_IRQ_COUNT, NULL); - - // marking IRQs as "filtered" means they don't propagate if the - // new value raised is the same as the last one.. in the case of the - // pwm value it makes sense not to bother. - p->io.irq[TIMER_IRQ_OUT_PWM0].flags |= IRQ_FLAG_FILTERED; - p->io.irq[TIMER_IRQ_OUT_PWM1].flags |= IRQ_FLAG_FILTERED; - p->io.irq[TIMER_IRQ_OUT_PWM2].flags |= IRQ_FLAG_FILTERED; - - if (p->wgm[0].reg) // these are not present on older AVRs - avr_register_io_write(avr, p->wgm[0].reg, avr_timer_write, p); - if (p->wgm[1].reg && - (p->wgm[1].reg != p->wgm[0].reg)) - avr_register_io_write(avr, p->wgm[1].reg, avr_timer_write, p); - if (p->wgm[2].reg && - (p->wgm[2].reg != p->wgm[0].reg) && - (p->wgm[2].reg != p->wgm[1].reg)) - avr_register_io_write(avr, p->wgm[2].reg, avr_timer_write, p); - if (p->wgm[3].reg && - (p->wgm[3].reg != p->wgm[0].reg) && - (p->wgm[3].reg != p->wgm[1].reg) && - (p->wgm[3].reg != p->wgm[2].reg)) - avr_register_io_write(avr, p->wgm[3].reg, avr_timer_write, p); - - avr_register_io_write(avr, p->cs[0].reg, avr_timer_write, p); - if (p->cs[1].reg && - (p->cs[1].reg != p->cs[0].reg)) - avr_register_io_write(avr, p->cs[1].reg, avr_timer_write, p); - if (p->cs[2].reg && - (p->cs[2].reg != p->cs[0].reg) && (p->cs[2].reg != p->cs[1].reg)) - avr_register_io_write(avr, p->cs[2].reg, avr_timer_write, p); - if (p->cs[3].reg && - (p->cs[3].reg != p->cs[0].reg) && - (p->cs[3].reg != p->cs[1].reg) && - (p->cs[3].reg != p->cs[2].reg)) - avr_register_io_write(avr, p->cs[3].reg, avr_timer_write, p); - - if (p->as2.reg) // as2 signifies timer/counter 2... therefore must check for register. - avr_register_io_write(avr, p->as2.reg, avr_timer_write, p); - - // this assumes all the "pending" interrupt bits are in the same - // register. Might not be true on all devices ? - avr_register_io_write(avr, p->overflow.raised.reg, avr_timer_write_pending, p); - - /* - * Even if the timer is 16 bits, we don't care to have watches on the - * high bytes because the datasheet says that the low address is always - * the trigger. - */ - for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) { - p->comp[compi].timer = p; - - avr_register_vector(avr, &p->comp[compi].interrupt); - - if (p->comp[compi].r_ocr) // not all timers have all comparators - avr_register_io_write(avr, p->comp[compi].r_ocr, avr_timer_write_ocr, &p->comp[compi]); - if (p->comp[compi].foc.reg) - avr_register_io_write(avr, p->comp[compi].foc.reg, avr_timer_write_foc, p); - } - avr_register_io_write(avr, p->r_tcnt, avr_timer_tcnt_write, p); - avr_register_io_read(avr, p->r_tcnt, avr_timer_tcnt_read, p); - - if (p->as2.reg) { - p->ext_clock_flags = AVR_TIMER_EXTCLK_FLAG_VIRT; - p->ext_clock = 32768.0f; - } else { - p->ext_clock_flags = 0; - p->ext_clock = 0.0f; - } -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.h deleted file mode 100644 index 837936c..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_timer.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - avr_timer.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_TIMER_H__ -#define __AVR_TIMER_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -enum { - AVR_TIMER_COMPA = 0, - AVR_TIMER_COMPB, - AVR_TIMER_COMPC, - - AVR_TIMER_COMP_COUNT -}; - -enum { - TIMER_IRQ_OUT_PWM0 = 0, - TIMER_IRQ_OUT_PWM1, - TIMER_IRQ_OUT_PWM2, - TIMER_IRQ_IN_ICP, // input capture - TIMER_IRQ_OUT_COMP, // comparator pins output IRQ - - TIMER_IRQ_COUNT = TIMER_IRQ_OUT_COMP + AVR_TIMER_COMP_COUNT -}; - -// Get the internal IRQ corresponding to the INT -#define AVR_IOCTL_TIMER_GETIRQ(_name) AVR_IOCTL_DEF('t','m','r',(_name)) - -// add timer number/name (character) to set tracing flags -#define AVR_IOCTL_TIMER_SET_TRACE(_number) AVR_IOCTL_DEF('t','m','t',(_number)) -// enforce using virtual clock generator when external clock is chosen by firmware -#define AVR_IOCTL_TIMER_SET_VIRTCLK(_number) AVR_IOCTL_DEF('t','m','v',(_number)) -// set frequency of the virtual clock generator -#define AVR_IOCTL_TIMER_SET_FREQCLK(_number) AVR_IOCTL_DEF('t','m','f',(_number)) - -// Waveform generation modes -enum { - avr_timer_wgm_none = 0, // invalid mode - avr_timer_wgm_normal, - avr_timer_wgm_ctc, - avr_timer_wgm_pwm, - avr_timer_wgm_fast_pwm, - avr_timer_wgm_fc_pwm, -}; - -// Compare output modes -enum { - avr_timer_com_normal = 0,// Normal mode, OCnx disconnected - avr_timer_com_toggle, // Toggle OCnx on compare match - avr_timer_com_clear, // clear OCnx on compare match - avr_timer_com_set, // set OCnx on compare match - -}; - -enum { - avr_timer_wgm_reg_constant = 0, - avr_timer_wgm_reg_ocra, - avr_timer_wgm_reg_icr, -}; - -typedef struct avr_timer_wgm_t { - uint32_t top: 8, bottom: 8, size : 8, kind : 8; -} avr_timer_wgm_t; - -#define AVR_TIMER_EXTCLK_CHOOSE 0x80 // marker value for cs_div specifying ext clock selection -#define AVR_TIMER_EXTCLK_FLAG_TN 0x80 // Tn external clock chosen -#define AVR_TIMER_EXTCLK_FLAG_STARTED 0x40 // peripheral started -#define AVR_TIMER_EXTCLK_FLAG_REVDIR 0x20 // reverse counting (decrement) -#define AVR_TIMER_EXTCLK_FLAG_AS2 0x10 // asynchronous external clock chosen -#define AVR_TIMER_EXTCLK_FLAG_VIRT 0x08 // don't use the input pin, generate clock internally -#define AVR_TIMER_EXTCLK_FLAG_EDGE 0x01 // use the rising edge - -#define AVR_TIMER_WGM_NORMAL8() { .kind = avr_timer_wgm_normal, .size=8 } -#define AVR_TIMER_WGM_NORMAL16() { .kind = avr_timer_wgm_normal, .size=16 } -#define AVR_TIMER_WGM_CTC() { .kind = avr_timer_wgm_ctc, .top = avr_timer_wgm_reg_ocra } -#define AVR_TIMER_WGM_ICCTC() { .kind = avr_timer_wgm_ctc, .top = avr_timer_wgm_reg_icr } -#define AVR_TIMER_WGM_FASTPWM8() { .kind = avr_timer_wgm_fast_pwm, .size=8 } -#define AVR_TIMER_WGM_FASTPWM9() { .kind = avr_timer_wgm_fast_pwm, .size=9 } -#define AVR_TIMER_WGM_FASTPWM10() { .kind = avr_timer_wgm_fast_pwm, .size=10 } -#define AVR_TIMER_WGM_FCPWM8() { .kind = avr_timer_wgm_fc_pwm, .size=8 } -#define AVR_TIMER_WGM_FCPWM9() { .kind = avr_timer_wgm_fc_pwm, .size=9 } -#define AVR_TIMER_WGM_FCPWM10() { .kind = avr_timer_wgm_fc_pwm, .size=10 } -#define AVR_TIMER_WGM_OCPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_ocra } -#define AVR_TIMER_WGM_ICPWM() { .kind = avr_timer_wgm_pwm, .top = avr_timer_wgm_reg_icr } -#define AVR_TIMER_WGM_ICFASTPWM() { .kind = avr_timer_wgm_fast_pwm, .top = avr_timer_wgm_reg_icr } - -typedef struct avr_timer_comp_t { - avr_int_vector_t interrupt; // interrupt vector - struct avr_timer_t *timer; // parent timer - avr_io_addr_t r_ocr; // comparator register low byte - avr_io_addr_t r_ocrh; // comparator register hi byte - avr_regbit_t com; // comparator output mode registers - avr_regbit_t com_pin; // where comparator output is connected - uint64_t comp_cycles; - avr_regbit_t foc; // "force compare match" strobe -} avr_timer_comp_t, *avr_timer_comp_p; - -enum { - avr_timer_trace_ocr = (1 << 0), - avr_timer_trace_tcnt = (1 << 1), - - avr_timer_trace_compa = (1 << 8), - avr_timer_trace_compb = (1 << 9), - avr_timer_trace_compc = (1 << 10), -}; - -typedef struct avr_timer_t { - avr_io_t io; - char name; - uint32_t trace; // debug trace - - avr_regbit_t disabled; // bit in the PRR - - avr_io_addr_t r_tcnt, r_icr; - avr_io_addr_t r_tcnth, r_icrh; - - avr_regbit_t wgm[4]; - avr_timer_wgm_t wgm_op[16]; - avr_timer_wgm_t mode; - int wgm_op_mode_kind; - uint32_t wgm_op_mode_size; - - avr_regbit_t as2; // asynchronous clock 32khz - avr_regbit_t cs[4]; // specify control register bits choosing clock sourcre - uint8_t cs_div[16]; // translate control register value to clock prescaler (orders of 2 exponent) - uint32_t cs_div_value; - - avr_regbit_t ext_clock_pin; // external clock input pin, to link IRQs - uint8_t ext_clock_flags; // holds AVR_TIMER_EXTCLK_FLAG_ON, AVR_TIMER_EXTCLK_FLAG_EDGE and other ext. clock mode flags - float ext_clock; // external clock frequency, e.g. 32768Hz - - avr_regbit_t icp; // input capture pin, to link IRQs - avr_regbit_t ices; // input capture edge select - - avr_timer_comp_t comp[AVR_TIMER_COMP_COUNT]; - - avr_int_vector_t overflow; // overflow - avr_int_vector_t icr; // input capture - - uint64_t tov_cycles; // number of cycles from zero to overflow - float tov_cycles_fract; // fractional part for external clock with non int ratio to F_CPU - float phase_accumulator; - uint64_t tov_base; // MCU cycle when the last overflow occured; when clocked externally holds external clock count - uint16_t tov_top; // current top value to calculate tnct -} avr_timer_t; - -void avr_timer_init(avr_t * avr, avr_timer_t * port); - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_TIMER_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.c deleted file mode 100644 index 521c03c..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.c +++ /dev/null @@ -1,521 +0,0 @@ -/* - avr_twi.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include "avr_twi.h" - -/* - * This block respectfully nicked straight out from the Atmel sample - * code for AVR315. Typos and all. - * There is no copyright notice on the original file. - */ -/**************************************************************************** - TWI State codes -****************************************************************************/ -// General TWI Master status codes -#define TWI_START 0x08 // START has been transmitted -#define TWI_REP_START 0x10 // Repeated START has been transmitted -#define TWI_ARB_LOST 0x38 // Arbitration lost - -// TWI Master Transmitter status codes -#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been transmitted and ACK received -#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been transmitted and NACK received -#define TWI_MTX_DATA_ACK 0x28 // Data byte has been transmitted and ACK received -#define TWI_MTX_DATA_NACK 0x30 // Data byte has been transmitted and NACK received - -// TWI Master Receiver status codes -#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been transmitted and ACK received -#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been transmitted and NACK received -#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK transmitted -#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK transmitted - -// TWI Slave Transmitter status codes -#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned -#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned -#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received -#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received -#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received - -// TWI Slave Receiver status codes -#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned -#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned -#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned -#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned -#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned -#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned -#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned -#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned -#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave - -// TWI Miscellaneous status codes -#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = �0� -#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition - -#define AVR_TWI_DEBUG 1 - -static inline void -_avr_twi_status_set( - avr_twi_t * p, - uint8_t v, - int interrupt) -{ - avr_regbit_setto_raw(p->io.avr, p->twsr, v); -#if AVR_TWI_DEBUG - AVR_TRACE(p->io.avr, "%s %02x\n", __func__, v); -#endif - avr_raise_irq(p->io.irq + TWI_IRQ_STATUS, v); - if (interrupt) - avr_raise_interrupt(p->io.avr, &p->twi); -} - -static __attribute__ ((unused)) inline uint8_t -_avr_twi_status_get( - avr_twi_t * p) -{ - return avr_regbit_get_raw(p->io.avr, p->twsr); -} - -static avr_cycle_count_t -avr_twi_set_state_timer( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - _avr_twi_status_set(p, p->next_twstate, 1); - p->next_twstate = 0; - return 0; -} - -// Quick exponent helper for integer values > 0. -static uint32_t _avr_twi_quick_exp(uint8_t base, uint8_t exp) -{ - uint32_t result = 1; - for (uint8_t i=exp; i>0; i--) - result *= base; - return result; -} - -/* - * This is supposed to trigger a timer whose duration is a multiple - * of 'twi' clock cycles, which should be derived from the prescaler - * (100khz, 400khz etc). - * Right now it cheats and uses one twi cycle == one usec. - */ - -static void -_avr_twi_delay_state( - avr_twi_t * p, - int twi_cycles, - uint8_t state) -{ - p->next_twstate = state; - uint8_t prescale = avr_regbit_get(p->io.avr, p->twps); - uint16_t bitrate = p->io.avr->data[p->r_twbr]; - uint32_t clockdiv = 16u+((bitrate<<1u)*_avr_twi_quick_exp(4,prescale)); - //One TWI cycle is "clockdiv" AVR Cycles. So we can wait in these directly. - // printf("Waiting %d cycles\n",clockdiv*twi_cycles); - avr_cycle_timer_register( - p->io.avr, twi_cycles*clockdiv, avr_twi_set_state_timer, p); -} - -static void -avr_twi_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - - uint8_t twen = avr_regbit_get(avr, p->twen); - uint8_t twsta = avr_regbit_get(avr, p->twsta); - uint8_t twsto = avr_regbit_get(avr, p->twsto); - uint8_t twint = avr_regbit_get(avr, p->twi.raised); - - avr_core_watch_write(avr, addr, v); -#if AVR_TWI_DEBUG - AVR_TRACE(avr, "%s %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", - __func__, v, - avr_regbit_get(avr, p->twsta), - avr_regbit_get(avr, p->twsto), - avr_regbit_get(avr, p->twea), - avr_regbit_get(avr, p->twi.raised), - avr_regbit_get_raw(p->io.avr, p->twsr), p->state); -#endif - if (twen != avr_regbit_get(avr, p->twen)) { - twen = !twen; - if (!twen) { // if we were running, now now are not - avr_regbit_clear(avr, p->twea); - avr_regbit_clear(avr, p->twsta); - avr_regbit_clear(avr, p->twsto); - avr_clear_interrupt(avr, &p->twi); - avr_core_watch_write(avr, p->r_twdr, 0xff); - _avr_twi_status_set(p, TWI_NO_STATE, 0); - p->state = 0; - p->peer_addr = 0; - } - AVR_TRACE(avr, "TWEN: %d\n", twen); - if (avr->data[p->r_twar]) { - AVR_TRACE(avr, "TWEN Slave: %02x&%02x\n", avr->data[p->r_twar] >> 1, avr->data[p->r_twamr] >> 1); - p->state |= TWI_COND_SLAVE; - } - } - if (!twen) - return; - - uint8_t cleared = avr_regbit_get(avr, p->twi.raised); - - /*int cleared = */ - avr_clear_interrupt_if(avr, &p->twi, twint); -// AVR_TRACE(avr, "cleared %d\n", cleared); - - if (!twsto && avr_regbit_get(avr, p->twsto)) { - // generate a stop condition -#if AVR_TWI_DEBUG - AVR_TRACE(avr, "<<<<< I2C stop\n"); -#endif - if (p->state) { // doing stuff - if (p->state & TWI_COND_START) { - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(TWI_COND_STOP, p->peer_addr, 1)); - } - } - /* clear stop condition regardless of status */ - avr_regbit_clear(avr, p->twsto); - _avr_twi_status_set(p, TWI_NO_STATE, 0); - p->state = 0; - } - if (!twsta && avr_regbit_get(avr, p->twsta)) { -#if AVR_TWI_DEBUG - AVR_TRACE(avr, ">>>>> I2C %sstart\n", p->state & TWI_COND_START ? "RE" : ""); -#endif - // generate a start condition - if (p->state & TWI_COND_START) - _avr_twi_delay_state(p, 0, TWI_REP_START); - else - _avr_twi_delay_state(p, 0, TWI_START); - p->peer_addr = 0; - p->state = TWI_COND_START; - } - - int data = cleared && - !avr_regbit_get(avr, p->twsta) && - !avr_regbit_get(avr, p->twsto); - - if (!data) - return; - - int do_read = p->peer_addr & 1; - int do_ack = avr_regbit_get(avr, p->twea) != 0; - - if (p->state & TWI_COND_SLAVE) { - // writing or reading a byte - if (p->state & TWI_COND_ADDR) { -#if AVR_TWI_DEBUG - if (do_read) - AVR_TRACE(avr, "I2C slave READ byte\n"); - else - AVR_TRACE(avr, "I2C slave WRITE byte\n"); -#endif - if (do_read) { - if (p->state & TWI_COND_WRITE) { - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(TWI_COND_READ | TWI_COND_ACK, p->peer_addr, avr->data[p->r_twdr])); - } -#if AVR_TWI_DEBUG - else - AVR_TRACE(avr, "I2C latch is not ready, do nothing\n"); -#endif - } else { - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(TWI_COND_ACK, p->peer_addr, 0)); - } - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(TWI_COND_ADDR + (do_ack ? TWI_COND_ACK : 0), p->peer_addr, avr->data[p->r_twdr])); - } else { // address, acknowledge it - p->state |= TWI_COND_ADDR; - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg( - TWI_COND_ADDR | - (do_ack ? TWI_COND_ACK : 0) | - (p->state & TWI_COND_WRITE ? TWI_COND_READ : 0), - p->peer_addr, avr->data[p->r_twdr])); - } - } else { - - // writing or reading a byte - if (p->state & TWI_COND_ADDR) { -#if AVR_TWI_DEBUG - if (do_read) - AVR_TRACE(avr, "I2C READ byte from %02x\n", p->peer_addr); - else - AVR_TRACE(avr, "I2C WRITE byte %02x to %02x\n", avr->data[p->r_twdr], p->peer_addr); -#endif - // a normal data byte - uint8_t msgv = do_read ? TWI_COND_READ : TWI_COND_WRITE; - - if (do_ack) - msgv |= TWI_COND_ACK; - - p->state &= ~TWI_COND_ACK; // clear ACK bit - - AVR_TRACE(avr, "state %02x want %02x\n", p->state, msgv); - // if the latch is ready... as set by writing/reading the TWDR - if (p->state & msgv) { - - // we send an IRQ and we /expect/ a slave to reply - // immediately via an IRQ to set the COND_ACK bit - // otherwise it's assumed it's been nacked... - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(msgv, p->peer_addr, avr->data[p->r_twdr])); - - if (do_read) { // read ? - _avr_twi_delay_state(p, 9, - msgv & TWI_COND_ACK ? - TWI_MRX_DATA_ACK : TWI_MRX_DATA_NACK); - } else { - _avr_twi_delay_state(p, 9, - p->state & TWI_COND_ACK ? - TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK); - } - } -#if AVR_TWI_DEBUG - else - AVR_TRACE(avr, "I2C latch is not ready, do nothing\n"); -#endif - } else if (p->state) { -#if AVR_TWI_DEBUG - AVR_TRACE(avr, "I2C Master address %02x\n", avr->data[p->r_twdr]); -#endif - // send the address - p->state |= TWI_COND_ADDR; - p->peer_addr = avr->data[p->r_twdr]; - p->state &= ~TWI_COND_ACK; // clear ACK bit - - // we send an IRQ and we /expect/ a slave to reply - // immediately via an IRQ tp set the COND_ACK bit - // otherwise it's assumed it's been nacked... - avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, - avr_twi_irq_msg(TWI_COND_START, p->peer_addr, 0)); - - if (p->peer_addr & 1) { // read ? - p->state |= TWI_COND_READ; // always allow read to start with - _avr_twi_delay_state(p, 9, - p->state & TWI_COND_ACK ? - TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK); - } else { - if(p->state & TWI_COND_ADDR){ - _avr_twi_delay_state(p, 0, - p->state & TWI_COND_ACK ? - TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK); - }else{ - _avr_twi_delay_state(p, 9, - p->state & TWI_COND_ACK ? - TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK); - } - } - } - p->state &= ~TWI_COND_WRITE; - } -} - -/* - * Write data to the latch, tell the system we have something - * to send next - */ -static void -avr_twi_write_data( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - - avr_core_watch_write(avr, addr, v); - // tell system we have something in the write latch - p->state |= TWI_COND_WRITE; -} - -/* - * Read data from the latch, tell the system can receive a new byte - */ -static uint8_t -avr_twi_read_data( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - - // tell system we can receive another byte - p->state |= TWI_COND_READ; - return avr->data[p->r_twdr]; -} - -/* - * prevent code from rewriting out status bits, since we actually use them! - */ -static void -avr_twi_write_status( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - uint8_t sr = avr_regbit_get(avr, p->twsr); - uint8_t c = avr_regbit_get(avr, p->twps); - - avr_core_watch_write(avr, addr, v); - avr_regbit_setto(avr, p->twsr, sr); // force restore - - if (c != avr_regbit_get(avr, p->twps)) { - // prescaler bits changed... - } -} - -static void -avr_twi_irq_input( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_twi_t * p = (avr_twi_t *)param; - avr_t * avr = p->io.avr; - - // check to see if we are enabled - if (!avr_regbit_get(avr, p->twen)) - return; - avr_twi_msg_irq_t msg; - msg.u.v = value; - - AVR_TRACE(avr, "%s %08x\n", __func__, value); - - // receiving an attempt at waking a slave - if (msg.u.twi.msg & TWI_COND_START) { - p->state = 0; - p->peer_addr = 0; - if (msg.u.twi.msg & TWI_COND_ADDR) { - uint8_t mask = ~avr->data[p->r_twamr] >> 1; - AVR_TRACE(avr, "I2C slave start %2x (want %02x&%02x)\n", - msg.u.twi.addr, avr->data[p->r_twar] >> 1, mask); - p->peer_addr = msg.u.twi.addr & mask; - if (p->peer_addr == ((avr->data[p->r_twar] >> 1) & mask)) { - // address match, we're talking - p->state = TWI_COND_SLAVE; - // INVERSE logic here - if (!(msg.u.twi.msg & TWI_COND_WRITE)) - p->peer_addr |= 1; - _avr_twi_delay_state(p, 9, - msg.u.twi.msg & TWI_COND_WRITE ? - TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK ); - } - } else { - // "general call" address - AVR_TRACE(avr, "I2C slave start without address?\n"); - if (avr->data[p->r_twar] & 1) { - // TODO - } - } - } - if (msg.u.twi.msg & TWI_COND_STOP) { - _avr_twi_delay_state(p, 9, - msg.u.twi.msg & TWI_COND_WRITE ? - TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK ); - } - // receiving an acknowledge bit - if (msg.u.twi.msg & TWI_COND_ACK) { -#if AVR_TWI_DEBUG - AVR_TRACE(avr, "I2C received ACK:%d\n", msg.u.twi.data & 1); -#endif - if (msg.u.twi.data & 1) - p->state |= TWI_COND_ACK; - else - p->state &= ~TWI_COND_ACK; - } - if (p->state & TWI_COND_SLAVE) { - if (msg.u.twi.msg & TWI_COND_WRITE) { - avr->data[p->r_twdr] = msg.u.twi.data; - _avr_twi_delay_state(p, 9, TWI_SRX_ADR_DATA_ACK ); - } - } else { - // receive a data byte from a slave - if (msg.u.twi.msg & TWI_COND_READ) { -#if AVR_TWI_DEBUG - AVR_TRACE(avr, "I2C received %02x\n", msg.u.twi.data); -#endif - avr->data[p->r_twdr] = msg.u.twi.data; - } - } -} - -void avr_twi_reset(struct avr_io_t *io) -{ - avr_twi_t * p = (avr_twi_t *)io; - avr_irq_register_notify(p->io.irq + TWI_IRQ_INPUT, avr_twi_irq_input, p); - p->state = p->peer_addr = 0; - avr_regbit_setto_raw(p->io.avr, p->twsr, TWI_NO_STATE); -} - -static const char * irq_names[TWI_IRQ_COUNT] = { - [TWI_IRQ_INPUT] = "8io = _io; - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->twi); - - //printf("%s TWI%c init\n", __FUNCTION__, p->name); - - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_TWI_GETIRQ(p->name), TWI_IRQ_COUNT, NULL); - - avr_register_io_write(avr, p->twen.reg, avr_twi_write, p); - avr_register_io_write(avr, p->r_twdr, avr_twi_write_data, p); - avr_register_io_read(avr, p->r_twdr, avr_twi_read_data, p); - avr_register_io_write(avr, p->twsr.reg, avr_twi_write_status, p); -} - -uint32_t -avr_twi_irq_msg( - uint8_t msg, - uint8_t addr, - uint8_t data) -{ - avr_twi_msg_irq_t _msg = { - .u.twi.msg = msg, - .u.twi.addr = addr, - .u.twi.data = data, - }; - return _msg.u.v; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.h deleted file mode 100644 index 8b37ba3..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_twi.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - avr_twi.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_TWI_H__ -#define __AVR_TWI_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -//#include "sim_twi.h" - -enum { - TWI_IRQ_INPUT = 0, - TWI_IRQ_OUTPUT, - TWI_IRQ_STATUS, - TWI_IRQ_COUNT -}; - -enum { - TWI_COND_START = (1 << 0), - TWI_COND_STOP = (1 << 1), - TWI_COND_ADDR = (1 << 2), - TWI_COND_ACK = (1 << 3), - TWI_COND_WRITE = (1 << 4), - TWI_COND_READ = (1 << 5), - // internal state, do not use in irq messages - TWI_COND_SLAVE = (1 << 6), -}; - -typedef struct avr_twi_msg_t { - uint32_t unused : 8, - msg : 8, - addr : 8, - data : 8; -} avr_twi_msg_t; - -typedef struct avr_twi_msg_irq_t { - union { - uint32_t v; - avr_twi_msg_t twi; - } u; -} avr_twi_msg_irq_t; - -// add port number to get the real IRQ -#define AVR_IOCTL_TWI_GETIRQ(_name) AVR_IOCTL_DEF('t','w','i',(_name)) - -typedef struct avr_twi_t { - avr_io_t io; - char name; - - avr_regbit_t disabled; // bit in the PRR - - avr_io_addr_t r_twbr; // bit rate register - avr_io_addr_t r_twcr; // control register - avr_io_addr_t r_twsr; // status register - avr_io_addr_t r_twar; // address register (slave) - avr_io_addr_t r_twamr; // address mask register - avr_io_addr_t r_twdr; // data register - - avr_regbit_t twen; // twi enable bit - avr_regbit_t twea; // enable acknowledge bit - avr_regbit_t twsta; // start condition - avr_regbit_t twsto; // stop condition - avr_regbit_t twwc; // write collision - - avr_regbit_t twsr; // status registers, (5 bits) - avr_regbit_t twps; // prescaler bits (2 bits) - - avr_int_vector_t twi; // twi interrupt - - uint8_t state; - uint8_t peer_addr; - uint8_t next_twstate; -} avr_twi_t; - -void -avr_twi_init( - avr_t * avr, - avr_twi_t * port); - -/* - * Create a message value for twi including the 'msg' bitfield, - * 'addr' and data. This value is what is sent as the IRQ value - */ -uint32_t -avr_twi_irq_msg( - uint8_t msg, - uint8_t addr, - uint8_t data); - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_TWI_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.c deleted file mode 100644 index 25b6fe6..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - avr_uart.c - - Handles UART access - Right now just handle "write" to the serial port at any speed - and printf to the console when '\n' is written. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifdef NO_COLOR - #define FONT_GREEN - #define FONT_DEFAULT -#else - #define FONT_GREEN "\e[32m" - #define FONT_DEFAULT "\e[0m" -#endif - -#include -#include -#include -#include -#include "avr_uart.h" -#include "sim_hex.h" -#include "sim_time.h" -#include "sim_gdb.h" - -//#define TRACE(_w) _w -#ifndef TRACE -#define TRACE(_w) -#endif - -DEFINE_FIFO(uint16_t, uart_fifo); - -static inline void -avr_uart_clear_interrupt( - avr_t * avr, - avr_int_vector_t * vector) -{ - if (!vector->vector) - return; - // clear the interrupt flag even it's 'sticky' - if (avr_regbit_get(avr, vector->raised)) - avr_clear_interrupt_if(avr, vector, 0); - if (avr_regbit_get(avr, vector->raised)) - avr_regbit_clear(avr, vector->raised); -} - -static avr_cycle_count_t -avr_uart_txc_raise( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - if (p->tx_cnt) { - // Even if the interrupt is disabled, still raise the TXC flag - if (p->tx_cnt == 1) - avr_raise_interrupt(avr, &p->txc); - p->tx_cnt--; - } - if (p->udrc.vector) {// UDRE is disabled in the LIN mode - if (p->tx_cnt) { - if (avr_regbit_get(avr, p->udrc.raised)) { - avr_uart_clear_interrupt(avr, &p->udrc); - } - } else { - if (avr_regbit_get(avr, p->txen)) { - // Even if the interrupt is disabled, still raise the UDRE flag - avr_raise_interrupt(avr, &p->udrc); - if (!avr_regbit_get(avr, p->udrc.enable)) { - return 0; //polling mode: stop TX pump - } else // udrc (alias udre) should be rased repeatedly while output buffer is empty - return when + p->cycles_per_byte; - } else - return 0; // transfer disabled: stop TX pump - } - } - if (p->tx_cnt) - return when + p->cycles_per_byte; - return 0; // stop TX pump -} - -static avr_cycle_count_t -avr_uart_rxc_raise( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - if (avr_regbit_get(avr, p->rxen)) { - // rxc should be rased continiosly untill input buffer is empty - if (!uart_fifo_isempty(&p->input)) { - if (!avr_regbit_get(avr, p->rxc.raised)) { - p->rxc_raise_time = when; - p->rx_cnt = 0; - } - avr_raise_interrupt(avr, &p->rxc); - return when + p->cycles_per_byte; - } - } - return 0; -} - -static uint8_t -avr_uart_status_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - - if (addr == p->fe.reg) { - if (!uart_fifo_isempty(&p->input)) { - uint16_t d = uart_fifo_read_at(&p->input, 0); - - uint8_t st = avr->data[addr]; - - st &= ~(p->fe.mask << p->fe.bit); - if (d & UART_INPUT_FE) { - st |= p->fe.mask << p->fe.bit; - } - - avr->data[addr] = st; - } - } - - uint8_t v = avr_core_watch_read(avr, addr); - - if (addr == p->rxc.raised.reg) { - //static uint8_t old = 0xff; if (v != old) printf("UCSRA read %02x\n", v); old = v; - // - // if RX is enabled, and there is nothing to read, and - // the AVR core is reading this register, it's probably - // to poll the RXC TXC flag and spinloop - // so here we introduce a usleep to make it a bit lighter - // on CPU and let data arrive - // - uint8_t ri = !avr_regbit_get(avr, p->rxen) || !avr_regbit_get(avr, p->rxc.raised); - uint8_t ti = !avr_regbit_get(avr, p->txen) || !avr_regbit_get(avr, p->txc.raised); - - if (p->flags & AVR_UART_FLAG_POLL_SLEEP) { - - if (ri && ti) - usleep(1); - } - // if reception is idle and the fifo is empty, tell whomever there is room - if (avr_regbit_get(avr, p->rxen) && uart_fifo_isempty(&p->input)) { - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0); - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1); - } - } - - return v; -} - -static uint8_t -avr_uart_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - uint8_t v = 0; - - if (!avr_regbit_get(avr, p->rxen) || - !avr_regbit_get(avr, p->rxc.raised) // rxc flag not raised - nothing to read! - ) { - AVR_LOG(avr, LOG_TRACE, "UART%c: attempt to read empty rx buffer\n", p->name); - avr->data[addr] = 0; - // made to trigger potential watchpoints - avr_core_watch_read(avr, addr); - //return 0; - goto avr_uart_read_check; - } - if (!uart_fifo_isempty(&p->input)) { // probably redundant check - v = (uint8_t)uart_fifo_read(&p->input) & 0xFF; - p->rx_cnt++; - if ((p->rx_cnt > 1) && // UART actually has 2-character rx buffer - ((avr->cycle-p->rxc_raise_time)/p->rx_cnt < p->cycles_per_byte)) { - // prevent the firmware from reading input characters with non-realistic high speed - avr_uart_clear_interrupt(avr, &p->rxc); - p->rx_cnt = 0; - } - } else { - AVR_LOG(avr, LOG_TRACE, "UART%c: BUG: rxc raised with empty rx buffer\n", p->name); - } - -// TRACE(printf("UART read %02x %s\n", v, uart_fifo_isempty(&p->input) ? "EMPTY!" : "");) - avr->data[addr] = v; - // made to trigger potential watchpoints - v = avr_core_watch_read(avr, addr); - -avr_uart_read_check: - if (uart_fifo_isempty(&p->input)) { - avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); - avr_uart_clear_interrupt(avr, &p->rxc); - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0); - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1); - } - if (!uart_fifo_isfull(&p->input)) { - avr_regbit_clear(avr, p->dor); - } - - return v; -} - -static void -avr_uart_baud_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - avr_core_watch_write(avr, addr, v); - uint32_t val = avr_regbit_get(avr,p->ubrrl) | (avr_regbit_get(avr,p->ubrrh) << 8); - - const int databits[] = { 5,6,7,8, /* 'reserved', assume 8 */8,8,8, 9 }; - int db = databits[avr_regbit_get(avr, p->ucsz) | (avr_regbit_get(avr, p->ucsz2) << 2)]; - int sb = 1 + avr_regbit_get(avr, p->usbs); - int word_size = 1 /* start */ + db /* data bits */ + 1 /* parity */ + sb /* stops */; - int cycles_per_bit = (val+1)*8; - if (!avr_regbit_get(avr, p->u2x)) - cycles_per_bit *= 2; - double baud = ((double)avr->frequency) / cycles_per_bit; // can be less than 1 - p->cycles_per_byte = cycles_per_bit * word_size; - - AVR_LOG(avr, LOG_TRACE, "UART: %c configured to %04x = %.4f bps (x%d), %d data %d stop\n", - p->name, val, baud, avr_regbit_get(avr, p->u2x)?2:1, db, sb); - AVR_LOG(avr, LOG_TRACE, "UART: Roughly %d usec per byte\n", - avr_cycles_to_usec(avr, p->cycles_per_byte)); -} - -static void -avr_uart_udr_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - - // The byte to be sent should NOT be written there, - // the value written could never be read back. - //avr_core_watch_write(avr, addr, v); - if (avr->gdb) { - avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_WRITE); - } - - //avr_cycle_timer_cancel(avr, avr_uart_txc_raise, p); // synchronize tx pump - if (p->udrc.vector && avr_regbit_get(avr, p->udrc.raised)) { - avr_uart_clear_interrupt(avr, &p->udrc); - } - - if (p->flags & AVR_UART_FLAG_STDIO) { - const int maxsize = 256; - if (!p->stdio_out) - p->stdio_out = malloc(maxsize); - p->stdio_out[p->stdio_len++] = v < ' ' ? '.' : v; - p->stdio_out[p->stdio_len] = 0; - if (v == '\n' || p->stdio_len == maxsize) { - p->stdio_len = 0; - AVR_LOG(avr, LOG_OUTPUT, - FONT_GREEN "%s\n" FONT_DEFAULT, p->stdio_out); - } - } - TRACE(printf("UDR%c(%02x) = %02x\n", p->name, addr, v);) - // tell other modules we are "outputting" a byte - if (avr_regbit_get(avr, p->txen)) { - avr_raise_irq(p->io.irq + UART_IRQ_OUTPUT, v); - p->tx_cnt++; - if (p->tx_cnt > 2) // AVR actually has 1-character UART tx buffer, plus shift register - AVR_LOG(avr, LOG_TRACE, - "UART%c: tx buffer overflow %d\n", - p->name, (int)p->tx_cnt); - if (avr_cycle_timer_status(avr, avr_uart_txc_raise, p) == 0) - avr_cycle_timer_register(avr, p->cycles_per_byte, - avr_uart_txc_raise, p); // start the tx pump - } -} - - -static void -avr_uart_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - - uint8_t masked_v = v; - uint8_t clear_txc = 0; - uint8_t clear_rxc = 0; - - // exclude these locations from direct write: - if (p->udrc.raised.reg == addr) { - masked_v &= ~(p->udrc.raised.mask << p->udrc.raised.bit); - masked_v |= avr_regbit_get_raw(avr, p->udrc.raised); - } - if (p->txc.raised.reg == addr) { - uint8_t mask = p->txc.raised.mask << p->txc.raised.bit; - masked_v &= ~(mask); - masked_v |= avr_regbit_get_raw(avr, p->txc.raised); - // it can be cleared by writing a one to its bit location - if (v & mask) - clear_txc = 1; - } - if (p->rxc.raised.reg == addr) { - uint8_t mask = p->rxc.raised.mask << p->rxc.raised.bit; - masked_v &= ~(mask); - masked_v |= avr_regbit_get_raw(avr, p->rxc.raised); - if (!p->udrc.vector) { - // In the LIN mode it can be cleared by writing a one to its bit location - if (v & mask) - clear_rxc = 1; - } - } - // mainly to prevent application to confuse itself - // by writing something there and reading it back: - if (p->fe.reg == addr) { - masked_v &= ~(p->fe.mask << p->fe.bit); - masked_v |= avr_regbit_get_raw(avr, p->fe); - } - if (p->dor.reg == addr) { - masked_v &= ~(p->dor.mask << p->dor.bit); - //masked_v |= avr_regbit_get_raw(avr, p->dor); - } - if (p->upe.reg == addr) { - masked_v &= ~(p->upe.mask << p->upe.bit); - masked_v |= avr_regbit_get_raw(avr, p->upe); - } - if (p->rxb8.reg == addr) { - masked_v &= ~(p->rxb8.mask << p->rxb8.bit); - masked_v |= avr_regbit_get_raw(avr, p->rxb8); - } - - uint8_t txen = avr_regbit_get(avr, p->txen); - uint8_t rxen = avr_regbit_get(avr, p->rxen); - uint8_t udrce = avr_regbit_get(avr, p->udrc.enable); - // Now write whatever bits could be writen directly. - // It is necessary anyway, to trigger potential watchpoints. - avr_core_watch_write(avr, addr, masked_v); - uint8_t new_txen = avr_regbit_get(avr, p->txen); - uint8_t new_rxen = avr_regbit_get(avr, p->rxen); - uint8_t new_udrce = avr_regbit_get(avr, p->udrc.enable); - if (p->udrc.vector && (!udrce && new_udrce) && new_txen) { - // If enabling the UDRC (alias is UDRE) interrupt, raise it immediately if FIFO is empty. - // If the FIFO is not empty (clear timer is flying) we don't - // need to raise the interrupt, it will happen when the timer - // is fired. - if (avr_cycle_timer_status(avr, avr_uart_txc_raise, p) == 0) - avr_raise_interrupt(avr, &p->udrc); - } - if (clear_txc) - avr_uart_clear_interrupt(avr, &p->txc); - if (clear_rxc) - avr_uart_clear_interrupt(avr, &p->rxc); - - ///TODO: handle the RxD & TxD pins function override - - if (new_rxen != rxen) { - if (new_rxen) { - if (uart_fifo_isempty(&p->input)) { - // if reception is enabled and the fifo is empty, tell whomever there is room - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 0); - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XON, 1); - } - } else { - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 1); - avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); - // flush the Receive Buffer - uart_fifo_reset(&p->input); - // clear the rxc interrupt flag - avr_uart_clear_interrupt(avr, &p->rxc); - } - } - if (new_txen != txen) { - if (p->udrc.vector && !new_txen) { - avr_uart_clear_interrupt(avr, &p->udrc); - } else { - avr_regbit_set(avr, p->udrc.raised); - } - } -} - -static void -avr_uart_irq_input( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_uart_t * p = (avr_uart_t *)param; - avr_t * avr = p->io.avr; - - // check to see if receiver is enabled - if (!avr_regbit_get(avr, p->rxen)) - return; - - // reserved/not implemented: - //avr_regbit_clear(avr, p->fe); - //avr_regbit_clear(avr, p->upe); - //avr_regbit_clear(avr, p->rxb8); - - if (uart_fifo_isempty(&p->input) && - (avr_cycle_timer_status(avr, avr_uart_rxc_raise, p) == 0) - ) { - avr_cycle_timer_register(avr, p->cycles_per_byte, avr_uart_rxc_raise, p); // start the rx pump - p->rx_cnt = 0; - avr_regbit_clear(avr, p->dor); - } else if (uart_fifo_isfull(&p->input)) { - avr_regbit_setto(avr, p->dor, 1); - } - if (!avr_regbit_get(avr, p->dor)) { // otherwise newly received character must be rejected - uart_fifo_write(&p->input, value); // add to fifo - } else { - AVR_LOG(avr, LOG_ERROR, "UART%c: %s: RX buffer overrun, lost char=%c=0x%02X\n", p->name, __func__, - (char)value, (uint8_t)value ); - } - - TRACE(printf("UART IRQ in %02x (%d/%d) %s\n", value, p->input.read, p->input.write, uart_fifo_isfull(&p->input) ? "FULL!!" : "");) - - if (uart_fifo_isfull(&p->input)) - avr_raise_irq(p->io.irq + UART_IRQ_OUT_XOFF, 1); -} - - -void -avr_uart_reset( - struct avr_io_t *io) -{ - avr_uart_t * p = (avr_uart_t *)io; - avr_t * avr = p->io.avr; - if (p->udrc.vector) { - avr_regbit_set(avr, p->udrc.raised); - avr_regbit_clear(avr, p->dor); - } - avr_uart_clear_interrupt(avr, &p->txc); - avr_uart_clear_interrupt(avr, &p->rxc); - avr_irq_register_notify(p->io.irq + UART_IRQ_INPUT, avr_uart_irq_input, p); - avr_cycle_timer_cancel(avr, avr_uart_rxc_raise, p); - avr_cycle_timer_cancel(avr, avr_uart_txc_raise, p); - uart_fifo_reset(&p->input); - p->tx_cnt = 0; - - avr_regbit_set(avr, p->ucsz); - avr_regbit_clear(avr, p->ucsz2); - - // DEBUG allow printf without fiddling with enabling the uart - avr_regbit_set(avr, p->txen); - p->cycles_per_byte = avr_usec_to_cycles(avr, 100); -} - -static int -avr_uart_ioctl( - struct avr_io_t * port, - uint32_t ctl, - void * io_param) -{ - avr_uart_t * p = (avr_uart_t *)port; - int res = -1; - - if (!io_param) - return res; - - if (ctl == AVR_IOCTL_UART_SET_FLAGS(p->name)) { - p->flags = *(uint32_t*)io_param; - res = 0; - } - if (ctl == AVR_IOCTL_UART_GET_FLAGS(p->name)) { - *(uint32_t*)io_param = p->flags; - res = 0; - } - - return res; -} - -static const char * irq_names[UART_IRQ_COUNT] = { - [UART_IRQ_INPUT] = "8io = _io; - -// printf("%s UART%c UDR=%02x\n", __FUNCTION__, p->name, p->r_udr); - - p->flags = AVR_UART_FLAG_POLL_SLEEP|AVR_UART_FLAG_STDIO; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->rxc); - avr_register_vector(avr, &p->txc); - avr_register_vector(avr, &p->udrc); - - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_UART_GETIRQ(p->name), UART_IRQ_COUNT, NULL); - // Only call callbacks when the value change... - p->io.irq[UART_IRQ_OUT_XOFF].flags |= IRQ_FLAG_FILTERED; - - avr_register_io_write(avr, p->r_udr, avr_uart_udr_write, p); - avr_register_io_read(avr, p->r_udr, avr_uart_read, p); - - // status bits - // monitor code that reads the rxc flag, and delay it a bit - avr_register_io_read(avr, p->rxc.raised.reg, avr_uart_status_read, p); - if (p->fe.reg != p->rxc.raised.reg) - avr_register_io_read(avr, p->fe.reg, avr_uart_status_read, p); - - if (p->udrc.vector) - avr_register_io_write(avr, p->udrc.enable.reg, avr_uart_write, p); - if (p->r_ucsra) - avr_register_io_write(avr, p->r_ucsra, avr_uart_write, p); - if (p->ubrrl.reg) - avr_register_io_write(avr, p->ubrrl.reg, avr_uart_baud_write, p); - avr_register_io_write(avr, p->rxen.reg, avr_uart_write, p); -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.h deleted file mode 100644 index 107359e..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_uart.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - avr_uart.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_UART_H__ -#define __AVR_UART_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -#include "fifo_declare.h" - -DECLARE_FIFO(uint16_t, uart_fifo, 64); - -/* - * The method of "connecting" the the UART from external code is to use 4 IRQS. - * The easy one is UART->YOU, where you will be called with the byte every time - * the AVR firmware sends one. Do whatever you like with it. - * - * The slightly more tricky one is the INPUT part. Since the AVR is quite a bit - * slower than your code most likely, there is a way for the AVR UART to tell - * you to "pause" sending it bytes when its own input buffer is full. - * So, the UART will send XON to you when its fifo is empty, XON means you can - * send as many bytes as you have until XOFF is sent. Note that these are two - * IRQs because you /will/ be called with XOFF when sending a byte in INPUT... - * So it's a reentrant process. - * - * When XOFF has been called, do not send any new bytes, they would be dropped. - * Instead wait for XON again and continue. - * See examples/parts/uart_udp.c for a full implementation - * - * Pseudo code: - * - * volatile int off = 0; - * void irq_xon() - * { - * off = 0; - * while (!off && bytes_left) - * avr_raise_irq(UART_IRQ_INPUT, a_byte); - * } - * void irq_xoff() - * { - * off = 1; - * } - * - */ -enum { - UART_IRQ_INPUT = 0, - UART_IRQ_OUTPUT, - UART_IRQ_OUT_XON, // signaled (continuously) when input fifo is not full - UART_IRQ_OUT_XOFF, // signaled when input fifo IS full - UART_IRQ_COUNT -}; - -enum { - UART_INPUT_FE = 0x8000 // framing error -}; - -// add port number to get the real IRQ -#define AVR_IOCTL_UART_GETIRQ(_name) AVR_IOCTL_DEF('u','a','r',(_name)) - -enum { - // the uart code monitors for firmware that poll on - // reception registers, and can do an atomic usleep() - // if it's detected, this helps regulating CPU - AVR_UART_FLAG_POOL_SLEEP = (1 << 0), - AVR_UART_FLAG_POLL_SLEEP = (1 << 0), // to replace pool_sleep - AVR_UART_FLAG_STDIO = (1 << 1), // print lines on the console -}; - -typedef struct avr_uart_t { - avr_io_t io; - char name; - avr_regbit_t disabled; // bit in the PRR - - avr_io_addr_t r_udr; - avr_io_addr_t r_ucsra; - avr_io_addr_t r_ucsrb; - avr_io_addr_t r_ucsrc; - - avr_regbit_t rxen; // receive enabled - avr_regbit_t txen; // transmit enable - avr_regbit_t u2x; // double UART speed - avr_regbit_t usbs; // stop bits - avr_regbit_t ucsz; // data bits - avr_regbit_t ucsz2; // data bits, continued - - // read-only bits (just to mask it out) - avr_regbit_t fe; // frame error bit - avr_regbit_t dor; // data overrun bit - avr_regbit_t upe; // parity error bit - avr_regbit_t rxb8; // receive data bit 8 - - avr_regbit_t ubrrl; - avr_regbit_t ubrrh; - - avr_int_vector_t rxc; - avr_int_vector_t txc; - avr_int_vector_t udrc; - - uart_fifo_t input; - uint8_t tx_cnt; // number of unsent characters in the output buffer - uint32_t rx_cnt; // number of characters read by app since rxc_raise_time - - uint32_t flags; - avr_cycle_count_t cycles_per_byte; - avr_cycle_count_t rxc_raise_time; // the cpu cycle when rxc flag was raised last time - - uint8_t * stdio_out; - int stdio_len; // current size in the stdio output -} avr_uart_t; - -/* takes a uint32_t* as parameter */ -#define AVR_IOCTL_UART_SET_FLAGS(_name) AVR_IOCTL_DEF('u','a','s',(_name)) -#define AVR_IOCTL_UART_GET_FLAGS(_name) AVR_IOCTL_DEF('u','a','g',(_name)) - -void avr_uart_init(avr_t * avr, avr_uart_t * port); - -#define AVR_UARTX_DECLARE(_name, _prr, _prusart) \ - .uart ## _name = { \ - .name = '0' + _name, \ - .disabled = AVR_IO_REGBIT(_prr, _prusart), \ - \ - .r_udr = UDR ## _name, \ - \ - .fe = AVR_IO_REGBIT(UCSR ## _name ## A, FE ## _name), \ - .dor = AVR_IO_REGBIT(UCSR ## _name ## A, DOR ## _name), \ - .upe = AVR_IO_REGBIT(UCSR ## _name ## A, UPE ## _name), \ - .u2x = AVR_IO_REGBIT(UCSR ## _name ## A, U2X ## _name), \ - .txen = AVR_IO_REGBIT(UCSR ## _name ## B, TXEN ## _name), \ - .rxen = AVR_IO_REGBIT(UCSR ## _name ## B, RXEN ## _name), \ - .rxb8 = AVR_IO_REGBIT(UCSR ## _name ## B, RXB8 ## _name), \ - .usbs = AVR_IO_REGBIT(UCSR ## _name ## C, USBS ## _name), \ - .ucsz = AVR_IO_REGBITS(UCSR ## _name ## C, UCSZ ## _name ## 0, 0x3), \ - .ucsz2 = AVR_IO_REGBIT(UCSR ## _name ## B, UCSZ ## _name ## 2), \ - .ubrrl = AVR_IO_REGBITS(UBRR ## _name ## L, 0,0xFF), \ - .ubrrh = AVR_IO_REGBITS(UBRR ## _name ## H, 0,0xF), \ - \ - .r_ucsra = UCSR ## _name ## A, \ - .r_ucsrb = UCSR ## _name ## B, \ - .r_ucsrc = UCSR ## _name ## C, \ - \ - .rxc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _name ## B, RXCIE ## _name), \ - .raised = AVR_IO_REGBIT(UCSR ## _name ## A, RXC ## _name), \ - .vector = USART ## _name ## _RX_vect, \ - .raise_sticky = 1, \ - }, \ - .txc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _name ## B, TXCIE ## _name), \ - .raised = AVR_IO_REGBIT(UCSR ## _name ## A, TXC ## _name), \ - .vector = USART ## _name ## _TX_vect, \ - }, \ - .udrc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _name ## B, UDRIE ## _name), \ - .raised = AVR_IO_REGBIT(UCSR ## _name ## A, UDRE ## _name), \ - .vector = USART ## _name ## _UDRE_vect, \ - .raise_sticky = 1, \ - }, \ - } - -// This macro is for older single-interface devices where variable names are bit divergent -#define AVR_UART_DECLARE(_prr, _prusart, _upe_name, _rname_ix, _intr_c) \ - .uart = { \ - .name = '0', \ - .disabled = AVR_IO_REGBIT(_prr, _prusart), \ - .r_udr = UDR ## _rname_ix, \ - \ - .fe = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, FE ## _rname_ix), \ - .dor = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, DOR ## _rname_ix), \ - .upe = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, _upe_name ## _rname_ix), \ - .u2x = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, U2X ## _rname_ix), \ - .txen = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, TXEN ## _rname_ix), \ - .rxen = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXEN ## _rname_ix), \ - .rxb8 = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXB8 ## _rname_ix), \ - .usbs = AVR_IO_REGBIT(UCSR ## _rname_ix ## C, USBS ## _rname_ix), \ - .ucsz = AVR_IO_REGBITS(UCSR ## _rname_ix ## C, UCSZ ## _rname_ix ## 0, 0x3), \ - .ucsz2 = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, UCSZ ## _rname_ix ## 2), \ - .ubrrl = AVR_IO_REGBITS(UBRR ## _rname_ix ## L, 0,0xFF), \ - .ubrrh = AVR_IO_REGBITS(UBRR ## _rname_ix ## H, 0,0xF), \ - \ - .r_ucsra = UCSR ## _rname_ix ## A, \ - .r_ucsrb = UCSR ## _rname_ix ## B, \ - .r_ucsrc = UCSR ## _rname_ix ## C, \ - \ - .rxc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, RXCIE ## _rname_ix), \ - .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, RXC ## _rname_ix), \ - .vector = USART_RX ## _intr_c ## _vect, \ - .raise_sticky = 1, \ - }, \ - .txc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, TXCIE ## _rname_ix), \ - .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, TXC ## _rname_ix), \ - .vector = USART_TX ## _intr_c ## _vect, \ - }, \ - .udrc = { \ - .enable = AVR_IO_REGBIT(UCSR ## _rname_ix ## B, UDRIE ## _rname_ix), \ - .raised = AVR_IO_REGBIT(UCSR ## _rname_ix ## A, UDRE ## _rname_ix), \ - .vector = USART_UDRE_vect, \ - .raise_sticky = 1, \ - }, \ - } - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_UART_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.c deleted file mode 100644 index 4acbcfd..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.c +++ /dev/null @@ -1,801 +0,0 @@ -/* vim: set sts=4:sw=4:ts=4:noexpandtab - avr_usb.c - - Copyright 2012 Torbjorn Tyridal - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -/* TODO correct reset values */ -/* TODO generate sofi every 1ms (when connected) */ -/* TODO otg support? */ -/* TODO drop bitfields? */ -/* TODO thread safe ioctls */ -/* TODO dual-bank endpoint buffers */ -/* TODO actually pay attention to endpoint memory allocation ? buggy endpoint configuration doesn't matter in the simulator now. */ - -#include -#include -#include -#include -#include "avr_usb.h" - -enum usb_regs -{ - usbcon = 0, - udcon = 8, - udint = 9, - udien = 10, - udaddr = 11, - udfnuml = 12, - udfnumh = 13, - udmfn = 14, -// _res=15, - ueintx = 16, - uenum = 17, - uerst = 18, - ueconx = 19, - uecfg0x = 20, - uecfg1x = 21, - uesta0x = 22, - uesta1x = 23, - ueienx = 24, - uedatx = 25, - uebclx = 26, -// _res2=27, - ueint = 28, - otgtcon = 29, -}; - -union _ueintx { - struct { - uint8_t txini :1; - uint8_t stalledi :1; - uint8_t rxouti :1; - uint8_t rxstpi :1; - uint8_t nakouti :1; - uint8_t rwal :1; - uint8_t nakini :1; - uint8_t fifocon :1; - }; - uint8_t v; -}; - -struct _epstate { - union _ueintx ueintx; - uint8_t dummy1; - uint8_t dummy2; - union { - struct { - uint8_t epen :1; - uint8_t res :2; - uint8_t rstdt :1; - uint8_t stallrqc :1; - uint8_t stallrq :1; - }; - uint8_t v; - } ueconx; - union { - struct { - uint8_t epdir :1; - uint8_t res :5; - uint8_t eptype :2; - }; - uint8_t v; - } uecfg0x; - union { - struct { - uint8_t res :1; - uint8_t alloc :1; - uint8_t epbk1 :2; - uint8_t epsize :3; - uint8_t res2 :1; - }; - uint8_t v; - } uecfg1x; - union { - struct { - uint8_t nbusybk :2; - uint8_t dtseq :2; - uint8_t res :1; - uint8_t underfi :1; - uint8_t overfi :1; - uint8_t cfgok :1; - }; - uint8_t v; - } uesta0x; - union { - struct { - uint8_t curbk :2; - uint8_t ctrldir :1; - uint8_t res :5; - }; - uint8_t v; - } uesta1x; - union { - struct { - uint8_t txine :1; - uint8_t stallede :1; - uint8_t rxoute :1; - uint8_t rxstpe :1; - uint8_t nakoute :1; - uint8_t res :1; - uint8_t nakine :1; - uint8_t flerre :1; - }; - uint8_t v; - } ueienx; - - struct { - uint8_t bytes[64]; - uint8_t tail; - } bank[2]; - uint8_t current_bank; - int setup_is_read; -}; - -struct usb_internal_state { - struct _epstate ep_state[5]; - avr_int_vector_t com_vect; - avr_int_vector_t gen_vect; -}; - -const uint8_t num_endpoints = 5;//sizeof (struct usb_internal_state.ep_state) / sizeof (struct usb_internal_state.ep_state[0]); - -static uint8_t -current_ep_to_cpu( - avr_usb_t * p) -{ - return p->io.avr->data[p->r_usbcon + uenum]; -} - -static struct _epstate * -get_epstate( - avr_usb_t * p, - uint8_t ep) -{ - assert(ep < num_endpoints); - return &p->state->ep_state[ep]; -} - - -enum epints { - txini = 0, - stalledi = 1, - rxouti = 2, - rxstpi = 3, - nakouti = 4, - nakini = 6, - overfi = 10, - underfi = 11, -}; - -static void -raise_ep_interrupt( - struct avr_t * avr, - avr_usb_t * p, - uint8_t ep, - enum epints irq) -{ - struct _epstate * epstate = get_epstate(p, ep); - assert(ep < num_endpoints); - avr->data[p->r_usbcon + ueint] |= 1 << ep; - switch (irq) { - case txini: - case stalledi: - case rxouti: - case nakouti: - case nakini: - epstate->ueintx.v |= 1 << irq; - if (epstate->ueienx.v & (1 << irq)) - avr_raise_interrupt(avr, &p->state->com_vect); - break; - case rxstpi: - epstate->ueintx.v |= 1 << irq; - if (epstate->ueienx.v & (1 << irq)) - avr_raise_interrupt(avr, &p->state->com_vect); - break; - case overfi: - epstate->uesta0x.overfi = 1; - if (epstate->ueienx.flerre) - avr_raise_interrupt(avr, &p->state->com_vect); - break; - case underfi: - epstate->uesta0x.underfi = 1; - if (epstate->ueienx.flerre) - avr_raise_interrupt(avr, &p->state->com_vect); - break; - default: - assert(0); - } -} - -enum usbints { - suspi = 0, sofi = 2, eorsti = 3, wakeupi = 4, eorsmi = 5, uprsmi = 6 -}; -static void -raise_usb_interrupt( - avr_usb_t * p, - enum usbints irq) -{ - uint8_t * Rudien = &p->io.avr->data[p->r_usbcon + udien]; - uint8_t * Rudint = &p->io.avr->data[p->r_usbcon + udint]; - - switch (irq) { - case uprsmi: - case eorsmi: - case wakeupi: - case eorsti: - case sofi: - case suspi: - *Rudint |= 1 << irq; - if (*Rudien & (1 << irq)) - avr_raise_interrupt(p->io.avr, &p->state->gen_vect); - break; - default: - assert(0); - } - -} - -static void -reset_endpoints( - struct avr_t * avr, - avr_usb_t * p) -{ - memset(&p->state->ep_state[1], 0, - sizeof p->state->ep_state - sizeof p->state->ep_state[0]); -} - -static int -ep_fifo_empty( - struct _epstate * epstate) -{ - return epstate->bank[epstate->current_bank].tail == 0; -} - -static int -ep_fifo_full( - struct _epstate * epstate) -{ - return epstate->bank[epstate->current_bank].tail >= - (8 << epstate->uecfg1x.epsize); -} - -static uint8_t -ep_fifo_size( - struct _epstate * epstate) -{ - assert(epstate->ueconx.epen); - return (8 << epstate->uecfg1x.epsize); -} - -static uint8_t -ep_fifo_count( - struct _epstate * epstate) -{ - return epstate->bank[epstate->current_bank].tail; -} - -static int -ep_fifo_cpu_readbyte( - struct _epstate * epstate) -{ - uint8_t i, j; - uint8_t v = epstate->bank[epstate->current_bank].bytes[0]; - - if (!epstate->ueconx.epen) { - printf("WARNING! Adding bytes to non configured endpoint\n"); - return -1; - } - - if (ep_fifo_empty(epstate)) - return -2; - - for (i = 0, j = ep_fifo_count(epstate) - 1; i < j; i++) - epstate->bank[epstate->current_bank].bytes[i] = - epstate->bank[epstate->current_bank].bytes[i + 1]; - epstate->bank[epstate->current_bank].tail--; - return v; -} - -static int -ep_fifo_cpu_writebyte( - struct _epstate * epstate, - uint8_t v) -{ - if (!epstate->ueconx.epen) { - printf("WARNING! Adding bytes to non configured endpoint\n"); - return -1; - } - if (ep_fifo_full(epstate)) - return -2; - - epstate->bank[epstate->current_bank].bytes[epstate->bank[epstate->current_bank].tail++] = v; - return 0; -} - -static int -ep_fifo_usb_read( - struct _epstate * epstate, - uint8_t * buf) -{ - if (!epstate->ueconx.epen) { - printf("WARNING! Reading from non configured endpoint\n"); - return -1; - } - if (epstate->ueintx.txini) { - return AVR_IOCTL_USB_NAK; - } - if (epstate->ueintx.fifocon && epstate->uecfg0x.eptype != 0) { - return AVR_IOCTL_USB_NAK; - } - - int ret = epstate->bank[epstate->current_bank].tail; - memcpy(buf, epstate->bank[epstate->current_bank].bytes, - epstate->bank[epstate->current_bank].tail); - epstate->bank[epstate->current_bank].tail = 0; - return ret; -} - -static int -ep_fifo_usb_write( - struct _epstate * epstate, - uint8_t * buf, - uint8_t len) -{ - if (!epstate->ueconx.epen) { - printf("WARNING! Adding bytes to non configured endpoint\n"); - return -1; - } - - if (epstate->ueintx.rxouti) { - return AVR_IOCTL_USB_NAK; - } - if (epstate->ueintx.fifocon && epstate->uecfg0x.eptype != 0) { - return AVR_IOCTL_USB_NAK; - } - - if (len > ep_fifo_size(epstate)) { - printf("EP OVERFI\n"); - len = sizeof epstate->bank[epstate->current_bank].bytes; - } - memcpy(epstate->bank[epstate->current_bank].bytes, buf, len); - epstate->bank[epstate->current_bank].tail = len; - - return 0; -} - -static uint8_t -avr_usb_ep_read_bytecount( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - return ep_fifo_count(get_epstate(p, current_ep_to_cpu(p))); -} - -static void -avr_usb_udaddr_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - if (v & 0x80) - AVR_LOG(avr, LOG_TRACE, "USB: Activate address %d\n", v & 0x7f); - avr_core_watch_write(avr, addr, v); -} - -static void -avr_usb_udcon_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_usb_t * p = (avr_usb_t *)param; - - if(avr->data[addr]&1 && !(v&1)) - avr_raise_irq(p->io.irq + USB_IRQ_ATTACH, !(v&1)); - avr_core_watch_write(avr, addr, v); -} - -static void -avr_usb_uenum_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - assert(v < num_endpoints); - avr_core_watch_write(avr, addr, v); -} - -static uint8_t -avr_usb_ep_read_ueintx( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - uint8_t ep = current_ep_to_cpu(p); - - if (p->state->ep_state[ep].uecfg0x.epdir) - p->state->ep_state[ep].ueintx.rwal = !ep_fifo_full(get_epstate(p, ep)); - else - p->state->ep_state[ep].ueintx.rwal = !ep_fifo_empty(get_epstate(p, ep)); - - return p->state->ep_state[ep].ueintx.v; -} - -static void -avr_usb_ep_write_ueintx( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - uint8_t ep = current_ep_to_cpu(p); - - union _ueintx * newstate = (union _ueintx*) &v; - union _ueintx * curstate = &p->state->ep_state[ep].ueintx; - - if (curstate->rxouti & !newstate->rxouti) - curstate->rxouti = 0; - if (curstate->txini & !newstate->txini) - curstate->txini = 0; - if (curstate->rxstpi & !newstate->rxstpi) { - curstate->txini = 1; - curstate->rxouti = 0; - curstate->rxstpi = 0; - } - if (curstate->fifocon & !newstate->fifocon) - curstate->fifocon = 0; - if (curstate->nakini & !newstate->nakini) - curstate->nakini = 0; - if (curstate->nakouti & !newstate->nakouti) - curstate->nakouti = 0; - if (curstate->stalledi & !newstate->stalledi) - curstate->stalledi = 0; - if (curstate->rwal & !newstate->rwal) - AVR_LOG(avr, LOG_WARNING, "USB: Pointless change of ueintx.rwal\n"); - - if ((curstate->v & 0xdf) == 0) - avr->data[p->r_usbcon + ueint] &= 0xff ^ (1 << ep); // mark ep0 interrupt -} - -static uint8_t -avr_usb_ep_read( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - uint8_t laddr = addr - p->r_usbcon; - uint8_t v; - struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); - - switch(laddr) { - case ueconx: v = epstate->ueconx.v; break; - case uecfg0x: v = epstate->uecfg0x.v; break; - case uecfg1x: v = epstate->uecfg1x.v; break; - case uesta0x: v = epstate->uesta0x.v; break; - case uesta1x: v = epstate->uesta1x.v; break; - case ueienx: v = epstate->ueienx.v; break; - default:assert(0); - } - return v; -} - -static void -avr_usb_ep_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - struct _epstate * epstate = get_epstate(p, current_ep_to_cpu(p)); - uint8_t laddr = addr - p->r_usbcon; - - switch (laddr) { - case ueconx: - if (v & 1 << 4) - epstate->ueconx.stallrq = 0; - if (v & 1 << 5) - epstate->ueconx.stallrq = 1; - epstate->ueconx.epen = (v & 1) != 0; - break; - case uecfg0x: - epstate->uecfg0x.v = v; - epstate->uesta0x.cfgok = 0; - break; - case uecfg1x: - epstate->uecfg1x.v = v; - epstate->uesta0x.cfgok = epstate->uecfg1x.alloc; - if (epstate->uecfg0x.eptype == 0) - epstate->ueintx.txini = 1; - else if (epstate->uecfg0x.epdir) { - epstate->ueintx.txini = 1; - epstate->ueintx.rwal = 1; - epstate->ueintx.fifocon = 1; - } else - epstate->ueintx.rxouti = 0; - avr_core_watch_write(avr, p->r_usbcon + uesta0x, - epstate->uesta0x.v); - break; - case uesta0x: - v = (epstate->uesta0x.v & 0x9f) + (v & (0x60 & epstate->uesta0x.v)); - epstate->uesta0x.v = v; - break; - case ueienx: - epstate->ueienx.v = v; - break; - default: - assert(0); - } -} - -static uint8_t -avr_usb_ep_read_data( - struct avr_t * avr, - avr_io_addr_t addr, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - int ret = ep_fifo_cpu_readbyte(get_epstate(p, current_ep_to_cpu(p))); - - if (ret < 0) { - if (ret == -2) - raise_ep_interrupt(avr, p, current_ep_to_cpu(p), underfi); - return 0; - } else - return (uint8_t) ret; -} - -static void -avr_usb_ep_write_data( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - int ret = ep_fifo_cpu_writebyte(get_epstate(p, current_ep_to_cpu(p)), v); - if (ret == 0) - return; - - if (ret == -2) - raise_ep_interrupt(avr, p, current_ep_to_cpu(p), overfi); -} - -static void -avr_usb_pll_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - v |= (v >> 1) & 1; - avr_core_watch_write(avr, addr, v); -} - - -avr_cycle_count_t -sof_generator( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_usb_t * p = (avr_usb_t *) param; - //stop sof generation if detached - if (avr->data[p->r_usbcon + udcon] & 1) - return 0; - else { - raise_usb_interrupt(p, sofi); - return when; - } -} - -static int -avr_usb_ioctl( - struct avr_io_t * io, - uint32_t ctl, - void * io_param) -{ - avr_usb_t * p = (avr_usb_t *) io; - struct avr_io_usb * d = (struct avr_io_usb*) io_param; - struct _epstate * epstate = 0; - int ret; - uint8_t ep; - - switch (ctl) { - case AVR_IOCTL_USB_READ: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - if (epstate->ueconx.stallrq) { - raise_ep_interrupt(io->avr, p, 0, stalledi); - return AVR_IOCTL_USB_STALL; - } - if (ep && !epstate->uecfg0x.epdir) - AVR_LOG(io->avr, LOG_WARNING, "USB: Reading from IN endpoint from host??\n"); - - ret = ep_fifo_usb_read(epstate, d->buf); - if (ret < 0) { - // is this correct? It makes the cdc example work. - // Linux stops polling the data ep if we send naks,but - // according to usb spec nak'ing should be ok. - if (epstate->uecfg0x.eptype == 2) { - d->sz = 0; - return 0; - } else - return ret; - } - d->sz = ret; - ret = 0; - epstate->ueintx.fifocon = 1; - raise_ep_interrupt(io->avr, p, ep, txini); - return ret; - case AVR_IOCTL_USB_WRITE: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - if (ep && epstate->uecfg0x.epdir) - AVR_LOG(io->avr, LOG_WARNING, "USB: Writing to IN endpoint from host??\n"); - - if (epstate->ueconx.stallrq) { - raise_ep_interrupt(io->avr, p, 0, stalledi); - return AVR_IOCTL_USB_STALL; - } - - ret = ep_fifo_usb_write(epstate, d->buf, d->sz); - if (ret < 0) - return ret; - - epstate->ueintx.fifocon = 1; - raise_ep_interrupt(io->avr, p, ep, rxouti); - return 0; - case AVR_IOCTL_USB_SETUP: - ep = d->pipe & 0x7f; - epstate = get_epstate(p, ep); - - epstate->ueconx.stallrq = 0; - // teensy actually depends on this (fails to ack rxouti on usb - // control read status stage) even if the datasheet clearly states - // that one should do so. - epstate->ueintx.rxouti = 0; - - ret = ep_fifo_usb_write(epstate, d->buf, d->sz); - if (ret < 0) - return ret; - raise_ep_interrupt(io->avr, p, ep, rxstpi); - - return 0; - case AVR_IOCTL_USB_RESET: - AVR_LOG(io->avr, LOG_TRACE, "USB: __USB_RESET__\n"); - reset_endpoints(io->avr, p); - raise_usb_interrupt(p, eorsti); - if (0) - avr_cycle_timer_register_usec(io->avr, 1000, sof_generator, p); - return 0; - default: - return -1; - } -} - -void -avr_usb_reset( - struct avr_io_t *io) -{ - avr_usb_t * p = (avr_usb_t *) io; - uint8_t i; - - memset(p->state->ep_state, 0, sizeof p->state->ep_state); - - for (i = 0; i < otgtcon; i++) - p->io.avr->data[p->r_usbcon + i] = 0; - - p->io.avr->data[p->r_usbcon] = 0x20; - p->io.avr->data[p->r_usbcon + udcon] = 1; - - AVR_LOG(io->avr, LOG_TRACE, "USB: %s\n", __FUNCTION__); -} - -static const char * irq_names[USB_IRQ_COUNT] = { - [USB_IRQ_ATTACH] = ">attach", -}; - -static void -avr_usb_dealloc( - struct avr_io_t * port) -{ - avr_usb_t * p = (avr_usb_t *) port; - free(p->state); -} - -static avr_io_t _io = { - .kind = "usb", - .reset = avr_usb_reset, - .irq_names = irq_names, - .ioctl = avr_usb_ioctl, - .dealloc = avr_usb_dealloc, -}; - -static void -register_io_ep_readwrite( - avr_t * avr, - avr_usb_t * p, - uint8_t laddr) -{ - avr_register_io_write(avr, p->r_usbcon + laddr, avr_usb_ep_write, p); - avr_register_io_read(avr, p->r_usbcon + laddr, avr_usb_ep_read, p); -} - -static void -register_vectors( - avr_t * avr, - avr_usb_t * p) -{ - // usb interrupts are multiplexed into just two vectors. - // we therefore need fake bits for enable & raise - - // use usbe as fake enable bit - p->state->com_vect.enable = (avr_regbit_t)AVR_IO_REGBIT(p->r_usbcon, 7); - p->state->gen_vect.enable = (avr_regbit_t)AVR_IO_REGBIT(p->r_usbcon, 7); - -// // use reserved/unused bits in usbsta as fake raised bits -// p->state->com_vect.raised = (avr_regbit_t)AVR_IO_REGBIT(p->r_usbcon+1,7); -// p->state->gen_vect.raised = (avr_regbit_t)AVR_IO_REGBIT(p->r_usbcon+1,6); - - p->state->com_vect.vector = p->usb_com_vect; - p->state->gen_vect.vector = p->usb_gen_vect; - - avr_register_vector(avr, &p->state->com_vect); - avr_register_vector(avr, &p->state->gen_vect); -} - -void avr_usb_init(avr_t * avr, avr_usb_t * p) -{ - p->io = _io; - - p->state = calloc(1, sizeof *p->state); - - avr_register_io(avr, &p->io); - register_vectors(avr, p); - // allocate this module's IRQ - avr_io_setirqs(&p->io, AVR_IOCTL_USB_GETIRQ(), USB_IRQ_COUNT, NULL); - - avr_register_io_write(avr, p->r_usbcon + udaddr, avr_usb_udaddr_write, p); - avr_register_io_write(avr, p->r_usbcon + udcon, avr_usb_udcon_write, p); - avr_register_io_write(avr, p->r_usbcon + uenum, avr_usb_uenum_write, p); - - avr_register_io_read(avr, p->r_usbcon + uedatx, avr_usb_ep_read_data, p); - avr_register_io_write(avr, p->r_usbcon + uedatx, avr_usb_ep_write_data, p); - avr_register_io_read(avr, p->r_usbcon + uebclx, avr_usb_ep_read_bytecount, p); //ro - - avr_register_io_read(avr, p->r_usbcon + ueintx, avr_usb_ep_read_ueintx, p); - avr_register_io_write(avr, p->r_usbcon + ueintx, avr_usb_ep_write_ueintx, p); - - register_io_ep_readwrite(avr, p, ueconx); - register_io_ep_readwrite(avr, p, uecfg0x); - register_io_ep_readwrite(avr, p, uecfg1x); - register_io_ep_readwrite(avr, p, uesta0x); - register_io_ep_readwrite(avr, p, uesta1x); - register_io_ep_readwrite(avr, p, ueienx); - - avr_register_io_write(avr, p->r_pllcsr, avr_usb_pll_write, p); -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.h deleted file mode 100644 index 17e5c0d..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_usb.h +++ /dev/null @@ -1,74 +0,0 @@ -/* vim: set sts=4:sw=4:ts=4:noexpandtab - avr_usb.h - - Copyright 2012 Torbjorn Tyridal - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __AVR_USB_H__ -#define __AVR_USB_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -enum { - USB_IRQ_ATTACH = 0, - USB_IRQ_COUNT -}; - -// add port number to get the real IRQ -#define AVR_IOCTL_USB_WRITE AVR_IOCTL_DEF('u','s','b','w') -#define AVR_IOCTL_USB_READ AVR_IOCTL_DEF('u','s','b','r') -#define AVR_IOCTL_USB_SETUP AVR_IOCTL_DEF('u','s','b','s') -#define AVR_IOCTL_USB_RESET AVR_IOCTL_DEF('u','s','b','R') -#define AVR_IOCTL_USB_VBUS AVR_IOCTL_DEF('u','s','b','V') -#define AVR_IOCTL_USB_GETIRQ() AVR_IOCTL_DEF('u','s','b',' ') - -struct avr_io_usb { - uint8_t pipe; //[in] - uint32_t sz; //[in/out] - uint8_t * buf; //[in/out] -}; -#define AVR_IOCTL_USB_NAK -2 -#define AVR_IOCTL_USB_STALL -3 -#define AVR_IOCTL_USB_OK 0 - -typedef struct avr_usb_t { - avr_io_t io; - char name; - avr_regbit_t disabled; // bit in the PRR - avr_regbit_t usbrf; // bit in the MCUSR - avr_io_addr_t r_usbcon; // every usb reg is an offset of this. - avr_io_addr_t r_pllcsr; - - - uint8_t usb_com_vect; - uint8_t usb_gen_vect; - - struct usb_internal_state * state; -} avr_usb_t; - -void avr_usb_init(avr_t * avr, avr_usb_t * port); - -#ifdef __cplusplus -}; -#endif - -#endif /*__AVR_USB_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.c deleted file mode 100644 index b7a5d01..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - avr_watchdog.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include -#include -#include "avr_watchdog.h" - -static void avr_watchdog_run_callback_software_reset(avr_t * avr) -{ - avr_reset(avr); -} - -static avr_cycle_count_t avr_watchdog_timer( - struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_watchdog_t * p = (avr_watchdog_t *)param; - - if (avr_regbit_get(avr, p->watchdog.enable)) { - AVR_LOG(avr, LOG_TRACE, "WATCHDOG: timer fired.\n"); - avr_raise_interrupt(avr, &p->watchdog); - return when + p->cycle_count; - } else if (avr_regbit_get(avr, p->wde)) { - AVR_LOG(avr, LOG_TRACE, - "WATCHDOG: timer fired without interrupt. Resetting\n"); - - p->reset_context.avr_run = avr->run; - p->reset_context.wdrf = 1; - - /* Ideally we would perform a reset here via 'avr_reset' - * However, returning after reset would result in an unconsistent state. - * It seems our best (and cleanest) solution is to set a temporary call - * back which can safely perform the reset for us... During reset, - * the previous callback can be restored and safely resume. - */ - avr->run = avr_watchdog_run_callback_software_reset; - } - - return 0; -} - -static avr_cycle_count_t avr_wdce_clear( - struct avr_t * avr, avr_cycle_count_t when, void * param) -{ - avr_watchdog_t * p = (avr_watchdog_t *)param; - avr_regbit_clear(p->io.avr, p->wdce); - return 0; -} - -static void avr_watchdog_set_cycle_count_and_timer( - avr_t * avr, - avr_watchdog_t * p, - uint8_t was_enabled, - int8_t old_wdp) -{ - // If nothing else, always ensure we have a valid cycle count... - uint8_t wdp = avr_regbit_get_array(avr, p->wdp, 4); - - p->cycle_count = 2048 << wdp; - p->cycle_count = (p->cycle_count * avr->frequency) / 128000; - - uint8_t wde = avr_regbit_get(avr, p->wde); - uint8_t wdie = avr_regbit_get(avr, p->watchdog.enable); - - uint8_t enable_changed = (was_enabled != (wde || wdie)); - - uint8_t wdp_changed = ((old_wdp >= 0) ? (wdp != old_wdp) : 0); - - if (!enable_changed && !wdp_changed) - return; - - static char *message[2][2] = { - { 0, "reset" }, { "enabled", "enabled and set" } }; - - if (wde || wdie) { - AVR_LOG(avr, LOG_TRACE, - "WATCHDOG: %s to %d cycles @ 128kz (* %d) = %d CPU cycles.\n", - message[enable_changed][wdp_changed], 2048 << wdp, - 1 << wdp, (int)p->cycle_count); - - avr_cycle_timer_register(avr, p->cycle_count, avr_watchdog_timer, p); - } else if (enable_changed) { - AVR_LOG(avr, LOG_TRACE, "WATCHDOG: disabled\n"); - avr_cycle_timer_cancel(avr, avr_watchdog_timer, p); - } -} - -static void avr_watchdog_write( - avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) -{ - avr_watchdog_t * p = (avr_watchdog_t *)param; - - uint8_t old_wde = avr_regbit_get(avr, p->wde); - uint8_t old_wdie = avr_regbit_get(avr, p->watchdog.enable); - uint8_t old_wdce = avr_regbit_get(avr, p->wdce); - - uint8_t was_enabled = (old_wde || old_wdie); - - uint8_t old_v = avr->data[addr]; // allow gdb to see write... - avr_core_watch_write(avr, addr, v); - - if (old_wdce) { - uint8_t old_wdp = avr_regbit_get_array(avr, p->wdp, 4); - - // wdrf (watchdog reset flag) must be cleared before wde can be cleared. - if (avr_regbit_get(avr, p->wdrf)) - avr_regbit_set(avr, p->wde); - - avr_watchdog_set_cycle_count_and_timer(avr, p, was_enabled, old_wdp); - } else { - /* easier to change only what we need rather than check and reset - * locked/read-only bits. - */ - avr->data[addr] = old_v; - - uint8_t wdce_v = avr_regbit_from_value(avr, p->wdce, v); - uint8_t wde_v = avr_regbit_from_value(avr, p->wde, v); - - if (wdce_v && wde_v) { - avr_regbit_set(avr, p->wdce); - - avr_cycle_timer_register(avr, 4, avr_wdce_clear, p); - } else { - if (wde_v) // wde can be set but not cleared - avr_regbit_set(avr, p->wde); - - avr_regbit_setto_raw(avr, p->watchdog.enable, v); - - avr_watchdog_set_cycle_count_and_timer(avr, p, was_enabled, -1); - } - } -} - -/* - * called by the core when a WTD instruction is found - */ -static int avr_watchdog_ioctl( - struct avr_io_t * port, uint32_t ctl, void * io_param) -{ - avr_watchdog_t * p = (avr_watchdog_t *)port; - int res = -1; - - if (ctl == AVR_IOCTL_WATCHDOG_RESET) { - if (avr_regbit_get(p->io.avr, p->wde) || - avr_regbit_get(p->io.avr, p->watchdog.enable)) - avr_cycle_timer_register(p->io.avr, p->cycle_count, - avr_watchdog_timer, p); - res = 0; - } - - return res; -} - -static void avr_watchdog_irq_notify( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_watchdog_t * p = (avr_watchdog_t *)param; - avr_t * avr = p->io.avr; - - /* interrupt handling calls this twice... - * first when raised (during queuing), value = 1 - * again when cleared (after servicing), value = 0 - */ - - if (!value && avr_regbit_get(avr, p->watchdog.raised) && avr_regbit_get(avr, p->wde)) { - avr_regbit_clear(avr, p->watchdog.enable); - } -} - -static void avr_watchdog_reset(avr_io_t * port) -{ - avr_watchdog_t * p = (avr_watchdog_t *)port; - avr_t * avr = p->io.avr; - - if (p->reset_context.wdrf) { - p->reset_context.wdrf = 0; - /* - * if watchdog reset kicked, then watchdog gets restarted at - * fastest interval - */ - avr->run = p->reset_context.avr_run; - - avr_regbit_set(avr, p->wde); - avr_regbit_set(avr, p->wdrf); - avr_regbit_set_array_from_value(avr, p->wdp, 4, 0); - - avr_watchdog_set_cycle_count_and_timer(avr, p, 0, 0); - } - /* TODO could now use the two pending/running IRQs to do the same - * as before */ - avr_irq_register_notify(p->watchdog.irq, avr_watchdog_irq_notify, p); -} - -static avr_io_t _io = { - .kind = "watchdog", - .reset = avr_watchdog_reset, - .ioctl = avr_watchdog_ioctl, -}; - -void avr_watchdog_init(avr_t * avr, avr_watchdog_t * p) -{ - p->io = _io; - - avr_register_io(avr, &p->io); - avr_register_vector(avr, &p->watchdog); - - avr_register_io_write(avr, p->wdce.reg, avr_watchdog_write, p); - - p->reset_context.wdrf = 0; -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.h deleted file mode 100644 index da86371..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/avr_watchdog.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - avr_watchdog.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __AVR_WATCHDOG_H___ -#define __AVR_WATCHDOG_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -typedef struct avr_watchdog_t { - avr_io_t io; - - avr_regbit_t wdrf; // watchdog reset flag (in MCU Status Register) - - avr_regbit_t wdce; // watchdog change enable - avr_regbit_t wde; // watchdog enabled - avr_regbit_t wdp[4]; // watchdog Timer Prescaler - - avr_int_vector_t watchdog; // watchdog interrupt - - avr_cycle_count_t cycle_count; - - struct { - uint8_t wdrf; // saved watchdog reset flag - avr_run_t avr_run; // restored during reset - } reset_context; -} avr_watchdog_t; - -/* takes no parameter */ -#define AVR_IOCTL_WATCHDOG_RESET AVR_IOCTL_DEF('w','d','t','r') - -void avr_watchdog_init(avr_t * avr, avr_watchdog_t * p); - - -/* - * This helps declare a watchdog block into a core. - * No guarantee it will work with all, but it works - * with the one we have right now - */ -#define AVR_WATCHDOG_DECLARE(_WDSR, _vec) \ - .watchdog = {\ - .wdrf = AVR_IO_REGBIT(MCUSR, WDRF),\ - .wdce = AVR_IO_REGBIT(_WDSR, WDCE),\ - .wde = AVR_IO_REGBIT(_WDSR, WDE),\ - .wdp = { AVR_IO_REGBIT(_WDSR, WDP0),AVR_IO_REGBIT(_WDSR, WDP1),\ - AVR_IO_REGBIT(_WDSR, WDP2),AVR_IO_REGBIT(_WDSR, WDP3) },\ - .watchdog = {\ - .enable = AVR_IO_REGBIT(_WDSR, WDIE),\ - .raised = AVR_IO_REGBIT(_WDSR, WDIF),\ - .vector = _vec,\ - },\ - } - -/* no WDP3, WDIE, WDIF in atmega128 */ -/* MCUSR is called MCUCSR in atmega128 */ -#define AVR_WATCHDOG_DECLARE_128(_WDSR, _vec) \ - .watchdog = {\ - .wdrf = AVR_IO_REGBIT(MCUCSR, WDRF),\ - .wdce = AVR_IO_REGBIT(_WDSR, WDCE),\ - .wde = AVR_IO_REGBIT(_WDSR, WDE),\ - .wdp = { AVR_IO_REGBIT(_WDSR, WDP0),AVR_IO_REGBIT(_WDSR, WDP1),\ - AVR_IO_REGBIT(_WDSR, WDP2) },\ - .watchdog = {\ - .enable = AVR_IO_REGBIT(_WDSR, 6),\ - .raised = AVR_IO_REGBIT(_WDSR, 7),\ - .vector = _vec,\ - },\ - } - -#ifdef __cplusplus -}; -#endif - -#endif /* __AVR_WATCHDOG_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/fifo_declare.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/fifo_declare.h deleted file mode 100644 index 8a3b2fb..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/fifo_declare.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - fido_declare.h - Copyright (C) 2003-2012 Michel Pollet - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - * FIFO helpers, aka circular buffers - * - * these macros define accessories for FIFOs of any name, type and - * any (power of two) size - */ - -#ifndef __FIFO_DECLARE__ -#define __FIFO_DECLARE__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - doing a : - DECLARE_FIFO(uint8_t, myfifo, 128); - - will declare : - enum : myfifo_overflow_f - type : myfifo_t - functions: - // write a byte into the fifo, return 1 if there was room, 0 if there wasn't - int myfifo_write(myfifo_t *c, uint8_t b); - // reads a byte from the fifo, return 0 if empty. Use myfifo_isempty() to check beforehand - uint8_t myfifo_read(myfifo_t *c); - int myfifo_isfull(myfifo_t *c); - int myfifo_isempty(myfifo_t *c); - // returns number of items to read now - uint16_t myfifo_get_read_size(myfifo_t *c); - // read item at offset o from read cursor, no cursor advance - uint8_t myfifo_read_at(myfifo_t *c, uint16_t o); - // write b at offset o compared to current write cursor, no cursor advance - void myfifo_write_at(myfifo_t *c, uint16_t o, uint8_t b); - - In your .c you need to 'implement' the fifo: - DEFINE_FIFO(uint8_t, myfifo) - - To use the fifo, you must declare at least one : - myfifo_t fifo = FIFO_NULL; - - while (!myfifo_isfull(&fifo)) - myfifo_write(&fifo, 0xaa); - .... - while (!myfifo_isempty(&fifo)) - b = myfifo_read(&fifo); - */ - -#include - -#if __AVR__ -#define FIFO_CURSOR_TYPE uint8_t -#define FIFO_BOOL_TYPE char -#define FIFO_INLINE -#define FIFO_SYNC -#endif - -#ifndef FIFO_CURSOR_TYPE -#define FIFO_CURSOR_TYPE uint16_t -#endif -#ifndef FIFO_BOOL_TYPE -#define FIFO_BOOL_TYPE int -#endif -#ifndef FIFO_INLINE -#define FIFO_INLINE inline -#endif - -/* We should not need volatile */ -#ifndef FIFO_VOLATILE -#define FIFO_VOLATILE -#endif -#ifndef FIFO_SYNC -#define FIFO_SYNC __sync_synchronize() -#endif - -#ifndef FIFO_ZERO_INIT -#define FIFO_ZERO_INIT {0} -#endif -#define FIFO_NULL { FIFO_ZERO_INIT, 0, 0, 0 } - -/* New compilers don't like unused static functions. However, - * we do like 'static inlines' for these small accessors, - * so we mark them as 'unused'. It stops it complaining */ -#ifdef __GNUC__ -#define FIFO_DECL static __attribute__ ((unused)) -#else -#define FIFO_DECL static -#endif - -#define DECLARE_FIFO(__type, __name, __size) \ -enum { __name##_overflow_f = (1 << 0) }; \ -enum { __name##_fifo_size = (__size) }; \ -typedef struct __name##_t { \ - __type buffer[__name##_fifo_size]; \ - FIFO_VOLATILE FIFO_CURSOR_TYPE read; \ - FIFO_VOLATILE FIFO_CURSOR_TYPE write; \ - FIFO_VOLATILE uint8_t flags; \ -} __name##_t - -#define DEFINE_FIFO(__type, __name) \ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_write(__name##_t * c, __type b)\ -{\ - FIFO_CURSOR_TYPE now = c->write;\ - FIFO_CURSOR_TYPE next = (now + 1) & (__name##_fifo_size-1);\ - if (c->read != next) { \ - c->buffer[now] = b;\ - FIFO_SYNC; \ - c->write = next;\ - return 1;\ - }\ - return 0;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_isfull(__name##_t *c)\ -{\ - FIFO_CURSOR_TYPE next = (c->write + 1) & (__name##_fifo_size-1);\ - return c->read == next;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_isempty(__name##_t * c)\ -{\ - return c->read == c->write;\ -}\ -FIFO_DECL FIFO_INLINE __type __name##_read(__name##_t * c)\ -{\ - __type res = FIFO_ZERO_INIT; \ - FIFO_CURSOR_TYPE read = c->read;\ - if (read == c->write)\ - return res;\ - res = c->buffer[read];\ - FIFO_SYNC; \ - c->read = (read + 1) & (__name##_fifo_size-1);\ - return res;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_CURSOR_TYPE __name##_get_read_size(__name##_t *c)\ -{\ - return ((c->write + __name##_fifo_size) - c->read) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE FIFO_CURSOR_TYPE __name##_get_write_size(__name##_t *c)\ -{\ - return (__name##_fifo_size-1) - __name##_get_read_size(c);\ -}\ -FIFO_DECL FIFO_INLINE void __name##_read_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - FIFO_SYNC; \ - c->read = (c->read + o) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE __type __name##_read_at(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - return c->buffer[(c->read + o) & (__name##_fifo_size-1)];\ -}\ -FIFO_DECL FIFO_INLINE void __name##_write_at(__name##_t *c, FIFO_CURSOR_TYPE o, __type b)\ -{\ - c->buffer[(c->write + o) & (__name##_fifo_size-1)] = b;\ -}\ -FIFO_DECL FIFO_INLINE void __name##_write_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - FIFO_SYNC; \ - c->write = (c->write + o) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE void __name##_reset(__name##_t *c)\ -{\ - FIFO_SYNC; \ - c->read = c->write = c->flags = 0;\ -}\ -struct __name##_t - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/run_avr.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/run_avr.c deleted file mode 100644 index dfa6fce..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/run_avr.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - run_avr.c - - Copyright 2008, 2010 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include -#include "sim_avr.h" -#include "sim_elf.h" -#include "sim_core.h" -#include "sim_gdb.h" -#include "sim_hex.h" -#include "sim_vcd_file.h" - -#include "sim_core_decl.h" - -static void -display_usage( - const char * app) -{ - printf("Usage: %s [...] \n", app); - printf( - " [--help|-h|-?] Display this usage message and exit\n" - " [--list-cores] List all supported AVR cores and exit\n" - " [-v] Raise verbosity level\n" - " (can be passed more than once)\n" - " [--freq|-f ] Sets the frequency for an .hex firmware\n" - " [--mcu|-m ] Sets the MCU type for an .hex firmware\n" - " [--gdb|-g []] Listen for gdb connection on " - "(default 1234)\n" -#ifdef CONFIG_SIMAVR_TRACE - " [--trace, -t] Run full scale decoder trace\n" -#else - " [--trace, -t] Run full scale decoder trace (Off)\n" -#endif //CONFIG_SIMAVR_TRACE - " [-ti ] Add traces for IRQ vector \n" - " [--input|-i ] A VCD file to use as input signals\n" - " [--output|-o ] A VCD file to save the traced signals\n" - " [--add-trace|-at ]\n" - " Add signal to be included in VCD output\n" - " [-ff <.hex file>] Load next .hex file as flash\n" - " [-ee <.hex file>] Load next .hex file as eeprom\n" - " A .hex or an ELF file. ELF files are\n" - " preferred, and can include " - "debugging syms\n"); - exit(1); -} - -static void -list_cores() -{ - printf( "Supported AVR cores:\n"); - for (int i = 0; avr_kind[i]; i++) { - printf(" "); - for (int ti = 0; ti < 4 && avr_kind[i]->names[ti]; ti++) - printf("%s ", avr_kind[i]->names[ti]); - printf("\n"); - } - exit(1); -} - -static avr_t * avr = NULL; - -static void -sig_int( - int sign) -{ - printf("signal caught, simavr terminating\n"); - if (avr) - avr_terminate(avr); - exit(0); -} - -int -main( - int argc, - char *argv[]) -{ -#ifdef CONFIG_SIMAVR_TRACE - int trace = 0; -#endif //CONFIG_SIMAVR_TRACE - elf_firmware_t f = {{0}}; - uint32_t f_cpu = 0; - int gdb = 0; - int log = 1; - int port = 1234; - char name[24] = ""; - uint32_t loadBase = AVR_SEGMENT_OFFSET_FLASH; - int trace_vectors[8] = {0}; - int trace_vectors_count = 0; - const char *vcd_input = NULL; - - if (argc == 1) - display_usage(basename(argv[0])); - - for (int pi = 1; pi < argc; pi++) { - if (!strcmp(argv[pi], "--list-cores")) { - list_cores(); - } else if (!strcmp(argv[pi], "-h") || !strcmp(argv[pi], "--help")) { - display_usage(basename(argv[0])); - } else if (!strcmp(argv[pi], "-m") || !strcmp(argv[pi], "--mcu")) { - if (pi < argc-1) { - snprintf(name, sizeof(name), "%s", argv[++pi]); - strcpy(f.mmcu, name); - } else { - display_usage(basename(argv[0])); - } - } else if (!strcmp(argv[pi], "-f") || !strcmp(argv[pi], "--freq")) { - if (pi < argc-1) { - f_cpu = atoi(argv[++pi]); - f.frequency = f_cpu; - } else { - display_usage(basename(argv[0])); - } - } else if (!strcmp(argv[pi], "-i") || !strcmp(argv[pi], "--input")) { - if (pi < argc-1) - vcd_input = argv[++pi]; - else - display_usage(basename(argv[0])); - } else if (!strcmp(argv[pi], "-o") || - !strcmp(argv[pi], "--output")) { - if (pi + 1 >= argc) { - fprintf(stderr, "%s: missing mandatory argument for %s.\n", argv[0], argv[pi]); - exit(1); - } - snprintf(f.tracename, sizeof(f.tracename), "%s", argv[++pi]); - } else if (!strcmp(argv[pi], "-t") || - !strcmp(argv[pi], "--trace")) { -#ifdef CONFIG_SIMAVR_TRACE - trace++; -#else - fprintf(stderr, - "%s: tracing option '%s' requires " - "compilation option CONFIG_SIMAVR_TRACE.\n", - argv[0], argv[pi]); -#endif //CONFIG_SIMAVR_TRACE - } else if (!strcmp(argv[pi], "-at") || - !strcmp(argv[pi], "--add-trace")) { - if (pi + 1 >= argc) { - fprintf(stderr, "%s: missing mandatory argument for %s.\n", argv[0], argv[pi]); - exit(1); - } - ++pi; - struct { - char kind[64]; - uint8_t mask; - uint16_t addr; - char name[64]; - } trace; - const int n_args = sscanf( - argv[pi], - "%63[^=]=%63[^@]@0x%hx/0x%hhx", - &trace.name[0], - &trace.kind[0], - &trace.addr, - &trace.mask - ); - if (n_args != 4) { - --pi; - fprintf(stderr, "%s: format for %s is name=kind@addr/mask.\n", argv[0], argv[pi]); - exit(1); - } - - /****/ if (!strcmp(trace.kind, "portpin")) { - f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_PORTPIN; - } else if (!strcmp(trace.kind, "irq")) { - f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_IRQ; - } else if (!strcmp(trace.kind, "trace")) { - f.trace[f.tracecount].kind = AVR_MMCU_TAG_VCD_TRACE; - } else { - fprintf( - stderr, - "%s: unknown trace kind '%s', not one of 'portpin', 'irq', or 'trace'.\n", - argv[0], - trace.kind - ); - exit(1); - } - f.trace[f.tracecount].mask = trace.mask; - f.trace[f.tracecount].addr = trace.addr; - strncpy(f.trace[f.tracecount].name, trace.name, sizeof(f.trace[f.tracecount].name)); - - printf( - "Adding %s trace on address 0x%04x, mask 0x%02x ('%s')\n", - f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_PORTPIN ? "portpin" - : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_IRQ ? "irq" - : f.trace[f.tracecount].kind == AVR_MMCU_TAG_VCD_TRACE ? "trace" - : "unknown", - f.trace[f.tracecount].addr, - f.trace[f.tracecount].mask, - f.trace[f.tracecount].name - ); - - ++f.tracecount; - } else if (!strcmp(argv[pi], "-ti")) { - if (pi < argc-1) - trace_vectors[trace_vectors_count++] = atoi(argv[++pi]); - } else if (!strcmp(argv[pi], "-g") || - !strcmp(argv[pi], "--gdb")) { - gdb++; - if (pi < (argc-2) && argv[pi+1][0] != '-' ) - port = atoi(argv[++pi]); - } else if (!strcmp(argv[pi], "-v")) { - log++; - } else if (!strcmp(argv[pi], "-ee")) { - loadBase = AVR_SEGMENT_OFFSET_EEPROM; - } else if (!strcmp(argv[pi], "-ff")) { - loadBase = AVR_SEGMENT_OFFSET_FLASH; - } else if (argv[pi][0] != '-') { - sim_setup_firmware(argv[pi], loadBase, &f, argv[0]); - } - } - - // Frequency and MCU type were set early so they can be checked when - // loading a hex file. Set them again because they can also be set - // in an ELF firmware file. - - if (strlen(name)) - strcpy(f.mmcu, name); - if (f_cpu) - f.frequency = f_cpu; - - avr = avr_make_mcu_by_name(f.mmcu); - if (!avr) { - fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu); - exit(1); - } - avr_init(avr); - avr->log = (log > LOG_TRACE ? LOG_TRACE : log); -#ifdef CONFIG_SIMAVR_TRACE - avr->trace = trace; -#endif //CONFIG_SIMAVR_TRACE - - avr_load_firmware(avr, &f); - if (f.flashbase) { - printf("Attempted to load a bootloader at %04x\n", f.flashbase); - avr->pc = f.flashbase; - } - for (int ti = 0; ti < trace_vectors_count; ti++) { - for (int vi = 0; vi < avr->interrupts.vector_count; vi++) - if (avr->interrupts.vector[vi]->vector == trace_vectors[ti]) - avr->interrupts.vector[vi]->trace = 1; - } - if (vcd_input) { - static avr_vcd_t input; - if (avr_vcd_init_input(avr, vcd_input, &input)) { - fprintf(stderr, "%s: Warning: VCD input file %s failed\n", argv[0], vcd_input); - } - } - - // even if not setup at startup, activate gdb if crashing - avr->gdb_port = port; - if (gdb) { - avr->state = cpu_Stopped; - avr_gdb_init(avr); - } - - signal(SIGINT, sig_int); - signal(SIGTERM, sig_int); - - for (;;) { - int state = avr_run(avr); - if (state == cpu_Done || state == cpu_Crashed) - break; - } - - avr_terminate(avr); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.c deleted file mode 100644 index 24cb244..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.c +++ /dev/null @@ -1,453 +0,0 @@ -/* - sim_avr.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include "sim_avr.h" -#include "sim_core.h" -#include "sim_time.h" -#include "sim_gdb.h" -#include "avr_uart.h" -#include "sim_vcd_file.h" -#include "avr/avr_mcu_section.h" - -#define AVR_KIND_DECL -#include "sim_core_decl.h" - -static void -std_logger( - avr_t * avr, - const int level, - const char * format, - va_list ap); -static avr_logger_p _avr_global_logger = std_logger; - -void -avr_global_logger( - struct avr_t* avr, - const int level, - const char * format, - ... ) -{ - va_list args; - va_start(args, format); - if (_avr_global_logger) - _avr_global_logger(avr, level, format, args); - va_end(args); -} - -void -avr_global_logger_set( - avr_logger_p logger) -{ - _avr_global_logger = logger ? logger : std_logger; -} - -avr_logger_p -avr_global_logger_get(void) -{ - return _avr_global_logger; -} - -uint64_t -avr_get_time_stamp( - avr_t * avr ) -{ - uint64_t stamp; -#ifndef CLOCK_MONOTONIC_RAW - /* CLOCK_MONOTONIC_RAW isn't portable, here is the POSIX alternative. - * Only downside is that it will drift if the system clock changes */ - struct timeval tv; - gettimeofday(&tv, NULL); - stamp = (((uint64_t)tv.tv_sec) * 1E9) + (tv.tv_usec * 1000); -#else - struct timespec tp; - clock_gettime(CLOCK_MONOTONIC_RAW, &tp); - stamp = (tp.tv_sec * 1E9) + tp.tv_nsec; -#endif - if (!avr->time_base) - avr->time_base = stamp; - return stamp - avr->time_base; -} - -int -avr_init( - avr_t * avr) -{ - avr->flash = malloc(avr->flashend + 4); - memset(avr->flash, 0xff, avr->flashend + 1); - *((uint16_t*)&avr->flash[avr->flashend + 1]) = AVR_OVERFLOW_OPCODE; - avr->codeend = avr->flashend; - avr->data = malloc(avr->ramend + 1); - memset(avr->data, 0, avr->ramend + 1); -#ifdef CONFIG_SIMAVR_TRACE - avr->trace_data = calloc(1, sizeof(struct avr_trace_data_t)); -#endif - - AVR_LOG(avr, LOG_TRACE, "%s init\n", avr->mmcu); - - // cpu is in limbo before init is finished. - avr->state = cpu_Limbo; - avr->frequency = 1000000; // can be overridden via avr_mcu_section - avr_cmd_init(avr); - avr_interrupt_init(avr); - if (avr->custom.init) - avr->custom.init(avr, avr->custom.data); - if (avr->init) - avr->init(avr); - // set default (non gdb) fast callbacks - avr->run = avr_callback_run_raw; - avr->sleep = avr_callback_sleep_raw; - // number of address bytes to push/pull on/off the stack - avr->address_size = avr->eind ? 3 : 2; - avr->log = 1; - avr_reset(avr); - avr_regbit_set(avr, avr->reset_flags.porf); // by default set to power-on reset - return 0; -} - -void -avr_terminate( - avr_t * avr) -{ - if (avr->custom.deinit) - avr->custom.deinit(avr, avr->custom.data); - if (avr->gdb) { - avr_deinit_gdb(avr); - avr->gdb = NULL; - } - if (avr->vcd) { - avr_vcd_close(avr->vcd); - avr->vcd = NULL; - } - avr_deallocate_ios(avr); - - if (avr->flash) free(avr->flash); - if (avr->data) free(avr->data); - if (avr->io_console_buffer.buf) { - avr->io_console_buffer.len = 0; - avr->io_console_buffer.size = 0; - free(avr->io_console_buffer.buf); - avr->io_console_buffer.buf = NULL; - } - avr->flash = avr->data = NULL; -} - -void -avr_reset( - avr_t * avr) -{ - AVR_LOG(avr, LOG_TRACE, "%s reset\n", avr->mmcu); - - avr->state = cpu_Running; - for(int i = 0x20; i <= avr->ioend; i++) - avr->data[i] = 0; - _avr_sp_set(avr, avr->ramend); - avr->pc = avr->reset_pc; // Likely to be zero - for (int i = 0; i < 8; i++) - avr->sreg[i] = 0; - avr_interrupt_reset(avr); - avr_cycle_timer_reset(avr); - if (avr->reset) - avr->reset(avr); - avr_io_t * port = avr->io_port; - while (port) { - if (port->reset) - port->reset(port); - port = port->next; - } - avr->cycle = 0; // Prevent crash -} - -void -avr_sadly_crashed( - avr_t *avr, - uint8_t signal) -{ - AVR_LOG(avr, LOG_ERROR, "%s\n", __FUNCTION__); - avr->state = cpu_Stopped; - if (avr->gdb_port) { - // enable gdb server, and wait - if (!avr->gdb) - avr_gdb_init(avr); - } - if (!avr->gdb) - avr->state = cpu_Crashed; -} - -void -avr_set_command_register( - avr_t * avr, - avr_io_addr_t addr) -{ - avr_cmd_set_register(avr, addr); -} - -static void -_avr_io_console_write( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - if (v == '\r' && avr->io_console_buffer.buf) { - avr->io_console_buffer.buf[avr->io_console_buffer.len] = 0; - AVR_LOG(avr, LOG_OUTPUT, "O:" "%s" "" "\n", - avr->io_console_buffer.buf); - avr->io_console_buffer.len = 0; - return; - } - if (avr->io_console_buffer.len + 1 >= avr->io_console_buffer.size) { - avr->io_console_buffer.size += 128; - avr->io_console_buffer.buf = (char*)realloc( - avr->io_console_buffer.buf, - avr->io_console_buffer.size); - } - if (v >= ' ') - avr->io_console_buffer.buf[avr->io_console_buffer.len++] = v; -} - -void -avr_set_console_register( - avr_t * avr, - avr_io_addr_t addr) -{ - if (addr) - avr_register_io_write(avr, addr, _avr_io_console_write, NULL); -} - -void -avr_loadcode( - avr_t * avr, - uint8_t * code, - uint32_t size, - avr_flashaddr_t address) -{ - if ((address + size) > avr->flashend+1) { - AVR_LOG(avr, LOG_ERROR, "avr_loadcode(): Attempted to load code of size %d but flash size is only %d.\n", - size, avr->flashend + 1); - abort(); - } - memcpy(avr->flash + address, code, size); -} - -/** - * Accumulates sleep requests (and returns a sleep time of 0) until - * a minimum count of requested sleep microseconds are reached - * (low amounts cannot be handled accurately). - */ -uint32_t -avr_pending_sleep_usec( - avr_t * avr, - avr_cycle_count_t howLong) -{ - avr->sleep_usec += avr_cycles_to_usec(avr, howLong); - uint32_t usec = avr->sleep_usec; - if (usec > 200) { - avr->sleep_usec = 0; - return usec; - } - return 0; -} - -void -avr_callback_sleep_gdb( - avr_t * avr, - avr_cycle_count_t howLong) -{ - uint32_t usec = avr_pending_sleep_usec(avr, howLong); - while (avr_gdb_processor(avr, usec)) - ; -} - -void -avr_callback_run_gdb( - avr_t * avr) -{ - avr_gdb_processor(avr, avr->state == cpu_Stopped ? 50000 : 0); - - if (avr->state == cpu_Stopped) - return ; - - // if we are stepping one instruction, we "run" for one.. - int step = avr->state == cpu_Step; - if (step) - avr->state = cpu_Running; - - avr_flashaddr_t new_pc = avr->pc; - - if (avr->state == cpu_Running) { - new_pc = avr_run_one(avr); -#if CONFIG_SIMAVR_TRACE - avr_dump_state(avr); -#endif - } - - // run the cycle timers, get the suggested sleep time - // until the next timer is due - avr_cycle_count_t sleep = avr_cycle_timer_process(avr); - - avr->pc = new_pc; - - if (avr->state == cpu_Sleeping) { - if (!avr->sreg[S_I]) { - if (avr->log) - AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); - avr->state = cpu_Done; - return; - } - /* - * try to sleep for as long as we can (?) - */ - avr->sleep(avr, sleep); - avr->cycle += 1 + sleep; - } - // Interrupt servicing might change the PC too, during 'sleep' - if (avr->state == cpu_Running || avr->state == cpu_Sleeping) - avr_service_interrupts(avr); - - // if we were stepping, use this state to inform remote gdb - if (step) - avr->state = cpu_StepDone; -} - -/* -To avoid simulated time and wall clock time to diverge over time -this function tries to keep them in sync (roughly) by sleeping -for the time required to match the expected sleep deadline -in wall clock time. -*/ -void -avr_callback_sleep_raw( - avr_t *avr, - avr_cycle_count_t how_long) -{ - /* figure out how long we should wait to match the sleep deadline */ - uint64_t deadline_ns = avr_cycles_to_nsec(avr, avr->cycle + how_long); - uint64_t runtime_ns = avr_get_time_stamp(avr); - if (runtime_ns >= deadline_ns) - return; - uint64_t sleep_us = (deadline_ns - runtime_ns) / 1000; - usleep(sleep_us); - return; -} - -void -avr_callback_run_raw( - avr_t * avr) -{ - avr_flashaddr_t new_pc = avr->pc; - - if (avr->state == cpu_Running) { - new_pc = avr_run_one(avr); -#if CONFIG_SIMAVR_TRACE - avr_dump_state(avr); -#endif - } - - // run the cycle timers, get the suggested sleep time - // until the next timer is due - avr_cycle_count_t sleep = avr_cycle_timer_process(avr); - - avr->pc = new_pc; - - if (avr->state == cpu_Sleeping) { - if (!avr->sreg[S_I]) { - if (avr->log) - AVR_LOG(avr, LOG_TRACE, "simavr: sleeping with interrupts off, quitting gracefully\n"); - avr->state = cpu_Done; - return; - } - /* - * try to sleep for as long as we can (?) - */ - avr->sleep(avr, sleep); - avr->cycle += 1 + sleep; - } - // Interrupt servicing might change the PC too, during 'sleep' - if (avr->state == cpu_Running || avr->state == cpu_Sleeping) { - /* Note: checking interrupt_state here is completely superfluous, however - as interrupt_state tells us all we really need to know, here - a simple check here may be cheaper than a call not needed. */ - if (avr->interrupt_state) - avr_service_interrupts(avr); - } -} - - -int -avr_run( - avr_t * avr) -{ - avr->run(avr); - return avr->state; -} - -avr_t * -avr_core_allocate( - const avr_t * core, - uint32_t coreLen) -{ - uint8_t * b = malloc(coreLen); - memcpy(b, core, coreLen); - return (avr_t *)b; -} - -avr_t * -avr_make_mcu_by_name( - const char *name) -{ - avr_kind_t * maker = NULL; - for (int i = 0; avr_kind[i] && !maker; i++) { - for (int j = 0; avr_kind[i]->names[j]; j++) - if (!strcmp(avr_kind[i]->names[j], name)) { - maker = avr_kind[i]; - break; - } - } - if (!maker) { - AVR_LOG(((avr_t*)0), LOG_ERROR, "%s: AVR '%s' not known\n", __FUNCTION__, name); - return NULL; - } - - avr_t * avr = maker->make(); - AVR_LOG(avr, LOG_TRACE, "Starting %s - flashend %04x ramend %04x e2end %04x\n", - avr->mmcu, avr->flashend, avr->ramend, avr->e2end); - return avr; -} - -static void -std_logger( - avr_t * avr, - const int level, - const char * format, - va_list ap) -{ - if (!avr || avr->log >= level) { - vfprintf((level < LOG_ERROR) ? stdout : stderr, format, ap); - } -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.h deleted file mode 100644 index e9a97cd..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr.h +++ /dev/null @@ -1,517 +0,0 @@ -/* - sim_avr.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_AVR_H__ -#define __SIM_AVR_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif - -#if __has_attribute(fallthrough) - #define FALLTHROUGH __attribute__((fallthrough)); -#else - #define FALLTHROUGH -#endif - -#include "sim_irq.h" -#include "sim_interrupts.h" -#include "sim_cmds.h" -#include "sim_cycle_timers.h" - -typedef uint32_t avr_flashaddr_t; - -struct avr_t; -typedef uint8_t (*avr_io_read_t)( - struct avr_t * avr, - avr_io_addr_t addr, - void * param); -typedef void (*avr_io_write_t)( - struct avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param); - -enum { - // SREG bit indexes - S_C = 0,S_Z,S_N,S_V,S_S,S_H,S_T,S_I, - - // 16 bits register pairs - R_XL = 0x1a, R_XH,R_YL,R_YH,R_ZL,R_ZH, - // stack pointer - R_SPL = 32+0x3d, R_SPH, - // real SREG - R_SREG = 32+0x3f, - - // maximum number of IO registers, on normal AVRs - MAX_IOs = 280, // Bigger AVRs need more than 256-32 (mega1280) -}; - -#define AVR_DATA_TO_IO(v) ((v) - 32) -#define AVR_IO_TO_DATA(v) ((v) + 32) - -/** - * Logging macros and associated log levels. - * The current log level is kept in avr->log. - */ -enum { - LOG_NONE = 0, - LOG_OUTPUT, - LOG_ERROR, - LOG_WARNING, - LOG_TRACE, - LOG_DEBUG, -}; - - -#ifndef AVR_LOG -#define AVR_LOG(avr, level, ...) \ - do { \ - avr_global_logger(avr, level, __VA_ARGS__); \ - } while(0) -#endif -#define AVR_TRACE(avr, ... ) \ - AVR_LOG(avr, LOG_TRACE, __VA_ARGS__) - -/* - * Core states. - */ -enum { - cpu_Limbo = 0, // before initialization is finished - cpu_Stopped, // all is stopped, timers included - - cpu_Running, // we're free running - - cpu_Sleeping, // we're now sleeping until an interrupt - - cpu_Step, // run ONE instruction, then... - cpu_StepDone, // tell gdb it's all OK, and give it registers - cpu_Done, // avr software stopped gracefully - cpu_Crashed, // avr software crashed (watchdog fired) -}; - -// this is only ever used if CONFIG_SIMAVR_TRACE is defined -struct avr_trace_data_t { - struct avr_symbol_t ** codeline; - - /* DEBUG ONLY - * this keeps track of "jumps" ie, call,jmp,ret,reti and so on - * allows dumping of a meaningful data even if the stack is - * munched and so on - */ - #define OLD_PC_SIZE 32 - struct { - uint32_t pc; - uint16_t sp; - } old[OLD_PC_SIZE]; // catches reset.. - int old_pci; - -#if AVR_STACK_WATCH - #define STACK_FRAME_SIZE 32 - // this records the call/ret pairs, to try to catch - // code that munches the stack -under- their own frame - struct { - uint32_t pc; - uint16_t sp; - } stack_frame[STACK_FRAME_SIZE]; - int stack_frame_index; -#endif - - // DEBUG ONLY - // keeps track of which registers gets touched by instructions - // reset before each new instructions. Allows meaningful traces - uint32_t touched[256 / 32]; // debug -}; - -typedef void (*avr_run_t)( - struct avr_t * avr); - -#define AVR_FUSE_LOW 0 -#define AVR_FUSE_HIGH 1 -#define AVR_FUSE_EXT 2 - -#define REG_NAME_COUNT (256 + 32) // Size of reg_names table. - -/* - * Main AVR instance. Some of these fields are set by the AVR "Core" definition files - * the rest is runtime data (as little as possible) - */ -typedef struct avr_t { - const char * mmcu; // name of the AVR - // these are filled by sim_core_declare from constants in /usr/lib/avr/include/avr/io*.h - uint16_t ioend; - uint16_t ramend; - uint32_t flashend; - uint32_t e2end; - uint8_t vector_size; - uint8_t signature[3]; - uint8_t fuse[6]; - uint8_t lockbits; - avr_io_addr_t rampz; // optional, only for ELPM/SPM on >64Kb cores - avr_io_addr_t eind; // optional, only for EIJMP/EICALL on >64Kb cores - uint8_t address_size; // 2, or 3 for cores >128KB in flash - struct { - avr_regbit_t porf; - avr_regbit_t extrf; - avr_regbit_t borf; - avr_regbit_t wdrf; - } reset_flags; - - // filled by the ELF data, this allow tracking of invalid jumps - uint32_t codeend; - - int state; // stopped, running, sleeping - uint32_t frequency; // frequency we are running at - // mostly used by the ADC for now - uint32_t vcc,avcc,aref; // (optional) voltages in millivolts - - // cycles gets incremented when sleeping and when running; it corresponds - // not only to "cycles that runs" but also "cycles that might have run" - // like, sleeping. - avr_cycle_count_t cycle; // current cycle - - // these next two allow the core to freely run between cycle timers and also allows - // for a maximum run cycle limit... run_cycle_count is set during cycle timer processing. - avr_cycle_count_t run_cycle_count; // cycles to run before next timer - avr_cycle_count_t run_cycle_limit; // maximum run cycle interval limit - - /** - * Sleep requests are accumulated in sleep_usec until the minimum sleep value - * is reached, at which point sleep_usec is cleared and the sleep request - * is passed on to the operating system. - */ - uint32_t sleep_usec; - uint64_t time_base; // for avr_get_time_stamp() - - // called at init time - void (*init)(struct avr_t * avr); - // called at reset time - void (*reset)(struct avr_t * avr); - - struct { - // called at init time (for special purposes like using a - // memory mapped file as flash see: simduino) - void (*init)(struct avr_t * avr, void * data); - // called at termination time ( to clean special initializations) - void (*deinit)(struct avr_t * avr, void * data); - // value passed to init() and deinit() - void *data; - } custom; - - /*! - * Default AVR core run function. - * Two modes are available, a "raw" run that goes as fast as - * it can, and a "gdb" mode that also watchouts for gdb events - * and is a little bit slower. - */ - avr_run_t run; - - /*! - * Sleep default behaviour. - * In "raw" mode, it calls usleep, in gdb mode, it waits - * for howLong for gdb command on it's sockets. - */ - void (*sleep)(struct avr_t * avr, avr_cycle_count_t howLong); - - /*! - * Every IRQs will be stored in this pool. It is not - * mandatory (yet) but will allow listing IRQs and their connections - */ - avr_irq_pool_t irq_pool; - - // Mirror of the SREG register, to facilitate the access to bits - // in the opcode decoder. - // This array is re-synthesized back/forth when SREG changes - uint8_t sreg[8]; - - /* Interrupt state: - 00: idle (no wait, no pending interrupts) or disabled - <0: wait till zero - >0: interrupt pending */ - int8_t interrupt_state; // interrupt state - - /* - * ** current PC ** - * Note that the PC is representing /bytes/ while the AVR value is - * assumed to be "words". This is in line with what GDB does... - * this is why you will see >>1 and <<1 in the decoder to handle jumps. - * It CAN be a little confusing, so concentrate, young grasshopper. - */ - avr_flashaddr_t pc; - /* - * Reset PC, this is the value used to jump to at reset time, this - * allow support for bootloaders - */ - avr_flashaddr_t reset_pc; - - /* - * callback when specific IO registers are read/written. - * There is one drawback here, there is in way of knowing what is the - * "beginning of useful sram" on a core, so there is no way to deduce - * what is the maximum IO register for a core, and thus, we can't - * allocate this table dynamically. - * If you wanted to emulate the BIG AVRs, and XMegas, this would need - * work. - */ - struct { - struct avr_irq_t * irq; // optional, used only if asked for with avr_iomem_getirq() - struct { - void * param; - avr_io_read_t c; - } r; - struct { - void * param; - avr_io_write_t c; - } w; - } io[MAX_IOs]; - - /* - * This block allows sharing of the IO write/read on addresses between - * multiple callbacks. In 99% of case it's not needed, however on the tiny* - * (tiny85 at last) some registers have bits that are used by different - * IO modules. - * If this case is detected, a special "dispatch" callback is installed that - * will handle this particular case, without impacting the performance of the - * other, normal cases... - */ - int io_shared_io_count; - struct { - int used; - struct { - void * param; - void * c; - } io[4]; - } io_shared_io[4]; - - // flash memory (initialized to 0xff, and code loaded into it) - uint8_t * flash; - // this is the general purpose registers, IO registers, and SRAM - uint8_t * data; - - // queue of io modules - struct avr_io_t * io_port; - - // Builtin and user-defined commands - avr_cmd_table_t commands; - // cycle timers tracking & delivery - avr_cycle_timer_pool_t cycle_timers; - // interrupt vectors and delivery fifo - avr_int_table_t interrupts; - - // DEBUG ONLY -- value ignored if CONFIG_SIMAVR_TRACE = 0 - uint8_t trace : 1, - log : 4; // log level, default to 1 - - // Only used if CONFIG_SIMAVR_TRACE is defined - struct avr_trace_data_t *trace_data; - - // VALUE CHANGE DUMP file (waveforms) - // this is the VCD file that gets allocated if the - // firmware that is loaded explicitly asks for a trace - // to be generated, and allocates it's own symbols - // using AVR_MMCU_TAG_VCD_TRACE (see avr_mcu_section.h) - struct avr_vcd_t * vcd; - - // gdb hooking structure. Only present when gdb server is active - struct avr_gdb_t * gdb; - - // if non-zero, the gdb server will be started when the core - // crashed even if not activated at startup - // if zero, the simulator will just exit() in case of a crash - int gdb_port; - - // buffer for console debugging output from register - struct { - char * buf; - uint32_t size; - uint32_t len; - } io_console_buffer; -} avr_t; - - -// this is a static constructor for each of the AVR devices -typedef struct avr_kind_t { - const char * names[4]; // name aliases - avr_t * (*make)(void); -} avr_kind_t; - -// a symbol loaded from the .elf file -typedef struct avr_symbol_t { - uint32_t addr; - uint32_t size; - const char symbol[0]; -} avr_symbol_t; - -// locate the maker for mcu "name" and allocates a new avr instance -avr_t * -avr_make_mcu_by_name( - const char *name); -// initializes a new AVR instance. Will call the IO registers init(), and then reset() -int -avr_init( - avr_t * avr); -// Used by the cores, allocated a mutable avr_t from the const global -avr_t * -avr_core_allocate( - const avr_t * core, - uint32_t coreLen); - -// resets the AVR, and the IO modules -void -avr_reset( - avr_t * avr); -// run one cycle of the AVR, sleep if necessary -int -avr_run( - avr_t * avr); -// finish any pending operations -void -avr_terminate( - avr_t * avr); - -// set an IO register to receive commands from the AVR firmware -// it's optional, and uses the ELF tags -void -avr_set_command_register( - avr_t * avr, - avr_io_addr_t addr); - -// specify the "console register" -- output sent to this register -// is printed on the simulator console, without using a UART -void -avr_set_console_register( - avr_t * avr, - avr_io_addr_t addr); - -// load code in the "flash" -void -avr_loadcode( - avr_t * avr, - uint8_t * code, - uint32_t size, - avr_flashaddr_t address); - -/* - * These are accessors for avr->data but allows watchpoints to be set for gdb - * IO modules use that to set values to registers, and the AVR core decoder uses - * that to register "public" read by instructions. - */ -void -avr_core_watch_write( - avr_t *avr, - uint16_t addr, - uint8_t v); -uint8_t -avr_core_watch_read( - avr_t *avr, - uint16_t addr); - -// called when the core has detected a crash somehow. -// this might activate gdb server -void -avr_sadly_crashed( - avr_t *avr, - uint8_t signal); - -/* - * Logs a message using the current logger - */ -void -avr_global_logger( - struct avr_t* avr, - const int level, - const char * format, - ... ); - -#ifndef AVR_CORE -#include -/* - * Type for custom logging functions - */ -typedef void (*avr_logger_p)(struct avr_t* avr, const int level, const char * format, va_list ap); - -/* Sets a global logging function in place of the default */ -void -avr_global_logger_set( - avr_logger_p logger); -/* Gets the current global logger function */ -avr_logger_p -avr_global_logger_get(void); -#endif - -/* - * These are callbacks for the two 'main' behaviour in simavr - */ -void avr_callback_sleep_gdb(avr_t * avr, avr_cycle_count_t howLong); -void avr_callback_run_gdb(avr_t * avr); -void avr_callback_sleep_raw(avr_t * avr, avr_cycle_count_t howLong); -void avr_callback_run_raw(avr_t * avr); - -/** - * Accumulates sleep requests (and returns a sleep time of 0) until - * a minimum count of requested sleep microseconds are reached - * (low amounts cannot be handled accurately). - * This function is an utility function for the sleep callbacks - */ -uint32_t -avr_pending_sleep_usec( - avr_t * avr, - avr_cycle_count_t howLong); -/* Return the number of 'real time' spent since sim started, in uS */ -uint64_t -avr_get_time_stamp( - avr_t * avr ); - -#ifdef __cplusplus -}; -#endif - -#include "sim_io.h" -#include "sim_regbit.h" - -#ifdef __GNUC__ - -# ifndef likely -# define likely(x) __builtin_expect(!!(x), 1) -# endif - -# ifndef unlikely -# define unlikely(x) __builtin_expect(!!(x), 0) -# endif - -#else /* ! __GNUC__ */ - -# ifndef likely -# define likely(x) x -# endif - -# ifndef unlikely -# define unlikely(x) x -# endif - -#endif /* __GNUC__ */ - -#endif /*__SIM_AVR_H__*/ - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr_types.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr_types.h deleted file mode 100644 index b15bafc..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_avr_types.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - sim_avr_types.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __SIM_AVR_TYPES_H___ -#define __SIM_AVR_TYPES_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -typedef uint64_t avr_cycle_count_t; -typedef uint16_t avr_io_addr_t; - -/* - * this 'structure' is a packed representation of an IO register 'bit' - * (or consecutive bits). This allows a way to set/get/clear them. - * gcc is happy passing these as register value, so you don't need to - * use a pointer when passing them along to functions. - * - * 9 bits ought to be enough, as it's the maximum I've seen (atmega2560) - */ -typedef struct avr_regbit_t { - uint32_t reg : 9, bit : 3, mask : 8; -} avr_regbit_t; - -// printf() conversion specifier for avr_cycle_count_t -#define PRI_avr_cycle_count PRIu64 - -struct avr_t; - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_AVR_TYPES_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.c deleted file mode 100644 index 587f259..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - sim_cmds.c - - Copyright 2014 Florian Albrechtskirchinger - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include -#include -#include "sim_avr.h" -#include "sim_cmds.h" -#include "sim_vcd_file.h" -#include "avr_uart.h" -#include "avr/avr_mcu_section.h" - -#define LOG_PREFIX "CMDS: " - -static void -_avr_cmd_io_write( - avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - avr_cmd_table_t * commands = &avr->commands; - avr_cmd_t * command = commands->pending; - - AVR_LOG(avr, LOG_TRACE, LOG_PREFIX "%s: 0x%02x\n", __FUNCTION__, v); - - if (!command) { - if (v > MAX_AVR_COMMANDS) { - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: code 0x%02x outside permissible range (>0x%02x)\n", - __FUNCTION__, v, MAX_AVR_COMMANDS - 1); - return; - } - command = &commands->table[v]; - } - if (!command->handler) { - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: code 0x%02x has no handler (wrong MMCU config)\n", - __FUNCTION__, v); - return; - } - - if (command) { - if (command->handler(avr, v, command->param)) - commands->pending = command; - else - commands->pending = NULL; - } else - AVR_LOG(avr, LOG_TRACE, LOG_PREFIX "%s: unknown command 0x%02x\n", - __FUNCTION__, v); -} - -void -avr_cmd_set_register( - avr_t * avr, - avr_io_addr_t addr) -{ - if (addr) - avr_register_io_write(avr, addr, &_avr_cmd_io_write, NULL); -} - -void -avr_cmd_register( - avr_t * avr, - uint8_t code, - avr_cmd_handler_t handler, - void * param) -{ - avr_cmd_table_t * commands = &avr->commands; - avr_cmd_t * command; - - if (!handler) - return; - - if (code > MAX_AVR_COMMANDS) { - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: code 0x%02x outside permissible range (>0x%02x)\n", - __FUNCTION__, code, MAX_AVR_COMMANDS - 1); - return; - } - - command = &commands->table[code]; - if (command->handler) { - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: code 0x%02x is already registered\n", - __FUNCTION__, code); - return; - } - - command->handler = handler; - command->param = param; -} - -void -avr_cmd_unregister( - avr_t * avr, - uint8_t code) -{ - avr_cmd_table_t * commands = &avr->commands; - avr_cmd_t * command; - - if (code > MAX_AVR_COMMANDS) { - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: code 0x%02x outside permissible range (>0x%02x)\n", - __FUNCTION__, code, MAX_AVR_COMMANDS - 1); - return; - } - - command = &commands->table[code]; - if (command->handler) { - if(command->param) - free(command->param); - - command->handler = NULL; - command->param = NULL; - } else - AVR_LOG(avr, LOG_ERROR, LOG_PREFIX - "%s: no command registered for code 0x%02x\n", - __FUNCTION__, code); -} - -static int -_simavr_cmd_vcd_start_trace( - avr_t * avr, - uint8_t v, - void * param) -{ - if (avr->vcd) - avr_vcd_start(avr->vcd); - - return 0; -} - -static int -_simavr_cmd_vcd_stop_trace( - avr_t * avr, - uint8_t v, - void * param) -{ - if (avr->vcd) - avr_vcd_stop(avr->vcd); - - return 0; -} - -static int -_simavr_cmd_uart_loopback( - avr_t * avr, - uint8_t v, - void * param) -{ - avr_irq_t * src = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_OUTPUT); - avr_irq_t * dst = avr_io_getirq(avr, AVR_IOCTL_UART_GETIRQ('0'), UART_IRQ_INPUT); - - if(src && dst) { - AVR_LOG(avr, LOG_TRACE, LOG_PREFIX - "%s: activating uart local echo; IRQ src %p dst %p\n", - __FUNCTION__, src, dst); - avr_connect_irq(src, dst); - } - - return 0; -} - -void -avr_cmd_init( - avr_t * avr) -{ - memset(&avr->commands, 0, sizeof(avr->commands)); - - // Register builtin commands - avr_cmd_register(avr, SIMAVR_CMD_VCD_START_TRACE, &_simavr_cmd_vcd_start_trace, NULL); - avr_cmd_register(avr, SIMAVR_CMD_VCD_STOP_TRACE, &_simavr_cmd_vcd_stop_trace, NULL); - avr_cmd_register(avr, SIMAVR_CMD_UART_LOOPBACK, &_simavr_cmd_uart_loopback, NULL); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.h deleted file mode 100644 index aac75fc..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cmds.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - sim_cmds.h - - Copyright 2014 Florian Albrechtskirchinger - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#pragma once - -#include "sim_avr_types.h" - -#define MAX_AVR_COMMANDS 32 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef int (*avr_cmd_handler_t)( - struct avr_t * avr, - uint8_t v, - void * param); - -typedef struct avr_cmd_t { - avr_cmd_handler_t handler; - void * param; -} avr_cmd_t; - -typedef struct avr_cmd_table_t { - avr_cmd_t table[MAX_AVR_COMMANDS]; - avr_cmd_t * pending; // Holds a reference to a pending multi-byte command -} avr_cmd_table_t; - -// Called by avr_set_command_register() -void -avr_cmd_set_register( - struct avr_t * avr, - avr_io_addr_t addr); - -/* - * Register a command distinguished by 'code'. - * - * When 'code' is written to the configured IO address, 'handler' is executed - * with the value written, as well as 'param'. - * 'handler' can return non-zero, to indicate, that this is a multi-byte command. - * Subsequent writes are then dispatched to the same handler, until 0 is returned. - */ -void -avr_cmd_register( - struct avr_t * avr, - uint8_t code, - avr_cmd_handler_t handler, - void * param); - -void -avr_cmd_unregister( - struct avr_t * avr, - uint8_t code); - -// Private functions - -// Called from avr_init() to initialize the avr_cmd_table_t and register builtin commands. -void -avr_cmd_init( - struct avr_t * avr); - -#ifdef __cplusplus -} -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.c deleted file mode 100644 index ab8015c..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.c +++ /dev/null @@ -1,1457 +0,0 @@ -/* - sim_core.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include "sim_avr.h" -#include "sim_core.h" -#include "sim_gdb.h" -#include "avr_flash.h" -#include "avr_watchdog.h" - -// SREG bit names -const char * _sreg_bit_name = "cznvshti"; - -/* - * Handle "touching" registers, marking them changed. - * This is used only for debugging purposes to be able to - * print the effects of each instructions on registers - */ -#if CONFIG_SIMAVR_TRACE - -#define T(w) w - -#define REG_TOUCH(a, r) (a)->trace_data->touched[(r) >> 5] |= (1 << ((r) & 0x1f)) -#define REG_ISTOUCHED(a, r) ((a)->trace_data->touched[(r) >> 5] & (1 << ((r) & 0x1f))) - -/* - * This allows a "special case" to skip instruction tracing when in these - * symbols since printf() is useful to have, but generates a lot of cycles. - */ -int dont_trace(const char * name) -{ - return ( - !strcmp(name, "uart_putchar") || - !strcmp(name, "fputc") || - !strcmp(name, "printf") || - !strcmp(name, "vfprintf") || - !strcmp(name, "__ultoa_invert") || - !strcmp(name, "__prologue_saves__") || - !strcmp(name, "__epilogue_restores__")); -} - -int donttrace = 0; - -#define STATE(_f, args...) { \ - if (avr->trace) {\ - if (avr->trace_data->codeline && avr->trace_data->codeline[avr->pc>>1]) {\ - const char * symn = avr->trace_data->codeline[avr->pc>>1]->symbol; \ - int dont = 0 && dont_trace(symn);\ - if (dont!=donttrace) { \ - donttrace = dont;\ - DUMP_REG();\ - }\ - if (donttrace==0)\ - printf("%04x: %-25s " _f, avr->pc, symn, ## args);\ - } else \ - printf("%s: %04x: " _f, __FUNCTION__, avr->pc, ## args);\ - }\ - } -#define SREG() if (avr->trace && donttrace == 0) {\ - printf("%04x: \t\t\t\t\t\t\t\t\tSREG = ", avr->pc); \ - for (int _sbi = 0; _sbi < 8; _sbi++)\ - printf("%c", avr->sreg[_sbi] ? toupper(_sreg_bit_name[_sbi]) : '.');\ - printf("\n");\ -} - -void crash(avr_t* avr) -{ - DUMP_REG(); - printf("*** CYCLE %" PRI_avr_cycle_count "PC %04x\n", avr->cycle, avr->pc); - - for (int i = OLD_PC_SIZE-1; i > 0; i--) { - int pci = (avr->trace_data->old_pci + i) & 0xf; - printf(FONT_RED "*** %04x: %-25s RESET -%d; sp %04x\n" FONT_DEFAULT, - avr->trace_data->old[pci].pc, avr->trace_data->codeline ? avr->trace_data->codeline[avr->trace_data->old[pci].pc>>1]->symbol : "unknown", OLD_PC_SIZE-i, avr->trace_data->old[pci].sp); - } - - printf("Stack Ptr %04x/%04x = %d \n", _avr_sp_get(avr), avr->ramend, avr->ramend - _avr_sp_get(avr)); - DUMP_STACK(); - - avr_sadly_crashed(avr, 0); -} -#else -#define T(w) -#define REG_TOUCH(a, r) -#define STATE(_f, args...) -#define SREG() - -void crash(avr_t* avr) -{ - avr_sadly_crashed(avr, 0); - -} -#endif - -static inline uint16_t -_avr_flash_read16le( - avr_t * avr, - avr_flashaddr_t addr) -{ - return(avr->flash[addr] | (avr->flash[addr + 1] << 8)); -} - -static inline void _call_register_irqs(avr_t * avr, uint16_t addr) -{ - if (addr > 31 && addr < 31 + MAX_IOs) { - avr_io_addr_t io = AVR_DATA_TO_IO(addr); - - if (avr->io[io].irq) { - uint8_t v = avr->data[addr]; - avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v); - for (int i = 0; i < 8; i++) - avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1); - } - } -} - -void avr_core_watch_write(avr_t *avr, uint16_t addr, uint8_t v) -{ - if (addr > avr->ramend) { - AVR_LOG(avr, LOG_WARNING, - "CORE: *** Wrapping write address " - "PC=%04x SP=%04x O=%04x v=%02x Address %04x %% %04x --> %04x\n", - avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc), v, addr, (avr->ramend + 1), addr % (avr->ramend + 1)); - addr = addr % (avr->ramend + 1); - } - if (addr < 32) { - AVR_LOG(avr, LOG_ERROR, FONT_RED - "CORE: *** Invalid write address PC=%04x SP=%04x O=%04x Address %04x=%02x low registers\n" - FONT_DEFAULT, - avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc), addr, v); - crash(avr); - } -#if AVR_STACK_WATCH - /* - * this checks that the current "function" is not doctoring the stack frame that is located - * higher on the stack than it should be. It's a sign of code that has overrun it's stack - * frame and is munching on it's own return address. - */ - if (avr->trace_data->stack_frame_index > 1 && addr > avr->trace_data->stack_frame[avr->trace_data->stack_frame_index-2].sp) { - printf( FONT_RED "%04x : munching stack " - "SP %04x, A=%04x <= %02x\n" FONT_DEFAULT, - avr->pc, _avr_sp_get(avr), addr, v); - } -#endif - - if (avr->gdb) { - avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_WRITE); - } - - avr->data[addr] = v; - _call_register_irqs(avr, addr); -} - -uint8_t avr_core_watch_read(avr_t *avr, uint16_t addr) -{ - if (addr > avr->ramend) { - AVR_LOG(avr, LOG_WARNING, - "CORE: *** Wrapping read address " - "PC=%04x SP=%04x O=%04x Address %04x %% %04x --> %04x\n" - FONT_DEFAULT, - avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc), - addr, (avr->ramend + 1), addr % (avr->ramend + 1)); - addr = addr % (avr->ramend + 1); - } - - if (avr->gdb) { - avr_gdb_handle_watchpoints(avr, addr, AVR_GDB_WATCH_READ); - } - -// _call_register_irqs(avr, addr); - return avr->data[addr]; -} - -/* - * Set a register (r < 256) - * if it's an IO register (> 31) also (try to) call any callback that was - * registered to track changes to that register. - */ -static inline void _avr_set_r(avr_t * avr, uint16_t r, uint8_t v) -{ - REG_TOUCH(avr, r); - - if (r == R_SREG) { - avr->data[R_SREG] = v; - // unsplit the SREG - SET_SREG_FROM(avr, v); - SREG(); - } - if (r > 31) { - avr_io_addr_t io = AVR_DATA_TO_IO(r); - if (avr->io[io].w.c) { - avr->io[io].w.c(avr, r, v, avr->io[io].w.param); - } else { - avr->data[r] = v; - if (avr->io[io].irq) { - avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v); - for (int i = 0; i < 8; i++) - avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1); - } - } - } else - avr->data[r] = v; -} - -static inline void -_avr_set_r16le( - avr_t * avr, - uint16_t r, - uint16_t v) -{ - _avr_set_r(avr, r, v); - _avr_set_r(avr, r + 1, v >> 8); -} - -static inline void -_avr_set_r16le_hl( - avr_t * avr, - uint16_t r, - uint16_t v) -{ - _avr_set_r(avr, r + 1, v >> 8); - _avr_set_r(avr, r , v); -} - -/* - * Stack pointer access - */ -inline uint16_t _avr_sp_get(avr_t * avr) -{ - return avr->data[R_SPL] | (avr->data[R_SPH] << 8); -} - -inline void _avr_sp_set(avr_t * avr, uint16_t sp) -{ - _avr_set_r16le(avr, R_SPL, sp); -} - -/* - * Set any address to a value; split between registers and SRAM - */ -static inline void _avr_set_ram(avr_t * avr, uint16_t addr, uint8_t v) -{ - if (addr <= avr->ioend) - _avr_set_r(avr, addr, v); - else - avr_core_watch_write(avr, addr, v); -} - -/* - * Get a value from SRAM. - */ -static inline uint8_t _avr_get_ram(avr_t * avr, uint16_t addr) -{ - if (addr == R_SREG) { - /* - * SREG is special it's reconstructed when read - * while the core itself uses the "shortcut" array - */ - READ_SREG_INTO(avr, avr->data[R_SREG]); - - } else if (addr > 31 && addr < 31 + MAX_IOs) { - avr_io_addr_t io = AVR_DATA_TO_IO(addr); - - if (avr->io[io].r.c) - avr->data[addr] = avr->io[io].r.c(avr, addr, avr->io[io].r.param); -#if 0 - if (avr->io[io].irq) { - uint8_t v = avr->data[addr]; - avr_raise_irq(avr->io[io].irq + AVR_IOMEM_IRQ_ALL, v); - for (int i = 0; i < 8; i++) - avr_raise_irq(avr->io[io].irq + i, (v >> i) & 1); - } -#endif - } - return avr_core_watch_read(avr, addr); -} - -/* - * Stack push accessors. - */ -static inline void _avr_push8(avr_t * avr, uint16_t v) -{ - uint16_t sp = _avr_sp_get(avr); - _avr_set_ram(avr, sp, v); - _avr_sp_set(avr, sp-1); -} - -static inline uint8_t _avr_pop8(avr_t * avr) -{ - uint16_t sp = _avr_sp_get(avr) + 1; - uint8_t res = _avr_get_ram(avr, sp); - _avr_sp_set(avr, sp); - return res; -} - -int _avr_push_addr(avr_t * avr, avr_flashaddr_t addr) -{ - uint16_t sp = _avr_sp_get(avr); - addr >>= 1; - for (int i = 0; i < avr->address_size; i++, addr >>= 8, sp--) { - _avr_set_ram(avr, sp, addr); - } - _avr_sp_set(avr, sp); - return avr->address_size; -} - -avr_flashaddr_t _avr_pop_addr(avr_t * avr) -{ - uint16_t sp = _avr_sp_get(avr) + 1; - avr_flashaddr_t res = 0; - for (int i = 0; i < avr->address_size; i++, sp++) { - res = (res << 8) | _avr_get_ram(avr, sp); - } - res <<= 1; - _avr_sp_set(avr, sp -1); - return res; -} - -/* - * "Pretty" register names - */ -const char * reg_names[REG_NAME_COUNT] = { - [R_XH] = "XH", [R_XL] = "XL", - [R_YH] = "YH", [R_YL] = "YL", - [R_ZH] = "ZH", [R_ZL] = "ZL", - [R_SPH] = "SPH", [R_SPL] = "SPL", - [R_SREG] = "SREG", -}; - - -const char * avr_regname(unsigned int reg) -{ - if (!reg_names[reg]) { - char tt[16]; - if (reg < 32) - sprintf(tt, "r%d", reg); - else - sprintf(tt, "io:%02x", reg); - reg_names[reg] = strdup(tt); - } - return reg_names[reg]; -} - -/* - * Called when an invalid opcode is decoded - */ -static void _avr_invalid_opcode(avr_t * avr) -{ -#if CONFIG_SIMAVR_TRACE - printf( FONT_RED "*** %04x: %-25s Invalid Opcode SP=%04x O=%04x \n" FONT_DEFAULT, - avr->pc, avr->trace_data->codeline[avr->pc>>1]->symbol, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc)); -#else - AVR_LOG(avr, LOG_ERROR, FONT_RED "CORE: *** %04x: Invalid Opcode SP=%04x O=%04x \n" FONT_DEFAULT, - avr->pc, _avr_sp_get(avr), _avr_flash_read16le(avr, avr->pc)); -#endif -} - -#if CONFIG_SIMAVR_TRACE -/* - * Dump changed registers when tracing - */ -void avr_dump_state(avr_t * avr) -{ - if (!avr->trace || donttrace) - return; - - int doit = 0; - - for (int r = 0; r < 3 && !doit; r++) - if (avr->trace_data->touched[r]) - doit = 1; - if (!doit) - return; - printf(" ->> "); - const int r16[] = { R_SPL, R_XL, R_YL, R_ZL }; - for (int i = 0; i < 4; i++) - if (REG_ISTOUCHED(avr, r16[i]) || REG_ISTOUCHED(avr, r16[i]+1)) { - REG_TOUCH(avr, r16[i]); - REG_TOUCH(avr, r16[i]+1); - } - - for (int i = 0; i < 3*32; i++) - if (REG_ISTOUCHED(avr, i)) { - printf("%s=%02x ", avr_regname(i), avr->data[i]); - } - printf("\n"); -} -#endif - -#define get_d5(o) \ - const uint8_t d = (o >> 4) & 0x1f; - -#define get_vd5(o) \ - get_d5(o) \ - const uint8_t vd = avr->data[d]; - -#define get_r5(o) \ - const uint8_t r = ((o >> 5) & 0x10) | (o & 0xf); - -#define get_d5_a6(o) \ - get_d5(o); \ - const uint8_t A = ((((o >> 9) & 3) << 4) | ((o) & 0xf)) + 32; - -#define get_vd5_s3(o) \ - get_vd5(o); \ - const uint8_t s = o & 7; - -#define get_vd5_s3_mask(o) \ - get_vd5_s3(o); \ - const uint8_t mask = 1 << s; - -#define get_vd5_vr5(o) \ - get_r5(o); \ - get_d5(o); \ - const uint8_t vd = avr->data[d], vr = avr->data[r]; - -#define get_d5_vr5(o) \ - get_d5(o); \ - get_r5(o); \ - const uint8_t vr = avr->data[r]; - -#define get_h4_k8(o) \ - const uint8_t h = 16 + ((o >> 4) & 0xf); \ - const uint8_t k = ((o & 0x0f00) >> 4) | (o & 0xf); - -#define get_vh4_k8(o) \ - get_h4_k8(o) \ - const uint8_t vh = avr->data[h]; - -#define get_d5_q6(o) \ - get_d5(o) \ - const uint8_t q = ((o & 0x2000) >> 8) | ((o & 0x0c00) >> 7) | (o & 0x7); - -#define get_io5(o) \ - const uint8_t io = ((o >> 3) & 0x1f) + 32; - -#define get_io5_b3(o) \ - get_io5(o); \ - const uint8_t b = o & 0x7; - -#define get_io5_b3mask(o) \ - get_io5(o); \ - const uint8_t mask = 1 << (o & 0x7); - -// const int16_t o = ((int16_t)(op << 4)) >> 3; // CLANG BUG! -#define get_o12(op) \ - const int16_t o = ((int16_t)((op << 4) & 0xffff)) >> 3; - -#define get_vp2_k6(o) \ - const uint8_t p = 24 + ((o >> 3) & 0x6); \ - const uint8_t k = ((o & 0x00c0) >> 2) | (o & 0xf); \ - const uint16_t vp = avr->data[p] | (avr->data[p + 1] << 8); - -#define get_sreg_bit(o) \ - const uint8_t b = (o >> 4) & 7; - -/* - * Add a "jump" address to the jump trace buffer - */ -#if CONFIG_SIMAVR_TRACE -#define TRACE_JUMP()\ - avr->trace_data->old[avr->trace_data->old_pci].pc = avr->pc;\ - avr->trace_data->old[avr->trace_data->old_pci].sp = _avr_sp_get(avr);\ - avr->trace_data->old_pci = (avr->trace_data->old_pci + 1) & (OLD_PC_SIZE-1);\ - -#if AVR_STACK_WATCH -#define STACK_FRAME_PUSH()\ - avr->trace_data->stack_frame[avr->trace_data->stack_frame_index].pc = avr->pc;\ - avr->trace_data->stack_frame[avr->trace_data->stack_frame_index].sp = _avr_sp_get(avr);\ - avr->trace_data->stack_frame_index++; -#define STACK_FRAME_POP()\ - if (avr->trace_data->stack_frame_index > 0) \ - avr->trace_data->stack_frame_index--; -#else -#define STACK_FRAME_PUSH() -#define STACK_FRAME_POP() -#endif -#else /* CONFIG_SIMAVR_TRACE */ - -#define TRACE_JUMP() -#define STACK_FRAME_PUSH() -#define STACK_FRAME_POP() - -#endif - -/****************************************************************************\ - * - * Helper functions for calculating the status register bit values. - * See the Atmel data sheet for the instruction set for more info. - * -\****************************************************************************/ - -static void -_avr_flags_zns (struct avr_t * avr, uint8_t res) -{ - avr->sreg[S_Z] = res == 0; - avr->sreg[S_N] = (res >> 7) & 1; - avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V]; -} - -static void -_avr_flags_zns16 (struct avr_t * avr, uint16_t res) -{ - avr->sreg[S_Z] = res == 0; - avr->sreg[S_N] = (res >> 15) & 1; - avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V]; -} - -static void -_avr_flags_add_zns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr) -{ - /* carry & half carry */ - uint8_t add_carry = (rd & rr) | (rr & ~res) | (~res & rd); - avr->sreg[S_H] = (add_carry >> 3) & 1; - avr->sreg[S_C] = (add_carry >> 7) & 1; - - /* overflow */ - avr->sreg[S_V] = (((rd & rr & ~res) | (~rd & ~rr & res)) >> 7) & 1; - - /* zns */ - _avr_flags_zns(avr, res); -} - - -static void -_avr_flags_sub_zns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr) -{ - /* carry & half carry */ - uint8_t sub_carry = (~rd & rr) | (rr & res) | (res & ~rd); - avr->sreg[S_H] = (sub_carry >> 3) & 1; - avr->sreg[S_C] = (sub_carry >> 7) & 1; - - /* overflow */ - avr->sreg[S_V] = (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1; - - /* zns */ - _avr_flags_zns(avr, res); -} - -static void -_avr_flags_Rzns (struct avr_t * avr, uint8_t res) -{ - if (res) - avr->sreg[S_Z] = 0; - avr->sreg[S_N] = (res >> 7) & 1; - avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V]; -} - -static void -_avr_flags_sub_Rzns (struct avr_t * avr, uint8_t res, uint8_t rd, uint8_t rr) -{ - /* carry & half carry */ - uint8_t sub_carry = (~rd & rr) | (rr & res) | (res & ~rd); - avr->sreg[S_H] = (sub_carry >> 3) & 1; - avr->sreg[S_C] = (sub_carry >> 7) & 1; - - /* overflow */ - avr->sreg[S_V] = (((rd & ~rr & ~res) | (~rd & rr & res)) >> 7) & 1; - - _avr_flags_Rzns(avr, res); -} - -static void -_avr_flags_zcvs (struct avr_t * avr, uint8_t res, uint8_t vr) -{ - avr->sreg[S_Z] = res == 0; - avr->sreg[S_C] = vr & 1; - avr->sreg[S_V] = avr->sreg[S_N] ^ avr->sreg[S_C]; - avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V]; -} - -static void -_avr_flags_zcnvs (struct avr_t * avr, uint8_t res, uint8_t vr) -{ - avr->sreg[S_Z] = res == 0; - avr->sreg[S_C] = vr & 1; - avr->sreg[S_N] = res >> 7; - avr->sreg[S_V] = avr->sreg[S_N] ^ avr->sreg[S_C]; - avr->sreg[S_S] = avr->sreg[S_N] ^ avr->sreg[S_V]; -} - -static void -_avr_flags_znv0s (struct avr_t * avr, uint8_t res) -{ - avr->sreg[S_V] = 0; - _avr_flags_zns(avr, res); -} - -static inline int _avr_is_instruction_32_bits(avr_t * avr, avr_flashaddr_t pc) -{ - uint16_t o = _avr_flash_read16le(avr, pc) & 0xfe0f; - return o == 0x9200 || // STS ! Store Direct to Data Space - o == 0x9000 || // LDS Load Direct from Data Space - o == 0x940c || // JMP Long Jump - o == 0x940d || // JMP Long Jump - o == 0x940e || // CALL Long Call to sub - o == 0x940f; // CALL Long Call to sub -} - -/* - * Main opcode decoder - * - * The decoder was written by following the datasheet in no particular order. - * As I went along, I noticed "bit patterns" that could be used to factor opcodes - * However, a lot of these only became apparent later on, so SOME instructions - * (skip of bit set etc) are compact, and some could use some refactoring (the ALU - * ones scream to be factored). - * I assume that the decoder could easily be 2/3 of it's current size. - * - * + It lacks the "extended" XMega jumps. - * + It also doesn't check whether the core it's - * emulating is supposed to have the fancy instructions, like multiply and such. - * - * The number of cycles taken by instruction has been added, but might not be - * entirely accurate. - */ -avr_flashaddr_t avr_run_one(avr_t * avr) -{ -run_one_again: -#if CONFIG_SIMAVR_TRACE - /* - * this traces spurious reset or bad jumps - */ - if ((avr->pc == 0 && avr->cycle > 0) || avr->pc >= avr->codeend || _avr_sp_get(avr) > avr->ramend) { -// avr->trace = 1; - STATE("RESET\n"); - crash(avr); - } - avr->trace_data->touched[0] = avr->trace_data->touched[1] = avr->trace_data->touched[2] = 0; -#endif - - /* Ensure we don't crash simavr due to a bad instruction reading past - * the end of the flash. - */ - if (unlikely(avr->pc >= avr->flashend)) { - STATE("CRASH\n"); - crash(avr); - return 0; - } - - uint32_t opcode = _avr_flash_read16le(avr, avr->pc); - avr_flashaddr_t new_pc = avr->pc + 2; // future "default" pc - int cycle = 1; - - switch (opcode & 0xf000) { - case 0x0000: { - switch (opcode) { - case 0x0000: { // NOP - STATE("nop\n"); - } break; - default: { - switch (opcode & 0xfc00) { - case 0x0400: { // CPC -- Compare with carry -- 0000 01rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd - vr - avr->sreg[S_C]; - STATE("cpc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - _avr_flags_sub_Rzns(avr, res, vd, vr); - SREG(); - } break; - case 0x0c00: { // ADD -- Add without carry -- 0000 11rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd + vr; - if (r == d) { - STATE("lsl %s[%02x] = %02x\n", avr_regname(d), vd, res & 0xff); - } else { - STATE("add %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - } - _avr_set_r(avr, d, res); - _avr_flags_add_zns(avr, res, vd, vr); - SREG(); - } break; - case 0x0800: { // SBC -- Subtract with carry -- 0000 10rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd - vr - avr->sreg[S_C]; - STATE("sbc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), avr->data[d], avr_regname(r), avr->data[r], res); - _avr_set_r(avr, d, res); - _avr_flags_sub_Rzns(avr, res, vd, vr); - SREG(); - } break; - default: - switch (opcode & 0xff00) { - case 0x0100: { // MOVW -- Copy Register Word -- 0000 0001 dddd rrrr - uint8_t d = ((opcode >> 4) & 0xf) << 1; - uint8_t r = ((opcode) & 0xf) << 1; - STATE("movw %s:%s, %s:%s[%02x%02x]\n", avr_regname(d), avr_regname(d+1), avr_regname(r), avr_regname(r+1), avr->data[r+1], avr->data[r]); - uint16_t vr = avr->data[r] | (avr->data[r + 1] << 8); - _avr_set_r16le(avr, d, vr); - } break; - case 0x0200: { // MULS -- Multiply Signed -- 0000 0010 dddd rrrr - int8_t r = 16 + (opcode & 0xf); - int8_t d = 16 + ((opcode >> 4) & 0xf); - int16_t res = ((int8_t)avr->data[r]) * ((int8_t)avr->data[d]); - STATE("muls %s[%d], %s[%02x] = %d\n", avr_regname(d), ((int8_t)avr->data[d]), avr_regname(r), ((int8_t)avr->data[r]), res); - _avr_set_r16le(avr, 0, res); - avr->sreg[S_C] = (res >> 15) & 1; - avr->sreg[S_Z] = res == 0; - cycle++; - SREG(); - } break; - case 0x0300: { // MUL -- Multiply -- 0000 0011 fddd frrr - int8_t r = 16 + (opcode & 0x7); - int8_t d = 16 + ((opcode >> 4) & 0x7); - int16_t res = 0; - uint8_t c = 0; - T(const char * name = "";) - switch (opcode & 0x88) { - case 0x00: // MULSU -- Multiply Signed Unsigned -- 0000 0011 0ddd 0rrr - res = ((uint8_t)avr->data[r]) * ((int8_t)avr->data[d]); - c = (res >> 15) & 1; - T(name = "mulsu";) - break; - case 0x08: // FMUL -- Fractional Multiply Unsigned -- 0000 0011 0ddd 1rrr - res = ((uint8_t)avr->data[r]) * ((uint8_t)avr->data[d]); - c = (res >> 15) & 1; - res <<= 1; - T(name = "fmul";) - break; - case 0x80: // FMULS -- Multiply Signed -- 0000 0011 1ddd 0rrr - res = ((int8_t)avr->data[r]) * ((int8_t)avr->data[d]); - c = (res >> 15) & 1; - res <<= 1; - T(name = "fmuls";) - break; - case 0x88: // FMULSU -- Multiply Signed Unsigned -- 0000 0011 1ddd 1rrr - res = ((uint8_t)avr->data[r]) * ((int8_t)avr->data[d]); - c = (res >> 15) & 1; - res <<= 1; - T(name = "fmulsu";) - break; - } - cycle++; - STATE("%s %s[%d], %s[%02x] = %d\n", name, avr_regname(d), ((int8_t)avr->data[d]), avr_regname(r), ((int8_t)avr->data[r]), res); - _avr_set_r16le(avr, 0, res); - avr->sreg[S_C] = c; - avr->sreg[S_Z] = res == 0; - SREG(); - } break; - default: _avr_invalid_opcode(avr); - } - } - } - } - } break; - - case 0x1000: { - switch (opcode & 0xfc00) { - case 0x1800: { // SUB -- Subtract without carry -- 0001 10rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd - vr; - STATE("sub %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - _avr_set_r(avr, d, res); - _avr_flags_sub_zns(avr, res, vd, vr); - SREG(); - } break; - case 0x1000: { // CPSE -- Compare, skip if equal -- 0001 00rd dddd rrrr - get_vd5_vr5(opcode); - uint16_t res = vd == vr; - STATE("cpse %s[%02x], %s[%02x]\t; Will%s skip\n", avr_regname(d), avr->data[d], avr_regname(r), avr->data[r], res ? "":" not"); - if (res) { - if (_avr_is_instruction_32_bits(avr, new_pc)) { - new_pc += 4; cycle += 2; - } else { - new_pc += 2; cycle++; - } - } - } break; - case 0x1400: { // CP -- Compare -- 0001 01rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd - vr; - STATE("cp %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - _avr_flags_sub_zns(avr, res, vd, vr); - SREG(); - } break; - case 0x1c00: { // ADD -- Add with carry -- 0001 11rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd + vr + avr->sreg[S_C]; - if (r == d) { - STATE("rol %s[%02x] = %02x\n", avr_regname(d), avr->data[d], res); - } else { - STATE("addc %s[%02x], %s[%02x] = %02x\n", avr_regname(d), avr->data[d], avr_regname(r), avr->data[r], res); - } - _avr_set_r(avr, d, res); - _avr_flags_add_zns(avr, res, vd, vr); - SREG(); - } break; - default: _avr_invalid_opcode(avr); - } - } break; - - case 0x2000: { - switch (opcode & 0xfc00) { - case 0x2000: { // AND -- Logical AND -- 0010 00rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd & vr; - if (r == d) { - STATE("tst %s[%02x]\n", avr_regname(d), avr->data[d]); - } else { - STATE("and %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - } - _avr_set_r(avr, d, res); - _avr_flags_znv0s(avr, res); - SREG(); - } break; - case 0x2400: { // EOR -- Logical Exclusive OR -- 0010 01rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd ^ vr; - if (r==d) { - STATE("clr %s[%02x]\n", avr_regname(d), avr->data[d]); - } else { - STATE("eor %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - } - _avr_set_r(avr, d, res); - _avr_flags_znv0s(avr, res); - SREG(); - } break; - case 0x2800: { // OR -- Logical OR -- 0010 10rd dddd rrrr - get_vd5_vr5(opcode); - uint8_t res = vd | vr; - STATE("or %s[%02x], %s[%02x] = %02x\n", avr_regname(d), vd, avr_regname(r), vr, res); - _avr_set_r(avr, d, res); - _avr_flags_znv0s(avr, res); - SREG(); - } break; - case 0x2c00: { // MOV -- 0010 11rd dddd rrrr - get_d5_vr5(opcode); - uint8_t res = vr; - STATE("mov %s, %s[%02x] = %02x\n", avr_regname(d), avr_regname(r), vr, res); - _avr_set_r(avr, d, res); - } break; - default: _avr_invalid_opcode(avr); - } - } break; - - case 0x3000: { // CPI -- Compare Immediate -- 0011 kkkk hhhh kkkk - get_vh4_k8(opcode); - uint8_t res = vh - k; - STATE("cpi %s[%02x], 0x%02x\n", avr_regname(h), vh, k); - _avr_flags_sub_zns(avr, res, vh, k); - SREG(); - } break; - - case 0x4000: { // SBCI -- Subtract Immediate With Carry -- 0100 kkkk hhhh kkkk - get_vh4_k8(opcode); - uint8_t res = vh - k - avr->sreg[S_C]; - STATE("sbci %s[%02x], 0x%02x = %02x\n", avr_regname(h), vh, k, res); - _avr_set_r(avr, h, res); - _avr_flags_sub_Rzns(avr, res, vh, k); - SREG(); - } break; - - case 0x5000: { // SUBI -- Subtract Immediate -- 0101 kkkk hhhh kkkk - get_vh4_k8(opcode); - uint8_t res = vh - k; - STATE("subi %s[%02x], 0x%02x = %02x\n", avr_regname(h), vh, k, res); - _avr_set_r(avr, h, res); - _avr_flags_sub_zns(avr, res, vh, k); - SREG(); - } break; - - case 0x6000: { // ORI aka SBR -- Logical OR with Immediate -- 0110 kkkk hhhh kkkk - get_vh4_k8(opcode); - uint8_t res = vh | k; - STATE("ori %s[%02x], 0x%02x\n", avr_regname(h), vh, k); - _avr_set_r(avr, h, res); - _avr_flags_znv0s(avr, res); - SREG(); - } break; - - case 0x7000: { // ANDI -- Logical AND with Immediate -- 0111 kkkk hhhh kkkk - get_vh4_k8(opcode); - uint8_t res = vh & k; - STATE("andi %s[%02x], 0x%02x\n", avr_regname(h), vh, k); - _avr_set_r(avr, h, res); - _avr_flags_znv0s(avr, res); - SREG(); - } break; - - case 0xa000: - case 0x8000: { - /* - * Load (LDD/STD) store instructions - * - * 10q0 qqsd dddd yqqq - * s = 0 = load, 1 = store - * y = 16 bits register index, 1 = Y, 0 = X - * q = 6 bit displacement - */ - switch (opcode & 0xd008) { - case 0xa000: - case 0x8000: { // LD (LDD) -- Load Indirect using Z -- 10q0 qqsd dddd yqqq - uint16_t v = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - get_d5_q6(opcode); - if (opcode & 0x0200) { - STATE("st (Z+%d[%04x]), %s[%02x]\n", q, v+q, avr_regname(d), avr->data[d]); - _avr_set_ram(avr, v+q, avr->data[d]); - } else { - STATE("ld %s, (Z+%d[%04x])=[%02x]\n", avr_regname(d), q, v+q, avr->data[v+q]); - _avr_set_r(avr, d, _avr_get_ram(avr, v+q)); - } - cycle += 1; // 2 cycles, 3 for tinyavr - } break; - case 0xa008: - case 0x8008: { // LD (LDD) -- Load Indirect using Y -- 10q0 qqsd dddd yqqq - uint16_t v = avr->data[R_YL] | (avr->data[R_YH] << 8); - get_d5_q6(opcode); - if (opcode & 0x0200) { - STATE("st (Y+%d[%04x]), %s[%02x]\n", q, v+q, avr_regname(d), avr->data[d]); - _avr_set_ram(avr, v+q, avr->data[d]); - } else { - STATE("ld %s, (Y+%d[%04x])=[%02x]\n", avr_regname(d), q, v+q, avr->data[d+q]); - _avr_set_r(avr, d, _avr_get_ram(avr, v+q)); - } - cycle += 1; // 2 cycles, 3 for tinyavr - } break; - default: _avr_invalid_opcode(avr); - } - } break; - - case 0x9000: { - /* this is an annoying special case, but at least these lines handle all the SREG set/clear opcodes */ - if ((opcode & 0xff0f) == 0x9408) { - get_sreg_bit(opcode); - STATE("%s%c\n", opcode & 0x0080 ? "cl" : "se", _sreg_bit_name[b]); - avr_sreg_set(avr, b, (opcode & 0x0080) == 0); - SREG(); - } else switch (opcode) { - case 0x9588: { // SLEEP -- 1001 0101 1000 1000 - STATE("sleep\n"); - /* Don't sleep if there are interrupts about to be serviced. - * Without this check, it was possible to incorrectly enter a state - * in which the cpu was sleeping and interrupts were disabled. For more - * details, see the commit message. */ - if (!avr_has_pending_interrupts(avr) || !avr->sreg[S_I]) - avr->state = cpu_Sleeping; - } break; - case 0x9598: { // BREAK -- 1001 0101 1001 1000 - STATE("break\n"); - if (avr->gdb) { - // if gdb is on, break here. - avr->state = cpu_Stopped; - avr_gdb_handle_break(avr); - } - } break; - case 0x95a8: { // WDR -- Watchdog Reset -- 1001 0101 1010 1000 - STATE("wdr\n"); - avr_ioctl(avr, AVR_IOCTL_WATCHDOG_RESET, 0); - } break; - case 0x95e8: { // SPM -- Store Program Memory -- 1001 0101 1110 1000 - STATE("spm\n"); - avr_ioctl(avr, AVR_IOCTL_FLASH_SPM, 0); - } break; - case 0x9409: // IJMP -- Indirect jump -- 1001 0100 0000 1001 - case 0x9419: // EIJMP -- Indirect jump -- 1001 0100 0001 1001 bit 4 is "indirect" - case 0x9509: // ICALL -- Indirect Call to Subroutine -- 1001 0101 0000 1001 - case 0x9519: { // EICALL -- Indirect Call to Subroutine -- 1001 0101 0001 1001 bit 8 is "push pc" - int e = opcode & 0x10; - int p = opcode & 0x100; - if (e && !avr->eind) - _avr_invalid_opcode(avr); - uint32_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - if (e) - z |= avr->data[avr->eind] << 16; - STATE("%si%s Z[%04x]\n", e?"e":"", p?"call":"jmp", z << 1); - if (p) - cycle += _avr_push_addr(avr, new_pc) - 1; - new_pc = z << 1; - cycle++; - TRACE_JUMP(); - } break; - case 0x9518: // RETI -- Return from Interrupt -- 1001 0101 0001 1000 - avr_sreg_set(avr, S_I, 1); - avr_interrupt_reti(avr); - FALLTHROUGH - case 0x9508: { // RET -- Return -- 1001 0101 0000 1000 - new_pc = _avr_pop_addr(avr); - cycle += 1 + avr->address_size; - STATE("ret%s\n", opcode & 0x10 ? "i" : ""); - TRACE_JUMP(); - STACK_FRAME_POP(); - } break; - case 0x95c8: { // LPM -- Load Program Memory R0 <- (Z) -- 1001 0101 1100 1000 - uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - STATE("lpm %s, (Z[%04x])\n", avr_regname(0), z); - cycle += 2; // 3 cycles - _avr_set_r(avr, 0, avr->flash[z]); - } break; - case 0x95d8: { // ELPM -- Load Program Memory R0 <- (Z) -- 1001 0101 1101 1000 - if (!avr->rampz) - _avr_invalid_opcode(avr); - uint32_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8) | (avr->data[avr->rampz] << 16); - STATE("elpm %s, (Z[%02x:%04x])\n", avr_regname(0), z >> 16, z & 0xffff); - _avr_set_r(avr, 0, avr->flash[z]); - cycle += 2; // 3 cycles - } break; - default: { - switch (opcode & 0xfe0f) { - case 0x9000: { // LDS -- Load Direct from Data Space, 32 bits -- 1001 0000 0000 0000 - get_d5(opcode); - uint16_t x = _avr_flash_read16le(avr, new_pc); - new_pc += 2; - STATE("lds %s[%02x], 0x%04x\n", avr_regname(d), avr->data[d], x); - _avr_set_r(avr, d, _avr_get_ram(avr, x)); - cycle++; // 2 cycles - } break; - case 0x9005: - case 0x9004: { // LPM -- Load Program Memory -- 1001 000d dddd 01oo - get_d5(opcode); - uint16_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8); - int op = opcode & 1; - STATE("lpm %s, (Z[%04x]%s)\n", avr_regname(d), z, op ? "+" : ""); - _avr_set_r(avr, d, avr->flash[z]); - if (op) { - z++; - _avr_set_r16le_hl(avr, R_ZL, z); - } - cycle += 2; // 3 cycles - } break; - case 0x9006: - case 0x9007: { // ELPM -- Extended Load Program Memory -- 1001 000d dddd 01oo - if (!avr->rampz) - _avr_invalid_opcode(avr); - uint32_t z = avr->data[R_ZL] | (avr->data[R_ZH] << 8) | (avr->data[avr->rampz] << 16); - get_d5(opcode); - int op = opcode & 1; - STATE("elpm %s, (Z[%02x:%04x]%s)\n", avr_regname(d), z >> 16, z & 0xffff, op ? "+" : ""); - _avr_set_r(avr, d, avr->flash[z]); - if (op) { - z++; - _avr_set_r(avr, avr->rampz, z >> 16); - _avr_set_r16le_hl(avr, R_ZL, z); - } - cycle += 2; // 3 cycles - } break; - /* - * Load store instructions - * - * 1001 00sr rrrr iioo - * s = 0 = load, 1 = store - * ii = 16 bits register index, 11 = X, 10 = Y, 00 = Z - * oo = 1) post increment, 2) pre-decrement - */ - case 0x900c: - case 0x900d: - case 0x900e: { // LD -- Load Indirect from Data using X -- 1001 000d dddd 11oo - int op = opcode & 3; - get_d5(opcode); - uint16_t x = (avr->data[R_XH] << 8) | avr->data[R_XL]; - STATE("ld %s, %sX[%04x]%s\n", avr_regname(d), op == 2 ? "--" : "", x, op == 1 ? "++" : ""); - cycle++; // 2 cycles (1 for tinyavr, except with inc/dec 2) - if (op == 2) x--; - uint8_t vd = _avr_get_ram(avr, x); - if (op == 1) x++; - _avr_set_r16le_hl(avr, R_XL, x); - _avr_set_r(avr, d, vd); - } break; - case 0x920c: - case 0x920d: - case 0x920e: { // ST -- Store Indirect Data Space X -- 1001 001d dddd 11oo - int op = opcode & 3; - get_vd5(opcode); - uint16_t x = (avr->data[R_XH] << 8) | avr->data[R_XL]; - STATE("st %sX[%04x]%s, %s[%02x] \n", op == 2 ? "--" : "", x, op == 1 ? "++" : "", avr_regname(d), vd); - cycle++; // 2 cycles, except tinyavr - if (op == 2) x--; - _avr_set_ram(avr, x, vd); - if (op == 1) x++; - _avr_set_r16le_hl(avr, R_XL, x); - } break; - case 0x9009: - case 0x900a: { // LD -- Load Indirect from Data using Y -- 1001 000d dddd 10oo - int op = opcode & 3; - get_d5(opcode); - uint16_t y = (avr->data[R_YH] << 8) | avr->data[R_YL]; - STATE("ld %s, %sY[%04x]%s\n", avr_regname(d), op == 2 ? "--" : "", y, op == 1 ? "++" : ""); - cycle++; // 2 cycles, except tinyavr - if (op == 2) y--; - uint8_t vd = _avr_get_ram(avr, y); - if (op == 1) y++; - _avr_set_r16le_hl(avr, R_YL, y); - _avr_set_r(avr, d, vd); - } break; - case 0x9209: - case 0x920a: { // ST -- Store Indirect Data Space Y -- 1001 001d dddd 10oo - int op = opcode & 3; - get_vd5(opcode); - uint16_t y = (avr->data[R_YH] << 8) | avr->data[R_YL]; - STATE("st %sY[%04x]%s, %s[%02x]\n", op == 2 ? "--" : "", y, op == 1 ? "++" : "", avr_regname(d), vd); - cycle++; - if (op == 2) y--; - _avr_set_ram(avr, y, vd); - if (op == 1) y++; - _avr_set_r16le_hl(avr, R_YL, y); - } break; - case 0x9200: { // STS -- Store Direct to Data Space, 32 bits -- 1001 0010 0000 0000 - get_vd5(opcode); - uint16_t x = _avr_flash_read16le(avr, new_pc); - new_pc += 2; - STATE("sts 0x%04x, %s[%02x]\n", x, avr_regname(d), vd); - cycle++; - _avr_set_ram(avr, x, vd); - } break; - case 0x9001: - case 0x9002: { // LD -- Load Indirect from Data using Z -- 1001 000d dddd 00oo - int op = opcode & 3; - get_d5(opcode); - uint16_t z = (avr->data[R_ZH] << 8) | avr->data[R_ZL]; - STATE("ld %s, %sZ[%04x]%s\n", avr_regname(d), op == 2 ? "--" : "", z, op == 1 ? "++" : ""); - cycle++;; // 2 cycles, except tinyavr - if (op == 2) z--; - uint8_t vd = _avr_get_ram(avr, z); - if (op == 1) z++; - _avr_set_r16le_hl(avr, R_ZL, z); - _avr_set_r(avr, d, vd); - } break; - case 0x9201: - case 0x9202: { // ST -- Store Indirect Data Space Z -- 1001 001d dddd 00oo - int op = opcode & 3; - get_vd5(opcode); - uint16_t z = (avr->data[R_ZH] << 8) | avr->data[R_ZL]; - STATE("st %sZ[%04x]%s, %s[%02x] \n", op == 2 ? "--" : "", z, op == 1 ? "++" : "", avr_regname(d), vd); - cycle++; // 2 cycles, except tinyavr - if (op == 2) z--; - _avr_set_ram(avr, z, vd); - if (op == 1) z++; - _avr_set_r16le_hl(avr, R_ZL, z); - } break; - case 0x900f: { // POP -- 1001 000d dddd 1111 - get_d5(opcode); - _avr_set_r(avr, d, _avr_pop8(avr)); - T(uint16_t sp = _avr_sp_get(avr);) - STATE("pop %s (@%04x)[%02x]\n", avr_regname(d), sp, avr->data[sp]); - cycle++; - } break; - case 0x920f: { // PUSH -- 1001 001d dddd 1111 - get_vd5(opcode); - _avr_push8(avr, vd); - T(uint16_t sp = _avr_sp_get(avr);) - STATE("push %s[%02x] (@%04x)\n", avr_regname(d), vd, sp); - cycle++; - } break; - case 0x9400: { // COM -- One's Complement -- 1001 010d dddd 0000 - get_vd5(opcode); - uint8_t res = 0xff - vd; - STATE("com %s[%02x] = %02x\n", avr_regname(d), vd, res); - _avr_set_r(avr, d, res); - _avr_flags_znv0s(avr, res); - avr->sreg[S_C] = 1; - SREG(); - } break; - case 0x9401: { // NEG -- Two's Complement -- 1001 010d dddd 0001 - get_vd5(opcode); - uint8_t res = 0x00 - vd; - STATE("neg %s[%02x] = %02x\n", avr_regname(d), vd, res); - _avr_set_r(avr, d, res); - avr->sreg[S_H] = ((res >> 3) | (vd >> 3)) & 1; - avr->sreg[S_V] = res == 0x80; - avr->sreg[S_C] = res != 0; - _avr_flags_zns(avr, res); - SREG(); - } break; - case 0x9402: { // SWAP -- Swap Nibbles -- 1001 010d dddd 0010 - get_vd5(opcode); - uint8_t res = (vd >> 4) | (vd << 4) ; - STATE("swap %s[%02x] = %02x\n", avr_regname(d), vd, res); - _avr_set_r(avr, d, res); - } break; - case 0x9403: { // INC -- Increment -- 1001 010d dddd 0011 - get_vd5(opcode); - uint8_t res = vd + 1; - STATE("inc %s[%02x] = %02x\n", avr_regname(d), vd, res); - _avr_set_r(avr, d, res); - avr->sreg[S_V] = res == 0x80; - _avr_flags_zns(avr, res); - SREG(); - } break; - case 0x9405: { // ASR -- Arithmetic Shift Right -- 1001 010d dddd 0101 - get_vd5(opcode); - uint8_t res = (vd >> 1) | (vd & 0x80); - STATE("asr %s[%02x]\n", avr_regname(d), vd); - _avr_set_r(avr, d, res); - _avr_flags_zcnvs(avr, res, vd); - SREG(); - } break; - case 0x9406: { // LSR -- Logical Shift Right -- 1001 010d dddd 0110 - get_vd5(opcode); - uint8_t res = vd >> 1; - STATE("lsr %s[%02x]\n", avr_regname(d), vd); - _avr_set_r(avr, d, res); - avr->sreg[S_N] = 0; - _avr_flags_zcvs(avr, res, vd); - SREG(); - } break; - case 0x9407: { // ROR -- Rotate Right -- 1001 010d dddd 0111 - get_vd5(opcode); - uint8_t res = (avr->sreg[S_C] ? 0x80 : 0) | vd >> 1; - STATE("ror %s[%02x]\n", avr_regname(d), vd); - _avr_set_r(avr, d, res); - _avr_flags_zcnvs(avr, res, vd); - SREG(); - } break; - case 0x940a: { // DEC -- Decrement -- 1001 010d dddd 1010 - get_vd5(opcode); - uint8_t res = vd - 1; - STATE("dec %s[%02x] = %02x\n", avr_regname(d), vd, res); - _avr_set_r(avr, d, res); - avr->sreg[S_V] = res == 0x7f; - _avr_flags_zns(avr, res); - SREG(); - } break; - case 0x940c: - case 0x940d: { // JMP -- Long Call to sub, 32 bits -- 1001 010a aaaa 110a - avr_flashaddr_t a = ((opcode & 0x01f0) >> 3) | (opcode & 1); - uint16_t x = _avr_flash_read16le(avr, new_pc); - a = (a << 16) | x; - STATE("jmp 0x%06x\n", a); - new_pc = a << 1; - cycle += 2; - TRACE_JUMP(); - } break; - case 0x940e: - case 0x940f: { // CALL -- Long Call to sub, 32 bits -- 1001 010a aaaa 111a - avr_flashaddr_t a = ((opcode & 0x01f0) >> 3) | (opcode & 1); - uint16_t x = _avr_flash_read16le(avr, new_pc); - a = (a << 16) | x; - STATE("call 0x%06x\n", a); - new_pc += 2; - cycle += 1 + _avr_push_addr(avr, new_pc); - new_pc = a << 1; - TRACE_JUMP(); - STACK_FRAME_PUSH(); - } break; - - default: { - switch (opcode & 0xff00) { - case 0x9600: { // ADIW -- Add Immediate to Word -- 1001 0110 KKpp KKKK - get_vp2_k6(opcode); - uint16_t res = vp + k; - STATE("adiw %s:%s[%04x], 0x%02x\n", avr_regname(p), avr_regname(p + 1), vp, k); - _avr_set_r16le_hl(avr, p, res); - avr->sreg[S_V] = ((~vp & res) >> 15) & 1; - avr->sreg[S_C] = ((~res & vp) >> 15) & 1; - _avr_flags_zns16(avr, res); - SREG(); - cycle++; - } break; - case 0x9700: { // SBIW -- Subtract Immediate from Word -- 1001 0111 KKpp KKKK - get_vp2_k6(opcode); - uint16_t res = vp - k; - STATE("sbiw %s:%s[%04x], 0x%02x\n", avr_regname(p), avr_regname(p + 1), vp, k); - _avr_set_r16le_hl(avr, p, res); - avr->sreg[S_V] = ((vp & ~res) >> 15) & 1; - avr->sreg[S_C] = ((res & ~vp) >> 15) & 1; - _avr_flags_zns16(avr, res); - SREG(); - cycle++; - } break; - case 0x9800: { // CBI -- Clear Bit in I/O Register -- 1001 1000 AAAA Abbb - get_io5_b3mask(opcode); - uint8_t res = _avr_get_ram(avr, io) & ~mask; - STATE("cbi %s[%04x], 0x%02x = %02x\n", avr_regname(io), avr->data[io], mask, res); - _avr_set_ram(avr, io, res); - cycle++; - } break; - case 0x9900: { // SBIC -- Skip if Bit in I/O Register is Cleared -- 1001 1001 AAAA Abbb - get_io5_b3mask(opcode); - uint8_t res = _avr_get_ram(avr, io) & mask; - STATE("sbic %s[%04x], 0x%02x\t; Will%s branch\n", avr_regname(io), avr->data[io], mask, !res?"":" not"); - if (!res) { - if (_avr_is_instruction_32_bits(avr, new_pc)) { - new_pc += 4; cycle += 2; - } else { - new_pc += 2; cycle++; - } - } - } break; - case 0x9a00: { // SBI -- Set Bit in I/O Register -- 1001 1010 AAAA Abbb - get_io5_b3mask(opcode); - uint8_t res = _avr_get_ram(avr, io) | mask; - STATE("sbi %s[%04x], 0x%02x = %02x\n", avr_regname(io), avr->data[io], mask, res); - _avr_set_ram(avr, io, res); - cycle++; - } break; - case 0x9b00: { // SBIS -- Skip if Bit in I/O Register is Set -- 1001 1011 AAAA Abbb - get_io5_b3mask(opcode); - uint8_t res = _avr_get_ram(avr, io) & mask; - STATE("sbis %s[%04x], 0x%02x\t; Will%s branch\n", avr_regname(io), avr->data[io], mask, res?"":" not"); - if (res) { - if (_avr_is_instruction_32_bits(avr, new_pc)) { - new_pc += 4; cycle += 2; - } else { - new_pc += 2; cycle++; - } - } - } break; - default: - switch (opcode & 0xfc00) { - case 0x9c00: { // MUL -- Multiply Unsigned -- 1001 11rd dddd rrrr - get_vd5_vr5(opcode); - uint16_t res = vd * vr; - STATE("mul %s[%02x], %s[%02x] = %04x\n", avr_regname(d), vd, avr_regname(r), vr, res); - cycle++; - _avr_set_r16le(avr, 0, res); - avr->sreg[S_Z] = res == 0; - avr->sreg[S_C] = (res >> 15) & 1; - SREG(); - } break; - default: _avr_invalid_opcode(avr); - } - } - } break; - } - } break; - } - } break; - - case 0xb000: { - switch (opcode & 0xf800) { - case 0xb800: { // OUT A,Rr -- 1011 1AAd dddd AAAA - get_d5_a6(opcode); - STATE("out %s, %s[%02x]\n", avr_regname(A), avr_regname(d), avr->data[d]); - _avr_set_ram(avr, A, avr->data[d]); - } break; - case 0xb000: { // IN Rd,A -- 1011 0AAd dddd AAAA - get_d5_a6(opcode); - STATE("in %s, %s[%02x]\n", avr_regname(d), avr_regname(A), avr->data[A]); - _avr_set_r(avr, d, _avr_get_ram(avr, A)); - } break; - default: _avr_invalid_opcode(avr); - } - } break; - - case 0xc000: { // RJMP -- 1100 kkkk kkkk kkkk - get_o12(opcode); - STATE("rjmp .%d [%04x]\n", o >> 1, new_pc + o); - new_pc = (new_pc + o) % (avr->flashend+1); - cycle++; - TRACE_JUMP(); - } break; - - case 0xd000: { // RCALL -- 1101 kkkk kkkk kkkk - get_o12(opcode); - STATE("rcall .%d [%04x]\n", o >> 1, new_pc + o); - cycle += _avr_push_addr(avr, new_pc); - new_pc = (new_pc + o) % (avr->flashend+1); - // 'rcall .1' is used as a cheap "push 16 bits of room on the stack" - if (o != 0) { - TRACE_JUMP(); - STACK_FRAME_PUSH(); - } - } break; - - case 0xe000: { // LDI Rd, K aka SER (LDI r, 0xff) -- 1110 kkkk dddd kkkk - get_h4_k8(opcode); - STATE("ldi %s, 0x%02x\n", avr_regname(h), k); - _avr_set_r(avr, h, k); - } break; - - case 0xf000: { - switch (opcode & 0xfe00) { - case 0xf100: { /* simavr special opcodes */ - if (opcode == 0xf1f1) { // AVR_OVERFLOW_OPCODE - printf("FLASH overflow, soft reset\n"); - new_pc = 0; - TRACE_JUMP(); - } - } break; - case 0xf000: - case 0xf200: - case 0xf400: - case 0xf600: { // BRXC/BRXS -- All the SREG branches -- 1111 0Boo oooo osss - int16_t o = ((int16_t)(opcode << 6)) >> 9; // offset - uint8_t s = opcode & 7; - int set = (opcode & 0x0400) == 0; // this bit means BRXC otherwise BRXS - int branch = (avr->sreg[s] && set) || (!avr->sreg[s] && !set); - const char *names[2][8] = { - { "brcc", "brne", "brpl", "brvc", NULL, "brhc", "brtc", "brid"}, - { "brcs", "breq", "brmi", "brvs", NULL, "brhs", "brts", "brie"}, - }; - if (names[set][s]) { - STATE("%s .%d [%04x]\t; Will%s branch\n", names[set][s], o, new_pc + (o << 1), branch ? "":" not"); - } else { - STATE("%s%c .%d [%04x]\t; Will%s branch\n", set ? "brbs" : "brbc", _sreg_bit_name[s], o, new_pc + (o << 1), branch ? "":" not"); - } - if (branch) { - cycle++; // 2 cycles if taken, 1 otherwise - new_pc = new_pc + (o << 1); - } - } break; - case 0xf800: - case 0xf900: { // BLD -- Bit Store from T into a Bit in Register -- 1111 100d dddd 0bbb - get_vd5_s3_mask(opcode); - uint8_t v = (vd & ~mask) | (avr->sreg[S_T] ? mask : 0); - STATE("bld %s[%02x], 0x%02x = %02x\n", avr_regname(d), vd, mask, v); - _avr_set_r(avr, d, v); - } break; - case 0xfa00: - case 0xfb00:{ // BST -- Bit Store into T from bit in Register -- 1111 101d dddd 0bbb - get_vd5_s3(opcode) - STATE("bst %s[%02x], 0x%02x\n", avr_regname(d), vd, 1 << s); - avr->sreg[S_T] = (vd >> s) & 1; - SREG(); - } break; - case 0xfc00: - case 0xfe00: { // SBRS/SBRC -- Skip if Bit in Register is Set/Clear -- 1111 11sd dddd 0bbb - get_vd5_s3_mask(opcode) - int set = (opcode & 0x0200) != 0; - int branch = ((vd & mask) && set) || (!(vd & mask) && !set); - STATE("%s %s[%02x], 0x%02x\t; Will%s branch\n", set ? "sbrs" : "sbrc", avr_regname(d), vd, mask, branch ? "":" not"); - if (branch) { - if (_avr_is_instruction_32_bits(avr, new_pc)) { - new_pc += 4; cycle += 2; - } else { - new_pc += 2; cycle++; - } - } - } break; - default: _avr_invalid_opcode(avr); - } - } break; - - default: _avr_invalid_opcode(avr); - - } - avr->cycle += cycle; - - if ((avr->state == cpu_Running) && - (avr->run_cycle_count > cycle) && - (avr->interrupt_state == 0)) - { - avr->run_cycle_count -= cycle; - avr->pc = new_pc; - goto run_one_again; - } - - return new_pc; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.h deleted file mode 100644 index 874651e..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_core.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - sim_core.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_CORE_H__ -#define __SIM_CORE_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef NO_COLOR - #define FONT_GREEN - #define FONT_RED - #define FONT_DEFAULT -#else - #define FONT_GREEN "\e[32m" - #define FONT_RED "\e[31m" - #define FONT_DEFAULT "\e[0m" -#endif - -/* - * Instruction decoder, run ONE instruction - */ -avr_flashaddr_t avr_run_one(avr_t * avr); - -/* - * These are for internal access to the stack (for interrupts) - */ -uint16_t _avr_sp_get(avr_t * avr); -void _avr_sp_set(avr_t * avr, uint16_t sp); -int _avr_push_addr(avr_t * avr, avr_flashaddr_t addr); - -#if CONFIG_SIMAVR_TRACE - -/* - * Get a "pretty" register name - */ -const char * avr_regname(unsigned int reg); - -/* - * DEBUG bits follow - * These will disappear when gdb arrives - */ -void avr_dump_state(avr_t * avr); - -#define DUMP_REG() { \ - for (int i = 0; i < 32; i++) printf("%s=%02x%c", avr_regname(i), avr->data[i],i==15?'\n':' ');\ - printf("\n");\ - uint16_t y = avr->data[R_YL] | (avr->data[R_YH]<<8);\ - for (int i = 0; i < 20; i++) printf("Y+%02d=%02x ", i, avr->data[y+i]);\ - printf("\n");\ - } - - -#if AVR_STACK_WATCH -#define DUMP_STACK() \ - for (int i = avr->trace_data->stack_frame_index; i; i--) {\ - int pci = i-1;\ - printf(FONT_RED "*** %04x: %-25s sp %04x\n" FONT_DEFAULT,\ - avr->trace_data->stack_frame[pci].pc, \ - avr->trace_data->codeline ? avr->trace_data->codeline[avr->trace_data->stack_frame[pci].pc>>1]->symbol : "unknown", \ - avr->trace_data->stack_frame[pci].sp);\ - } -#else -#define DUMP_STACK() -#endif - -#else /* CONFIG_SIMAVR_TRACE */ - -#define DUMP_STACK() -#define DUMP_REG(); - -#endif - -/** - * Reconstructs the SREG value from avr->sreg into dst. - */ -#define READ_SREG_INTO(avr, dst) { \ - dst = 0; \ - for (int i = 0; i < 8; i++) \ - if (avr->sreg[i] > 1) { \ - printf("** Invalid SREG!!\n"); \ - } else if (avr->sreg[i]) \ - dst |= (1 << i); \ - } - -static inline void avr_sreg_set(avr_t * avr, uint8_t flag, uint8_t ival) -{ - /* - * clear interrupt_state if disabling interrupts. - * set wait if enabling interrupts. - * no change if interrupt flag does not change. - */ - - if (flag == S_I) { - if (ival) { - if (!avr->sreg[S_I]) - avr->interrupt_state = -1; - } else - avr->interrupt_state = 0; - } - - avr->sreg[flag] = ival; -} - -/** - * Splits the SREG value from src into the avr->sreg array. - */ -#define SET_SREG_FROM(avr, src) { \ - for (int i = 0; i < 8; i++) \ - avr_sreg_set(avr, i, (src & (1 << i)) != 0); \ - } - -/* - * Opcode is sitting at the end of the flash to catch PC overflows. - * Apparently it's used by some code to simulate soft reset? - */ -#define AVR_OVERFLOW_OPCODE 0xf1f1 - -#ifdef __cplusplus -}; -#endif - -#endif /*__SIM_CORE_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.c deleted file mode 100644 index 93cf265..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - sim_cycle_timers.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "sim_avr.h" -#include "sim_time.h" -#include "sim_cycle_timers.h" - -#define QUEUE(__q, __e) { \ - (__e)->next = (__q); \ - (__q) = __e; \ - } -#define DETACH(__q, __l, __e) { \ - if (__l) \ - (__l)->next = (__e)->next; \ - else \ - (__q) = (__e)->next; \ - } -#define INSERT(__q, __l, __e) { \ - if (__l) { \ - (__e)->next = (__l)->next; \ - (__l)->next = (__e); \ - } else { \ - (__e)->next = (__q); \ - (__q) = (__e); \ - } \ - } - -#define DEFAULT_SLEEP_CYCLES 1000 - -void -avr_cycle_timer_reset( - struct avr_t * avr) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - memset(pool, 0, sizeof(*pool)); - // queue all slots into the free queue - for (int i = 0; i < MAX_CYCLE_TIMERS; i++) { - avr_cycle_timer_slot_p t = &pool->timer_slots[i]; - QUEUE(pool->timer_free, t); - } - avr->run_cycle_count = 1; - avr->run_cycle_limit = 1; -} - -static avr_cycle_count_t -avr_cycle_timer_return_sleep_run_cycles_limited( - avr_t *avr, - avr_cycle_count_t sleep_cycle_count) -{ - // run_cycle_count is bound to run_cycle_limit but NOT less than 1 cycle... - // this is not an error!.. unless you like deadlock. - avr_cycle_count_t run_cycle_count = ((avr->run_cycle_limit >= sleep_cycle_count) ? - sleep_cycle_count : avr->run_cycle_limit); - avr->run_cycle_count = run_cycle_count ? run_cycle_count : 1; - - // sleep cycles are returned unbounded thus preserving original behavior. - return(sleep_cycle_count); -} - -static void -avr_cycle_timer_reset_sleep_run_cycles_limited( - avr_t *avr) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - avr_cycle_count_t sleep_cycle_count = DEFAULT_SLEEP_CYCLES; - - if(pool->timer) { - if(pool->timer->when > avr->cycle) { - sleep_cycle_count = pool->timer->when - avr->cycle; - } else { - sleep_cycle_count = 0; - } - } - - avr_cycle_timer_return_sleep_run_cycles_limited(avr, sleep_cycle_count); -} - -// no sanity checks checking here, on purpose -static void -avr_cycle_timer_insert( - avr_t * avr, - avr_cycle_count_t when, - avr_cycle_timer_t timer, - void * param) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - - when += avr->cycle; - - avr_cycle_timer_slot_p t = pool->timer_free; - - if (!t) { - AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: ran out of timers (%d)!\n", __func__, MAX_CYCLE_TIMERS); - return; - } - // detach head - pool->timer_free = t->next; - t->next = NULL; - t->timer = timer; - t->param = param; - t->when = when; - - // find its place in the list - avr_cycle_timer_slot_p loop = pool->timer, last = NULL; - while (loop) { - if (loop->when > when) - break; - last = loop; - loop = loop->next; - } - INSERT(pool->timer, last, t); -} - -void -avr_cycle_timer_register( - avr_t * avr, - avr_cycle_count_t when, - avr_cycle_timer_t timer, - void * param) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - - // remove it if it was already scheduled - avr_cycle_timer_cancel(avr, timer, param); - - if (!pool->timer_free) { - AVR_LOG(avr, LOG_ERROR, "CYCLE: %s: pool is full (%d)!\n", __func__, MAX_CYCLE_TIMERS); - return; - } - avr_cycle_timer_insert(avr, when, timer, param); - avr_cycle_timer_reset_sleep_run_cycles_limited(avr); -} - -void -avr_cycle_timer_register_usec( - avr_t * avr, - uint32_t when, - avr_cycle_timer_t timer, - void * param) -{ - avr_cycle_timer_register(avr, avr_usec_to_cycles(avr, when), timer, param); -} - -void -avr_cycle_timer_cancel( - avr_t * avr, - avr_cycle_timer_t timer, - void * param) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - - // find its place in the list - avr_cycle_timer_slot_p t = pool->timer, last = NULL; - while (t) { - if (t->timer == timer && t->param == param) { - DETACH(pool->timer, last, t); - QUEUE(pool->timer_free, t); - break; - } - last = t; - t = t->next; - } - avr_cycle_timer_reset_sleep_run_cycles_limited(avr); -} - -/* - * Check to see if a timer is present, if so, return the number (+1) of - * cycles left for it to fire, and if not present, return zero - */ -avr_cycle_count_t -avr_cycle_timer_status( - avr_t * avr, - avr_cycle_timer_t timer, - void * param) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - - // find its place in the list - avr_cycle_timer_slot_p t = pool->timer; - while (t) { - if (t->timer == timer && t->param == param) { - return 1 + (t->when - avr->cycle); - } - t = t->next; - } - return 0; -} - -/* - * run through all the timers, call the ones that needs it, - * clear the ones that wants it, and calculate the next - * potential cycle we could sleep for... - */ -avr_cycle_count_t -avr_cycle_timer_process( - avr_t * avr) -{ - avr_cycle_timer_pool_t * pool = &avr->cycle_timers; - - if (pool->timer) do { - avr_cycle_timer_slot_p t = pool->timer; - avr_cycle_count_t when = t->when; - - if (when > avr->cycle) - return avr_cycle_timer_return_sleep_run_cycles_limited(avr, when - avr->cycle); - - // detach from active timers - pool->timer = t->next; - t->next = NULL; - do { - avr_cycle_count_t w = t->timer(avr, when, t->param); - // make sure the return value is either zero, or greater - // than the last one to prevent infinite loop here - when = w > when ? w : 0; - } while (when && when <= avr->cycle); - - if (when) // reschedule then - avr_cycle_timer_insert(avr, when - avr->cycle, t->timer, t->param); - - // requeue this one into the free ones - QUEUE(pool->timer_free, t); - } while (pool->timer); - - // original behavior was to return 1000 cycles when no timers were present... - // run_cycles are bound to at least one cycle but no more than requested limit... - // value passed here is returned unbounded, thus preserving original behavior. - return avr_cycle_timer_return_sleep_run_cycles_limited(avr, DEFAULT_SLEEP_CYCLES); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.h deleted file mode 100644 index a4dfdf7..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_cycle_timers.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - sim_cycle_timers.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -/* - * cycle timers are callbacks that will be called when "when" cycle is reached - * these timers are one shots, then get cleared if the timer function returns zero, - * they get reset if the callback function returns a new cycle number - * - * the implementation maintains a list of 'pending' timers, sorted by when they - * should run, it allows very quick comparison with the next timer to run, and - * quick removal of then from the pile once dispatched. - */ -#ifndef __SIM_CYCLE_TIMERS_H___ -#define __SIM_CYCLE_TIMERS_H___ - -#include "sim_avr_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_CYCLE_TIMERS 64 - -typedef avr_cycle_count_t (*avr_cycle_timer_t)( - struct avr_t * avr, - avr_cycle_count_t when, - void * param); - -/* - * Each timer instance contains the absolute cycle number they - * are hoping to run at, a function pointer to call and a parameter - * - * it will NEVER be the exact cycle specified, as each instruction is - * not divisible and might take 2 or more cycles anyway. - * - * However if there was a LOT of cycle lag, the timer migth be called - * repeteadly until it 'caches up'. - */ -typedef struct avr_cycle_timer_slot_t { - struct avr_cycle_timer_slot_t *next; - avr_cycle_count_t when; - avr_cycle_timer_t timer; - void * param; -} avr_cycle_timer_slot_t, *avr_cycle_timer_slot_p; - -/* - * Timer pool contains a pool of timer slots available, they all - * start queued into the 'free' qeueue, are migrated to the - * 'active' queue when needed and are re-queued to the free one - * when done - */ -typedef struct avr_cycle_timer_pool_t { - avr_cycle_timer_slot_t timer_slots[MAX_CYCLE_TIMERS]; - avr_cycle_timer_slot_p timer_free; - avr_cycle_timer_slot_p timer; -} avr_cycle_timer_pool_t, *avr_cycle_timer_pool_p; - - -// register for calling 'timer' in 'when' cycles -void -avr_cycle_timer_register( - struct avr_t * avr, - avr_cycle_count_t when, - avr_cycle_timer_t timer, - void * param); -// register a timer to call in 'when' usec -void -avr_cycle_timer_register_usec( - struct avr_t * avr, - uint32_t when, - avr_cycle_timer_t timer, - void * param); -// cancel a previously set timer -void -avr_cycle_timer_cancel( - struct avr_t * avr, - avr_cycle_timer_t timer, - void * param); -/* - * Check to see if a timer is present, if so, return the number (+1) of - * cycles left for it to fire, and if not present, return zero - */ -avr_cycle_count_t -avr_cycle_timer_status( - struct avr_t * avr, - avr_cycle_timer_t timer, - void * param); - -// -// Private, called from the core -// -avr_cycle_count_t -avr_cycle_timer_process( - struct avr_t * avr); -void -avr_cycle_timer_reset( - struct avr_t * avr); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_CYCLE_TIMERS_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.c deleted file mode 100644 index df69b81..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.c +++ /dev/null @@ -1,499 +0,0 @@ -/* - sim_elf.c - - Loads a .elf file, extract the code, the data, the eeprom and - the "mcu" specification section, also load usable code symbols - to be able to print meaningful trace information. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sim_elf.h" -#include "sim_vcd_file.h" -#include "avr_eeprom.h" -#include "avr_ioport.h" - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -void -avr_load_firmware( - avr_t * avr, - elf_firmware_t * firmware) -{ - if (firmware->frequency) - avr->frequency = firmware->frequency; - if (firmware->vcc) - avr->vcc = firmware->vcc; - if (firmware->avcc) - avr->avcc = firmware->avcc; - if (firmware->aref) - avr->aref = firmware->aref; -#if CONFIG_SIMAVR_TRACE && ELF_SYMBOLS - int scount = firmware->flashsize >> 1; - avr->trace_data->codeline = malloc(scount * sizeof(avr_symbol_t*)); - memset(avr->trace_data->codeline, 0, scount * sizeof(avr_symbol_t*)); - - for (int i = 0; i < firmware->symbolcount; i++) - if (firmware->symbol[i]->addr < firmware->flashsize) // code address - avr->trace_data->codeline[firmware->symbol[i]->addr >> 1] = - firmware->symbol[i]; - // "spread" the pointers for known symbols forward - avr_symbol_t * last = NULL; - for (int i = 0; i < scount; i++) { - if (!avr->trace_data->codeline[i]) - avr->trace_data->codeline[i] = last; - else - last = avr->trace_data->codeline[i]; - } -#endif - - avr_loadcode(avr, firmware->flash, - firmware->flashsize, firmware->flashbase); - avr->codeend = firmware->flashsize + - firmware->flashbase - firmware->datasize; - - if (firmware->eeprom && firmware->eesize) { - avr_eeprom_desc_t d = { - .ee = firmware->eeprom, - .offset = 0, - .size = firmware->eesize - }; - avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &d); - } - if (firmware->fuse) - memcpy(avr->fuse, firmware->fuse, firmware->fusesize); - if (firmware->lockbits) - avr->lockbits = firmware->lockbits[0]; - // load the default pull up/down values for ports - for (int i = 0; i < 8 && firmware->external_state[i].port; i++) { - avr_ioport_external_t e = { - .name = firmware->external_state[i].port, - .mask = firmware->external_state[i].mask, - .value = firmware->external_state[i].value, - }; - avr_ioctl(avr, AVR_IOCTL_IOPORT_SET_EXTERNAL(e.name), &e); - } - avr_set_command_register(avr, firmware->command_register_addr); - avr_set_console_register(avr, firmware->console_register_addr); - - // rest is initialization of the VCD file - if (firmware->tracecount == 0) - return; - avr->vcd = malloc(sizeof(*avr->vcd)); - memset(avr->vcd, 0, sizeof(*avr->vcd)); - avr_vcd_init(avr, - firmware->tracename[0] ? firmware->tracename: "gtkwave_trace.vcd", - avr->vcd, - firmware->traceperiod >= 1000 ? firmware->traceperiod : 1000); - - AVR_LOG(avr, LOG_TRACE, "Creating VCD trace file '%s'\n", - avr->vcd->filename); - - for (int ti = 0; ti < firmware->tracecount; ti++) { - if (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_PORTPIN) { - avr_irq_t * irq = avr_io_getirq(avr, - AVR_IOCTL_IOPORT_GETIRQ(firmware->trace[ti].mask), - firmware->trace[ti].addr); - if (irq) { - char name[16]; - sprintf(name, "%c%d", firmware->trace[ti].mask, - firmware->trace[ti].addr); - avr_vcd_add_signal(avr->vcd, irq, 1, - firmware->trace[ti].name[0] ? - firmware->trace[ti].name : name); - } - } else if (firmware->trace[ti].kind == AVR_MMCU_TAG_VCD_IRQ) { - avr_irq_t * bit = avr_get_interrupt_irq(avr, firmware->trace[ti].mask); - if (bit && firmware->trace[ti].addr < AVR_INT_IRQ_COUNT) - avr_vcd_add_signal(avr->vcd, - &bit[firmware->trace[ti].addr], - firmware->trace[ti].mask == 0xff ? 8 : 1, - firmware->trace[ti].name); - } else if (firmware->trace[ti].mask == 0xff || - firmware->trace[ti].mask == 0) { - // easy one - avr_irq_t * all = avr_iomem_getirq(avr, - firmware->trace[ti].addr, - firmware->trace[ti].name, - AVR_IOMEM_IRQ_ALL); - if (!all) { - AVR_LOG(avr, LOG_ERROR, - "ELF: %s: unable to attach trace to address %04x\n", - __FUNCTION__, firmware->trace[ti].addr); - } else { - avr_vcd_add_signal(avr->vcd, all, 8, - firmware->trace[ti].name); - } - } else { - int count = __builtin_popcount(firmware->trace[ti].mask); - // for (int bi = 0; bi < 8; bi++) - // if (firmware->trace[ti].mask & (1 << bi)) - // count++; - for (int bi = 0; bi < 8; bi++) - if (firmware->trace[ti].mask & (1 << bi)) { - avr_irq_t * bit = avr_iomem_getirq(avr, - firmware->trace[ti].addr, - firmware->trace[ti].name, - bi); - if (!bit) { - AVR_LOG(avr, LOG_ERROR, - "ELF: %s: unable to attach trace to address %04x\n", - __FUNCTION__, firmware->trace[ti].addr); - break; - } - - if (count == 1) { - avr_vcd_add_signal(avr->vcd, - bit, 1, firmware->trace[ti].name); - break; - } - char comp[128]; - sprintf(comp, "%s.%d", firmware->trace[ti].name, bi); - avr_vcd_add_signal(avr->vcd, bit, 1, comp); - } - } - } - // if the firmware has specified a command register, do NOT start the trace here - // the firmware probably knows best when to start/stop it - if (!firmware->command_register_addr) - avr_vcd_start(avr->vcd); -} - -static void -elf_parse_mmcu_section( - elf_firmware_t * firmware, - uint8_t * src, - uint32_t size) -{ -// hdump(".mmcu", src, size); - while (size) { - uint8_t tag = *src++; - uint8_t ts = *src++; - int next = size > 2 + ts ? 2 + ts : size; - // printf("elf_parse_mmcu_section %2d, size %2d / remains %3d\n", - // tag, ts, size); - switch (tag) { - case AVR_MMCU_TAG_FREQUENCY: - firmware->frequency = - src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - break; - case AVR_MMCU_TAG_NAME: - strcpy(firmware->mmcu, (char*)src); - break; - case AVR_MMCU_TAG_VCC: - firmware->vcc = - src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - break; - case AVR_MMCU_TAG_AVCC: - firmware->avcc = - src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - break; - case AVR_MMCU_TAG_AREF: - firmware->aref = - src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - break; - case AVR_MMCU_TAG_PORT_EXTERNAL_PULL: { - for (int i = 0; i < 8; i++) - if (!firmware->external_state[i].port) { - firmware->external_state[i].port = src[2]; - firmware->external_state[i].mask = src[1]; - firmware->external_state[i].value = src[0]; -#if 0 - AVR_LOG(NULL, LOG_DEBUG, - "AVR_MMCU_TAG_PORT_EXTERNAL_PULL[%d] %c:%02x:%02x\n", - i, firmware->external_state[i].port, - firmware->external_state[i].mask, - firmware->external_state[i].value); -#endif - break; - } - } break; - case AVR_MMCU_TAG_VCD_PORTPIN: - case AVR_MMCU_TAG_VCD_IRQ: - case AVR_MMCU_TAG_VCD_TRACE: { - uint8_t mask = src[0]; - uint16_t addr = src[1] | (src[2] << 8); - char * name = (char*)src + 3; - -#if 0 - AVR_LOG(NULL, LOG_DEBUG, - "VCD_TRACE %d %04x:%02x - %s\n", tag, - addr, mask, name); -#endif - firmware->trace[firmware->tracecount].kind = tag; - firmware->trace[firmware->tracecount].mask = mask; - firmware->trace[firmware->tracecount].addr = addr; - strncpy(firmware->trace[firmware->tracecount].name, name, - sizeof(firmware->trace[firmware->tracecount].name)); - firmware->tracecount++; - } break; - case AVR_MMCU_TAG_VCD_FILENAME: { - strcpy(firmware->tracename, (char*)src); - } break; - case AVR_MMCU_TAG_VCD_PERIOD: { - firmware->traceperiod = - src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - } break; - case AVR_MMCU_TAG_SIMAVR_COMMAND: { - firmware->command_register_addr = src[0] | (src[1] << 8); - } break; - case AVR_MMCU_TAG_SIMAVR_CONSOLE: { - firmware->console_register_addr = src[0] | (src[1] << 8); - } break; - } - size -= next; - src += next - 2; // already incremented - } -} - -static int -elf_copy_segment(int fd, Elf32_Phdr *php, uint8_t **dest) -{ - int rv; - - if (*dest == NULL) - *dest = malloc(php->p_filesz); - if (!*dest) - return -1; - - lseek(fd, php->p_offset, SEEK_SET); - rv = read(fd, *dest, php->p_filesz); - if (rv != php->p_filesz) { - AVR_LOG(NULL, LOG_ERROR, - "Got %d when reading %d bytes for %x at offset %d " - "from ELF file\n", - rv, php->p_filesz, php->p_vaddr, php->p_offset); - return -1; - } - AVR_LOG(NULL, LOG_DEBUG, "Loaded %d bytes at %x\n", - php->p_filesz, php->p_vaddr); - return 0; -} - -static int -elf_handle_segment(int fd, Elf32_Phdr *php, uint8_t **dest, const char *name) -{ - if (*dest) { - AVR_LOG(NULL, LOG_ERROR, - "Unexpected extra %s data: %d bytes at %x.\n", - name, php->p_filesz, php->p_vaddr); - return -1; - } else { - elf_copy_segment(fd, php, dest); - return 0; - } -} - -/* The structure *firmware must be pre-initialised to zero, then optionally - * tracing and VCD information may be added. - */ - -int -elf_read_firmware( - const char * file, - elf_firmware_t * firmware) -{ - Elf32_Ehdr elf_header; /* ELF header */ - Elf *elf = NULL; /* Our Elf pointer for libelf */ - Elf32_Phdr *php; /* Program header. */ - Elf_Scn *scn = NULL; /* Section Descriptor */ - size_t ph_count; /* Program Header entry count. */ - int fd, i; /* File Descriptor */ - - if ((fd = open(file, O_RDONLY | O_BINARY)) == -1 || - (read(fd, &elf_header, sizeof(elf_header))) < sizeof(elf_header)) { - AVR_LOG(NULL, LOG_ERROR, "could not read %s\n", file); - perror(file); - close(fd); - return -1; - } - -#if ELF_SYMBOLS - firmware->symbolcount = 0; - firmware->symbol = NULL; -#endif - - /* this is actually mandatory !! otherwise elf_begin() fails */ - if (elf_version(EV_CURRENT) == EV_NONE) { - /* library out of date - recover from error */ - return -1; - } - // Iterate through section headers again this time well stop when we find symbols - elf = elf_begin(fd, ELF_C_READ, NULL); - //printf("Loading elf %s : %p\n", file, elf); - - if (!elf) - return -1; - if (elf_kind(elf) != ELF_K_ELF) { - AVR_LOG(NULL, LOG_ERROR, "Unexpected ELF file type\n"); - return -1; - } - - /* Scan the Program Header Table. */ - - if (elf_getphdrnum(elf, &ph_count) != 0 || ph_count == 0 || - (php = elf32_getphdr(elf)) == NULL) { - AVR_LOG(NULL, LOG_ERROR, "No ELF Program Headers\n"); - return -1; - } - - for (i = 0; i < (int)ph_count; ++i, ++php) { -#if 0 - printf("Header %d type %d addr %x/%x size %d/%d flags %x\n", - i, php->p_type, php->p_vaddr, php->p_paddr, - php->p_filesz, php->p_memsz, php->p_flags); -#endif - if (php->p_type != PT_LOAD || php->p_filesz == 0) - continue; - if (php->p_vaddr < 0x800000) { - /* Explicit flash section. Load it. */ - - if (elf_handle_segment(fd, php, &firmware->flash, "Flash")) - continue; - firmware->flashsize = php->p_filesz; - firmware->flashbase = php->p_vaddr; - } else if (php->p_vaddr < 0x810000) { - /* Data space. If there are initialised variables, treat - * them as extra initialised flash. The C startup function - * understands that and will copy them to RAM. - */ - - if (firmware->flash) { - uint8_t *where; - - firmware->flash = realloc(firmware->flash, - firmware->flashsize + php->p_filesz); - if (!firmware->flash) - return -1; - where = firmware->flash + firmware->flashsize; - elf_copy_segment(fd, php, &where); - firmware->flashsize += php->p_filesz; - } else { - /* If this ever happens, add a second pass. */ - - AVR_LOG(NULL, LOG_ERROR, - "Initialialised data but no flash (%d bytes at %x)!\n", - php->p_filesz, php->p_vaddr); - return -1; - } - } else if (php->p_vaddr < 0x820000) { - /* EEPROM. */ - - if (elf_handle_segment(fd, php, &firmware->eeprom, "EEPROM")) - continue; - firmware->eesize = php->p_filesz; - } else if (php->p_vaddr < 0x830000) { - /* Fuses. */ - - if (elf_handle_segment(fd, php, &firmware->fuse, "Fuses")) - continue; - firmware->fusesize = php->p_filesz; - } else if (php->p_vaddr < 0x840000) { - /* Lock bits. */ - - elf_handle_segment(fd, php, &firmware->lockbits, "Lock bits"); - } - } - - /* Scan the section table for .mmcu magic and symbols. */ - - while ((scn = elf_nextscn(elf, scn)) != NULL) { - GElf_Shdr shdr; /* Section Header */ - gelf_getshdr(scn, &shdr); - char * name = elf_strptr(elf, elf_header.e_shstrndx, shdr.sh_name); - // printf("Walking elf section '%s'\n", name); - - if (!strcmp(name, ".mmcu")) { - Elf_Data *s = elf_getdata(scn, NULL); - - elf_parse_mmcu_section(firmware, s->d_buf, s->d_size); - if (shdr.sh_addr < 0x860000) - AVR_LOG(NULL, LOG_WARNING, - "Warning: ELF .mmcu section at %x may be loaded.\n", - shdr.sh_addr); - // printf("%s: size %ld\n", __FUNCTION__, s->d_size); - // avr->frequency = f_cpu; - } - -#if ELF_SYMBOLS - // When we find a section header marked SHT_SYMTAB stop and get symbols - if (shdr.sh_type == SHT_SYMTAB) { - // edata points to our symbol table - Elf_Data *edata = elf_getdata(scn, NULL); - - // how many symbols are there? this number comes from the size of - // the section divided by the entry size - int symbol_count = shdr.sh_size / shdr.sh_entsize; - - // loop through to grab all symbols - for (int i = 0; i < symbol_count; i++) { - GElf_Sym sym; /* Symbol */ - // libelf grabs the symbol data using gelf_getsym() - gelf_getsym(edata, i, &sym); - - // print out the value and size - if (ELF32_ST_BIND(sym.st_info) == STB_GLOBAL || - ELF32_ST_TYPE(sym.st_info) == STT_FUNC || - ELF32_ST_TYPE(sym.st_info) == STT_OBJECT) { - const char * name = elf_strptr(elf, shdr.sh_link, sym.st_name); - - // if its a bootloader, this symbol will be the entry point we need - if (!strcmp(name, "__vectors")) - firmware->flashbase = sym.st_value; - avr_symbol_t * s = malloc(sizeof(avr_symbol_t) + strlen(name) + 1); - strcpy((char*)s->symbol, name); - s->addr = sym.st_value; - s->size = sym.st_size; - if (!(firmware->symbolcount % 8)) - firmware->symbol = realloc( - firmware->symbol, - (firmware->symbolcount + 8) * sizeof(firmware->symbol[0])); - - // insert new element, keep the array sorted - int insert = -1; - for (int si = 0; si < firmware->symbolcount && insert == -1; si++) - if (firmware->symbol[si]->addr >= s->addr) - insert = si; - if (insert == -1) - insert = firmware->symbolcount; - else - memmove(firmware->symbol + insert + 1, - firmware->symbol + insert, - (firmware->symbolcount - insert) * sizeof(firmware->symbol[0])); - firmware->symbol[insert] = s; - firmware->symbolcount++; - } - } - } -#endif // ELF_SYMBOLS - } - elf_end(elf); - close(fd); - return 0; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.h deleted file mode 100644 index 37d61d7..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_elf.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - sim_elf.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_ELF_H__ -#define __SIM_ELF_H__ - -#include "avr/avr_mcu_section.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ELF_SYMBOLS -#define ELF_SYMBOLS 1 -#endif - -/* these are the addresses the gnu linker uses to - * "fake" a non-Harvard addressing space for the AVR - */ -#define AVR_SEGMENT_OFFSET_FLASH 0 -#define AVR_SEGMENT_OFFSET_EEPROM 0x00810000 - -#include "sim_avr.h" - -typedef struct elf_firmware_t { - char mmcu[64]; - uint32_t frequency; - uint32_t vcc,avcc,aref; - - char tracename[128]; // trace filename - uint32_t traceperiod; - int tracecount; - struct { - uint8_t kind; - uint8_t mask; - uint16_t addr; - char name[64]; - } trace[32]; - - struct { - char port; - uint8_t mask, value; - } external_state[8]; - - // register to listen to for commands from the firmware - uint16_t command_register_addr; - uint16_t console_register_addr; - - uint32_t flashbase; // base address - uint8_t * flash; - uint32_t flashsize; - uint32_t datasize; - uint32_t bsssize; - // read the .eeprom section of the elf, too - uint8_t * eeprom; - uint32_t eesize; - uint8_t * fuse; - uint32_t fusesize; - uint8_t * lockbits; - -#if ELF_SYMBOLS - avr_symbol_t ** symbol; - uint32_t symbolcount; -#endif -} elf_firmware_t ; - -/* The structure *firmware must be pre-initialised to zero, then optionally - * with tracing and VCD information. - */ - -int -elf_read_firmware( - const char * file, - elf_firmware_t * firmware); - -void -avr_load_firmware( - avr_t * avr, - elf_firmware_t * firmware); - -#ifdef __cplusplus -}; -#endif - -#endif /*__SIM_ELF_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.c deleted file mode 100644 index cd2196e..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* - sim_gdb.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include "sim_network.h" -#include -#include -#include -#include -#include -#include -#include -#include "sim_avr.h" -#include "sim_core.h" // for SET_SREG_FROM, READ_SREG_INTO -#include "sim_hex.h" -#include "avr_eeprom.h" -#include "sim_gdb.h" - -// For debug printfs: "#define DBG(w) w" -#define DBG(w) - -#define WATCH_LIMIT (32) - -typedef struct { - uint32_t len; /**< How many points are taken (points[0] .. points[len - 1]). */ - struct { - uint32_t addr; /**< Which address is watched. */ - uint32_t size; /**< How large is the watched segment. */ - uint32_t kind; /**< Bitmask of enum avr_gdb_watch_type values. */ - } points[WATCH_LIMIT]; -} avr_gdb_watchpoints_t; - -/* How many AVR instructions to execute before looking for gdb input. */ - -#define GDB_BURST 256 - -typedef struct avr_gdb_t { - avr_t * avr; - int burst_count; // Current instruction burst size - int listen; // listen socket - int s; // current gdb connection - - avr_gdb_watchpoints_t breakpoints; - avr_gdb_watchpoints_t watchpoints; - - // These are used by gdb's "info io_registers" command. - - uint16_t ior_base; - uint8_t ior_count, mad; -} avr_gdb_t; - - -/** - * Returns the index of the watchpoint if found, -1 otherwise. - */ -static int -gdb_watch_find( - const avr_gdb_watchpoints_t * w, - uint32_t addr ) -{ - for (int i = 0; i < w->len; i++) { - if (w->points[i].addr > addr) { - return -1; - } else if (w->points[i].addr == addr) { - return i; - } - } - return -1; -} - -/** - * Contrary to gdb_watch_find, this actually checks the address against - * a watched memory _range_. - */ -static int -gdb_watch_find_range( - const avr_gdb_watchpoints_t * w, - uint32_t addr ) -{ - for (int i = 0; i < w->len; i++) { - if (w->points[i].addr > addr) { - return -1; - } else if (w->points[i].addr <= addr && - addr < w->points[i].addr + w->points[i].size) { - return i; - } - } - return -1; -} - -/** - * Returns -1 on error, 0 otherwise. - */ -static int -gdb_watch_add_or_update( - avr_gdb_watchpoints_t * w, - enum avr_gdb_watch_type kind, - uint32_t addr, - uint32_t size ) -{ - if (kind == AVR_GDB_WATCH_ACCESS) - kind |= AVR_GDB_WATCH_WRITE | AVR_GDB_WATCH_READ; - - /* If the watchpoint exists, update it. */ - int i = gdb_watch_find(w, addr); - if (i != -1) { - w->points[i].size = size; - w->points[i].kind |= kind; - return 0; - } - - /* Otherwise add it. */ - if (w->len == WATCH_LIMIT) { - return -1; - } - - /* Find the insertion point. */ - for (i = 0; i < w->len; i++) { - if (w->points[i].addr > addr) { - break; - } - } - - w->len++; - - /* Make space for new element, moving old ones from the end. */ - for (int j = w->len; j > i; j--) { - w->points[j] = w->points[j - 1]; - } - - /* Insert it. */ - w->points[i].kind = kind; - w->points[i].addr = addr; - w->points[i].size = size; - - return 0; -} - -/** - * Returns -1 on error or if the specified point does not exist, 0 otherwise. - */ -static int -gdb_watch_rm( - avr_gdb_watchpoints_t * w, - enum avr_gdb_watch_type kind, - uint32_t addr ) -{ - int i = gdb_watch_find(w, addr); - if (i == -1) { - return -1; - } - - w->points[i].kind &= ~kind; - if (w->points[i].kind) { - return 0; - } - - for (i = i + 1; i < w->len; i++) { - w->points[i - 1] = w->points[i]; - } - - w->len--; - - return 0; -} - -static void -gdb_watch_clear( - avr_gdb_watchpoints_t * w ) -{ - w->len = 0; -} - -static void -gdb_send_reply( - avr_gdb_t * g, - char * cmd ) -{ - uint8_t reply[1024]; - uint8_t * dst = reply; - uint8_t check = 0; - *dst++ = '$'; - while (*cmd) { - check += *cmd; - *dst++ = *cmd++; - } - sprintf((char*)dst, "#%02x", check); - DBG(printf("%s '%s'\n", __FUNCTION__, reply);) - send(g->s, reply, dst - reply + 3, 0); -} - -static void -gdb_send_stop_status( - avr_gdb_t * g, - uint8_t signal, - const char * reason, - uint32_t * pp ) -{ - avr_t * avr; - uint8_t sreg; - int n; - char cmd[64]; - - avr = g->avr; - READ_SREG_INTO(avr, sreg); - - n = sprintf(cmd, "T%02x20:%02x;21:%02x%02x;22:%02x%02x%02x00;", - signal, sreg, - avr->data[R_SPL], avr->data[R_SPH], - avr->pc & 0xff, (avr->pc >> 8) & 0xff, - (avr->pc >> 16) & 0xff); - if (reason) { - if (pp) - sprintf(cmd + n, "%s:%x;", reason, *pp); - else - sprintf(cmd + n, "%s:;", reason); - } - gdb_send_reply(g, cmd); -} - -static void -gdb_send_quick_status( - avr_gdb_t * g, - uint8_t signal ) -{ - gdb_send_stop_status(g, signal, NULL, NULL); -} - -static int -gdb_change_breakpoint( - avr_gdb_watchpoints_t * w, - int set, - enum avr_gdb_watch_type kind, - uint32_t addr, - uint32_t size ) -{ - DBG(printf("%s kind %d addr %08x len %d\n", set ? "Set" : "Clear", - kind, addr, size);) - - if (set) { - return gdb_watch_add_or_update(w, kind, addr, size); - } else { - return gdb_watch_rm(w, kind, addr); - } - return -1; -} - -static int -gdb_write_register( - avr_gdb_t * g, - int regi, - uint8_t * src ) -{ - switch (regi) { - case 0 ... 31: - g->avr->data[regi] = *src; - return 1; - case 32: - g->avr->data[R_SREG] = *src; - SET_SREG_FROM(g->avr, *src); - return 1; - case 33: - g->avr->data[R_SPL] = src[0]; - g->avr->data[R_SPH] = src[1]; - return 2; - case 34: - g->avr->pc = src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); - return 4; - } - return 1; -} - -static int -gdb_read_register( - avr_gdb_t * g, - int regi, - char * rep ) -{ - switch (regi) { - case 0 ... 31: - sprintf(rep, "%02x", g->avr->data[regi]); - break; - case 32: { - uint8_t sreg; - READ_SREG_INTO(g->avr, sreg); - sprintf(rep, "%02x", sreg); - } - break; - case 33: - sprintf(rep, "%02x%02x", g->avr->data[R_SPL], g->avr->data[R_SPH]); - break; - case 34: - sprintf(rep, "%02x%02x%02x00", - g->avr->pc & 0xff, (g->avr->pc>>8)&0xff, (g->avr->pc>>16)&0xff); - break; - } - return strlen(rep); -} - -static int tohex(const char *in, char *out, unsigned int len) -{ - int n = 0; - - while (*in && n + 2 < len) - n += sprintf(out + n, "%02x", (uint8_t)*in++); - return n; -} - -/* Send a message to the user. Gdb must be expecting a reply, otherwise this - * is ignored. - */ - -static void message(avr_gdb_t * g, const char *m) -{ - char buff[256]; - - buff[0] = 'O'; - tohex(m, buff + 1, sizeof buff - 1); - gdb_send_reply(g, buff); -} - -static int -handle_monitor(avr_t * avr, avr_gdb_t * g, char * cmd) -{ - char *ip, *op; - unsigned int c1, c2; - char dehex[128]; - - if (*cmd++ != ',') - return 1; // Bad format - for (op = dehex; op < dehex + (sizeof dehex - 1); ++op) { - if (!*cmd) - break; - if (sscanf(cmd, "%1x%1x", &c1, &c2) != 2) - return 2; // Bad format - *op = (c1 << 4) + c2; - cmd += 2; - } - *op = '\0'; - if (*cmd) - return 3; // Too long - ip = dehex; - while (*ip) { - while (*ip == ' ' || *ip == '\t') - ++ip; - - if (strncmp(ip, "reset", 5) == 0) { - avr_reset(avr); - avr->state = cpu_Stopped; - ip += 5; - } else if (strncmp(ip, "halt", 4) == 0) { - avr->state = cpu_Stopped; - ip += 4; - } else if (strncmp(ip, "ior", 3) == 0) { - unsigned int base; - int n, m, count; - - // Format is "ior - // or just "ior" to reset. - - ip += 3; - m = sscanf(ip, "%x %i%n", &base, &count, &n); - if (m <= 0) { - // Reset values. - - g->ior_base = g->ior_count = 0; - n = 0; - } else if (m != 2) { - return 1; - } else { - if (count <= 0 || base + count + 32 > REG_NAME_COUNT || - base + count + 32 > avr->ioend) { - return 4; // bad value - } - g->ior_base = base; - g->ior_count = count; - } - ip += n; - DBG( - } else if (strncmp(ip, "say ", 4) == 0) { - // Put a message in the debug output. - printf("Say: %s\n", ip + 4); - ip += strlen(ip); - ) - } else { - tohex("Monitor subcommands are: ior halt reset" DBG(" say") "\n", - dehex, sizeof dehex); - gdb_send_reply(g, dehex); - return -1; - } - } - return 0; -} - -static void -handle_io_registers(avr_t * avr, avr_gdb_t * g, char * cmd) -{ - extern const char *avr_regname(unsigned int); // sim_core.c - char * params; - char * reply; - unsigned int addr, count; - char buff[1024]; - - if (g->mad) { - /* For this command, gdb employs a streaming protocol, - * with the command being repeated until the stub sends - * an empy packet as terminator. That makes no sense, - * as the requests are sized to ensure the reply will - * fit in a single packet. - */ - - reply = ""; - g->mad = 0; - } else { - params = cmd + 11; - if (sscanf(params, ":%x,%x", &addr, &count) == 2) { - int i; - - // Send names and values. - addr += 32; - if (addr + count > avr->ioend) - count = avr->ioend + 1 - addr; - reply = buff; - for (i = 0; i < count; ++i) { - const char *name; - - name = avr_regname(addr + i); - reply += sprintf(reply, "%s,%x;", - name, avr->data[addr + i]); - if (reply > buff + sizeof buff - 20) - break; - } - } else { - // Send register count. - - count = g->ior_count ? g->ior_count : - avr->ioend > REG_NAME_COUNT ? - REG_NAME_COUNT - 32 : avr->ioend - 32; - sprintf(buff, "%x", count); - } - reply = buff; - g->mad = 1; - } - gdb_send_reply(g, reply); -} - -static void -handle_v(avr_t * avr, avr_gdb_t * g, char * cmd, int length) -{ - uint32_t addr; - uint8_t *src = NULL; - int len, err = -1; - - if (strncmp(cmd, "FlashErase", 10) == 0) { - - sscanf(cmd, "%*[^:]:%x,%x", &addr, &len); - if (addr < avr->flashend) { - src = avr->flash + addr; - if (addr + len > avr->flashend) - len = avr->flashend - addr; - memset(src, 0xff, len); - DBG(printf("FlashErase: %x,%x\n", addr, len);) //Remove - } else { - err = 1; - } - } else if (strncmp(cmd, "FlashWrite", 10) == 0) { - if (sscanf(cmd, "%*[^:]:%x:%n", &addr, &len) != 1) { - err = 2; - } else { - if (len >= length) { - err = 99; - } else if (addr < avr->flashend) { - int escaped; - char *end; - uint8_t *limit; - - end = cmd + length - 1; // Ignore final '#'. - cmd += len; - src = avr->flash + addr; - limit = avr->flash + avr->flashend; - for (escaped = 0; cmd < end && src < limit; ++cmd) { - if (escaped) { - *src++ = *cmd ^ 0x20; - escaped = 0; - } else if (*cmd == '}') { - escaped = 1; - } else { - *src++ = *cmd; - } - } - DBG(printf("FlashWrite %x, %ld bytes\n", addr, - (src - avr->flash) - addr);) - addr = src - avr->flash; // Address of end. - if (addr > avr->codeend) // Checked by sim_core.c - avr->codeend = addr; - if (cmd != end) { - DBG(printf("FlashWrite %ld bytes left!\n", end - cmd)); - } - } else { - err = 1; - } - } - } else if (strncmp(cmd, "FlashDone", 9) == 0) { - DBG(printf("FlashDone\n");) //Remove - } else { - gdb_send_reply(g, ""); - return; - } - - if (err < 0) { - gdb_send_reply(g, "OK"); - } else { - char b[32]; - - sprintf(b, "E %.2d", err); - gdb_send_reply(g, b); - } -} - -static void -gdb_handle_command( - avr_gdb_t * g, - char * cmd, - int length) -{ - avr_t * avr = g->avr; - char rep[1024]; - uint8_t command = *cmd++; - switch (command) { - case 'q': - if (strncmp(cmd, "Supported", 9) == 0) { - /* If GDB asked what features we support, report back - * the features we support, which is just memory layout - * information and stop reasons for now. - */ - gdb_send_reply(g, "qXfer:memory-map:read+;swbreak+;hwbreak+"); - break; - } else if (strncmp(cmd, "Attached", 8) == 0) { - /* Respond that we are attached to an existing process.. - * ourselves! - */ - gdb_send_reply(g, "1"); - break; - // Rmoving the following 3 lines fixes #150 issue: - // } else if (strncmp(cmd, "Offsets", 7) == 0) { - // gdb_send_reply(g, "Text=0;Data=800000;Bss=800000"); - // break; - } else if (strncmp(cmd, "Xfer:memory-map:read", 20) == 0) { - snprintf(rep, sizeof(rep), - "l\n" - " \n" - " \n" - " 0x80\n" - " \n" - "", - g->avr->ramend + 1, g->avr->flashend + 1); - - gdb_send_reply(g, rep); - break; - } else if (strncmp(cmd, "RegisterInfo", 12) == 0) { - // Send back the information we have on this register (if any). - long n = strtol(cmd + 12, NULL, 16); - if (n < 32) { - // General purpose (8-bit) registers. - snprintf(rep, sizeof(rep), "name:r%ld;bitsize:8;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:%ld;dwarf:%ld;", n, n, n); - gdb_send_reply(g, rep); - break; - } else if (n == 32) { - // SREG (flags) register. - snprintf(rep, sizeof(rep), "name:sreg;bitsize:8;offset:0;encoding:uint;format:binary;set:General Purpose Registers;gcc:32;dwarf:32;"); - gdb_send_reply(g, rep); - break; - } else if (n == 33) { - // SP register (SPH and SPL combined). - snprintf(rep, sizeof(rep), "name:sp;bitsize:16;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:33;dwarf:33;generic:sp;"); - gdb_send_reply(g, rep); - break; - } else if (n == 34) { - // PC register - snprintf(rep, sizeof(rep), "name:pc;bitsize:32;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:34;dwarf:34;generic:pc;"); - gdb_send_reply(g, rep); - break; - } else { - // Register not available. - // By sending back nothing, the debugger knows it has read - // all available registers. - } - } else if (strncmp(cmd, "Rcmd", 4) == 0) { // monitor command - int err = handle_monitor(avr, g, cmd + 4); - if (err > 0) { - snprintf(rep, sizeof rep, - "E%02x", err); - gdb_send_reply(g, rep); - } else if (err == 0) { - gdb_send_reply(g, "OK"); - } - break; - } else if (strncmp(cmd, "Ravr.io_reg", 11) == 0) { - handle_io_registers(avr, g, cmd); - break; - } - gdb_send_reply(g, ""); - break; - case '?': - gdb_send_quick_status(g, 0); - break; - case 'G': { // set all general purpose registers - // get their binary form - read_hex_string(cmd, (uint8_t*)rep, strlen(cmd)); - uint8_t *src = (uint8_t*)rep; - for (int i = 0; i < 35; i++) - src += gdb_write_register(g, i, src); - gdb_send_reply(g, "OK"); - } break; - case 'g': { // read all general purpose registers - char * dst = rep; - for (int i = 0; i < 35; i++) - dst += gdb_read_register(g, i, dst); - gdb_send_reply(g, rep); - } break; - case 'p': { // read register - unsigned int regi = 0; - sscanf(cmd, "%x", ®i); - gdb_read_register(g, regi, rep); - gdb_send_reply(g, rep); - } break; - case 'P': { // write register - unsigned int regi = 0; - char * val = strchr(cmd, '='); - if (!val) - break; - *val++ = 0; - sscanf(cmd, "%x", ®i); - read_hex_string(val, (uint8_t*)rep, strlen(val)); - gdb_write_register(g, regi, (uint8_t*)rep); - gdb_send_reply(g, "OK"); - } break; - case 'm': { // read memory - avr_flashaddr_t addr; - uint32_t len; - sscanf(cmd, "%x,%x", &addr, &len); - uint8_t * src = NULL; - /* GDB seems to also use 0x1800000 for sram ?!?! */ - addr &= 0xffffff; - if (addr < avr->flashend) { - src = avr->flash + addr; - } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) { - src = avr->data + addr - 0x800000; - } else if (addr == (0x800000 + avr->ramend + 1) && len == 2) { - // Allow GDB to read a value just after end of stack. - // This is necessary to make instruction stepping work when stack is empty - AVR_LOG(avr, LOG_TRACE, - "GDB: read just past end of stack %08x, %08x; returning zero\n", addr, len); - gdb_send_reply(g, "0000"); - break; - } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) { - avr_eeprom_desc_t ee = {.offset = (addr - 0x810000)}; - avr_ioctl(avr, AVR_IOCTL_EEPROM_GET, &ee); - if (ee.ee) - src = ee.ee; - else { - gdb_send_reply(g, "E01"); - break; - } - } else { - AVR_LOG(avr, LOG_ERROR, - "GDB: read memory error %08x, %08x (ramend %04x)\n", - addr, len, avr->ramend+1); - gdb_send_reply(g, "E01"); - break; - } - char * dst = rep; - while (len--) { - sprintf(dst, "%02x", *src++); - dst += 2; - } - *dst = 0; - gdb_send_reply(g, rep); - } break; - case 'M': { // write memory - uint32_t addr, len; - sscanf(cmd, "%x,%x", &addr, &len); - char * start = strchr(cmd, ':'); - if (!start) { - gdb_send_reply(g, "E01"); - break; - } - if (addr < 0xffff) { - read_hex_string(start + 1, avr->flash + addr, strlen(start+1)); - gdb_send_reply(g, "OK"); - } else if (addr >= 0x800000 && (addr - 0x800000) <= avr->ramend) { - read_hex_string(start + 1, avr->data + addr - 0x800000, strlen(start+1)); - gdb_send_reply(g, "OK"); - } else if (addr >= 0x810000 && (addr - 0x810000) <= avr->e2end) { - read_hex_string(start + 1, (uint8_t*)rep, strlen(start+1)); - avr_eeprom_desc_t ee = {.offset = (addr - 0x810000), .size = len, .ee = (uint8_t*)rep }; - avr_ioctl(avr, AVR_IOCTL_EEPROM_SET, &ee); - gdb_send_reply(g, "OK"); - } else { - AVR_LOG(avr, LOG_ERROR, "GDB: write memory error %08x, %08x\n", addr, len); - gdb_send_reply(g, "E01"); - } - } break; - case 'c': { // continue - avr->state = cpu_Running; - } break; - case 's': { // step - avr->state = cpu_Step; - } break; - case 'r': { // deprecated, suggested for AVRStudio compatibility - avr_reset(avr); - avr->state = cpu_Stopped; - } break; - case 'Z': // set clear break/watchpoint - case 'z': { - uint32_t kind, addr, len; - int set = (command == 'Z'); - sscanf(cmd, "%d,%x,%x", &kind, &addr, &len); -// printf("breakpoint %d, %08x, %08x\n", kind, addr, len); - switch (kind) { - case 0: // software breakpoint - case 1: // hardware breakpoint - if (addr > avr->flashend || - gdb_change_breakpoint(&g->breakpoints, set, 1 << kind, addr, len) == -1) { - gdb_send_reply(g, "E01"); - break; - } - - gdb_send_reply(g, "OK"); - break; - case 2: // write watchpoint - case 3: // read watchpoint - case 4: // access watchpoint - /* Mask out the offset applied to SRAM addresses. */ - addr &= ~0x800000; - if (addr > avr->ramend || - gdb_change_breakpoint(&g->watchpoints, set, 1 << kind, addr, len) == -1) { - gdb_send_reply(g, "E01"); - break; - } - - gdb_send_reply(g, "OK"); - break; - default: - gdb_send_reply(g, ""); - break; - } - } break; - case 'D': // detach -#ifdef DETACHABLE - if (avr->state = cpu_Stopped) - avr->state = cpu_Running; - gdb_send_reply(g, "OK"); - close(g->s); - g->s = -1; - break; -#endif - case 'k': // kill - avr->state = cpu_Done; - gdb_send_reply(g, "OK"); - break; - case 'v': - handle_v(avr, g, cmd, length); - break; - default: - gdb_send_reply(g, ""); - break; - } -} - -static int -gdb_network_handler( - avr_gdb_t * g, - uint32_t dosleep ) -{ - fd_set read_set; - int max; - FD_ZERO(&read_set); - - g->burst_count = 0; // Reset burst count - if (g->s != -1) { - FD_SET(g->s, &read_set); - max = g->s + 1; - } else { - FD_SET(g->listen, &read_set); - max = g->listen + 1; - } - struct timeval timo = { dosleep / 1000000, dosleep % 1000000 }; - int ret = select(max, &read_set, NULL, NULL, &timo); - - if (ret == 0) - return 0; - - if (FD_ISSET(g->listen, &read_set)) { - g->s = accept(g->listen, NULL, NULL); - - if (g->s == -1) { - perror("gdb_network_handler accept"); - sleep(5); - return 1; - } - int i = 1; - setsockopt (g->s, IPPROTO_TCP, TCP_NODELAY, &i, sizeof (i)); - g->avr->state = cpu_Stopped; - DBG(printf("%s connection opened\n", __FUNCTION__);) - } - - if (g->s != -1 && FD_ISSET(g->s, &read_set)) { - uint8_t buffer[1024]; - - ssize_t r = recv(g->s, buffer, sizeof(buffer)-1, 0); - - if (r == 0) { - DBG(printf("%s connection closed\n", __FUNCTION__);) - close(g->s); - gdb_watch_clear(&g->breakpoints); - gdb_watch_clear(&g->watchpoints); - g->avr->state = cpu_Running; // resume - g->s = -1; - return 1; - } - if (r == -1) { - perror("gdb_network_handler recv"); - sleep(1); - return 1; - } - buffer[r] = 0; - - uint8_t * src = buffer; - while (*src == '+' || *src == '-') - src++; - DBG( - if (!strncmp("$vFlashWrite", (char *)src, 12)) { - printf("%s: received Flashwrite command %ld bytes\n", - __FUNCTION__, r); - } else { - printf("%s: received command %ld bytes\n'%s'\n", - __FUNCTION__, r, buffer); - }) - // hdump("gdb", buffer, r); - // control C -- lets send the guy a nice status packet - if (*src == 3) { - src++; - gdb_send_quick_status(g, 2); // SIGINT - g->avr->state = cpu_Stopped; - printf("GDB hit control-c\n"); - } else if (*src == '$') { - // strip checksum - uint8_t * end = buffer + r - 1; - while (end > src && *end != '#') - *end-- = 0; - *end = 0; - src++; - DBG( - if (strncmp("vFlashWrite", (char *)src, 11)) - printf("GDB command = '%s'\n", src);) - send(g->s, "+", 1, 0); - if (end > src) - gdb_handle_command(g, (char*)src, end - src); - } - } - return 1; -} - -/* Called on a hardware break instruction. */ -void avr_gdb_handle_break(avr_t *avr) -{ - avr_gdb_t *g = avr->gdb; - - message(g, "Simavr executed 'break' instruction.\n"); - //gdb_send_stop_status(g, 5, "swbreak", NULL); Correct but ignored! - gdb_send_quick_status(g, 5); -} - -/** - * If an applicable watchpoint exists for addr, stop the cpu and send a status report. - * type is one of AVR_GDB_WATCH_READ, AVR_GDB_WATCH_WRITE depending on the type of access. - */ -void -avr_gdb_handle_watchpoints( - avr_t * avr, - uint16_t addr, - enum avr_gdb_watch_type type ) -{ - avr_gdb_t *g = avr->gdb; - uint32_t false_addr; - - int i = gdb_watch_find_range(&g->watchpoints, addr); - if (i == -1) { - return; - } - - int kind = g->watchpoints.points[i].kind; - DBG(printf("Addr %04x found watchpoint %d size %d type %x wanted %x\n", - addr, i, g->watchpoints.points[i].size, kind, type);) - if (kind & type) { - /* Send gdb reply (see GDB user manual appendix E.3). */ - - const char * what; - - what = (kind & AVR_GDB_WATCH_ACCESS) ? "awatch" : - (kind & AVR_GDB_WATCH_WRITE) ? "watch" : "rwatch"; - false_addr = addr + 0x800000; - gdb_send_stop_status(g, 5, what, &false_addr); - avr->state = cpu_Stopped; - } -} - -int -avr_gdb_processor( - avr_t * avr, - int sleep ) -{ - if (!avr || !avr->gdb) - return 0; - avr_gdb_t * g = avr->gdb; - - if (avr->state == cpu_Running && - gdb_watch_find(&g->breakpoints, avr->pc) != -1) { - DBG(printf("avr_gdb_processor hit breakpoint at %08x\n", avr->pc);) - gdb_send_stop_status(g, 5, "hwbreak", NULL); - avr->state = cpu_Stopped; - } else if (avr->state == cpu_StepDone) { - gdb_send_quick_status(g, 0); - avr->state = cpu_Stopped; - } else { - /* Look for gdb input every GDB_BURST instructions. */ - - if (sleep == 0 && g->burst_count++ < GDB_BURST) - return 0; - } - return gdb_network_handler(g, sleep); -} - - -int -avr_gdb_init( - avr_t * avr ) -{ - if (avr->gdb) - return 0; // GDB server already is active - - avr_gdb_t * g = malloc(sizeof(avr_gdb_t)); - memset(g, 0, sizeof(avr_gdb_t)); - - avr->gdb = NULL; - - if ( network_init() ) { - AVR_LOG(avr, LOG_ERROR, "GDB: Can't initialize network"); - goto error; - } - - if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) { - AVR_LOG(avr, LOG_ERROR, "GDB: Can't create socket: %s", strerror(errno)); - goto error; - } - - int optval = 1; - setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - - struct sockaddr_in address = { 0 }; - address.sin_family = AF_INET; - address.sin_port = htons (avr->gdb_port); - - if (bind(g->listen, (struct sockaddr *) &address, sizeof(address))) { - AVR_LOG(avr, LOG_ERROR, "GDB: Can not bind socket: %s", strerror(errno)); - goto error; - } - if (listen(g->listen, 1)) { - perror("listen"); - goto error; - } - printf("avr_gdb_init listening on port %d\n", avr->gdb_port); - g->avr = avr; - g->s = -1; - avr->gdb = g; - // change default run behaviour to use the slightly slower versions - avr->run = avr_callback_run_gdb; - avr->sleep = avr_callback_sleep_gdb; - - return 0; - -error: - if (g->listen >= 0) - close(g->listen); - free(g); - - return -1; -} - -void -avr_deinit_gdb( - avr_t * avr ) -{ - if (!avr->gdb) - return; - avr->run = avr_callback_run_raw; // restore normal callbacks - avr->sleep = avr_callback_sleep_raw; - if (avr->gdb->listen != -1) - close(avr->gdb->listen); - avr->gdb->listen = -1; - if (avr->gdb->s != -1) - close(avr->gdb->s); - avr->gdb->s = -1; - free(avr->gdb); - avr->gdb = NULL; - - network_release(); -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.h deleted file mode 100644 index 2936df7..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_gdb.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - sim_gdb.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_GDB_H__ -#define __SIM_GDB_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* Watchpoint types. - See GDB User Manual, Appendix E.2 */ -enum avr_gdb_watch_type { - AVR_GDB_BREAK_SOFT = 1 << 0, - AVR_GDB_BREAK_HARD = 1 << 1, - - AVR_GDB_WATCH_WRITE = 1 << 2, - AVR_GDB_WATCH_READ = 1 << 3, - AVR_GDB_WATCH_ACCESS = 1 << 4 -}; - -int avr_gdb_init(avr_t * avr); - -void avr_deinit_gdb(avr_t * avr); - -// call from the main AVR decoder thread -int avr_gdb_processor(avr_t * avr, int sleep); - -// Called from sim_core.c -void avr_gdb_handle_watchpoints(avr_t * g, uint16_t addr, enum avr_gdb_watch_type type); -void avr_gdb_handle_break(avr_t *); - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.c deleted file mode 100644 index fea67c4..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - sim_hex.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "sim_hex.h" -#include "sim_elf.h" - -// friendly hex dump -void hdump(const char *w, uint8_t *b, size_t l) -{ - uint32_t i; - if (l < 16) { - printf("%s: ",w); - for (i = 0; i < l; i++) printf("%02x",b[i]); - } else { - printf("%s:\n",w); - for (i = 0; i < l; i++) { - if (!(i & 0x1f)) printf(" "); - printf("%02x",b[i]); - if ((i & 0x1f) == 0x1f) { - printf(" "); - printf("\n"); - } - } - } - printf("\n"); -} - - // decode line text hex to binary -int read_hex_string(const char * src, uint8_t * buffer, int maxlen) -{ - uint8_t * dst = buffer; - int ls = 0; - uint8_t b = 0; - while (*src && maxlen) { - char c = *src++; - switch (c) { - case 'a' ... 'f': b = (b << 4) | (c - 'a' + 0xa); break; - case 'A' ... 'F': b = (b << 4) | (c - 'A' + 0xa); break; - case '0' ... '9': b = (b << 4) | (c - '0'); break; - default: - if (c > ' ') { - fprintf(stderr, "%s: huh '%c' (%s)\n", __FUNCTION__, c, src); - return -1; - } - continue; - } - if (ls & 1) { - *dst++ = b; b = 0; - maxlen--; - } - ls++; - } - - return dst - buffer; -} - -void -free_ihex_chunks( - ihex_chunk_p chunks) -{ - if (!chunks) - return; - for (int i = 0; chunks[i].size; i++) - if (chunks[i].data) - free(chunks[i].data); -} - -int -read_ihex_chunks( - const char * fname, - ihex_chunk_p * chunks ) -{ - if (!fname || !chunks) - return -1; - FILE * f = fopen(fname, "r"); - if (!f) { - perror(fname); - return -1; - } - uint32_t segment = 0; // segment address - int chunk = 0, max_chunks = 0; - *chunks = NULL; - - while (!feof(f)) { - char line[128]; - if (!fgets(line, sizeof(line)-1, f)) - continue; - if (line[0] != ':') { - fprintf(stderr, "AVR: '%s' invalid ihex format (%.4s)\n", fname, line); - break; - } - uint8_t bline[64]; - - int len = read_hex_string(line + 1, bline, sizeof(bline)); - if (len <= 0) - continue; - - uint8_t chk = 0; - { // calculate checksum - uint8_t * src = bline; - int tlen = len-1; - while (tlen--) - chk += *src++; - chk = 0x100 - chk; - } - if (chk != bline[len-1]) { - fprintf(stderr, "%s: %s, invalid checksum %02x/%02x\n", __FUNCTION__, fname, chk, bline[len-1]); - break; - } - uint32_t addr = 0; - switch (bline[3]) { - case 0: // normal data - addr = segment | (bline[1] << 8) | bline[2]; - break; - case 1: // end of file - reset segment - segment = 0; - continue; - case 2: // extended address 2 bytes - segment = ((bline[4] << 8) | bline[5]) << 4; - continue; - case 4: - segment = ((bline[4] << 8) | bline[5]) << 16; - continue; - default: - fprintf(stderr, "%s: %s, unsupported check type %02x\n", __FUNCTION__, fname, bline[3]); - continue; - } - if (chunk < max_chunks && addr != ((*chunks)[chunk].baseaddr + (*chunks)[chunk].size)) { - if ((*chunks)[chunk].size) - chunk++; - } - if (chunk >= max_chunks) { - max_chunks++; - /* Here we allocate and zero an extra chunk, to act as terminator */ - *chunks = realloc(*chunks, (1 + max_chunks) * sizeof(ihex_chunk_t)); - memset(*chunks + chunk, 0, - (1 + (max_chunks - chunk)) * sizeof(ihex_chunk_t)); - (*chunks)[chunk].baseaddr = addr; - } - (*chunks)[chunk].data = realloc((*chunks)[chunk].data, - (*chunks)[chunk].size + bline[0]); - memcpy((*chunks)[chunk].data + (*chunks)[chunk].size, - bline + 4, bline[0]); - (*chunks)[chunk].size += bline[0]; - } - fclose(f); - return max_chunks; -} - - -uint8_t * -read_ihex_file( - const char * fname, uint32_t * dsize, uint32_t * start) -{ - ihex_chunk_p chunks = NULL; - int count = read_ihex_chunks(fname, &chunks); - uint8_t * res = NULL; - - if (count > 0) { - *dsize = chunks[0].size; - *start = chunks[0].baseaddr; - res = chunks[0].data; - chunks[0].data = NULL; - } - if (count > 1) { - fprintf(stderr, "AVR: '%s' ihex contains more chunks than loaded (%d)\n", - fname, count); - } - free_ihex_chunks(chunks); - return res; -} - -/* Load a firmware file, ELF or HEX format, from filename, based at - * loadBase, returning the data in *fp ready for loading into - * the simulated MCU. Progname is the current program name for error messages. - * - * Included here as it mostly specific to HEX files. - */ - -void -sim_setup_firmware(const char * filename, uint32_t loadBase, - elf_firmware_t * fp, const char * progname) -{ - char * suffix = strrchr(filename, '.'); - - if (suffix && !strcasecmp(suffix, ".hex")) { - if (!(fp->mmcu[0] && fp->frequency > 0)) { - printf("MCU type and frequency are not set " - "when loading .hex file\n"); - } - ihex_chunk_p chunk = NULL; - int cnt = read_ihex_chunks(filename, &chunk); - if (cnt <= 0) { - fprintf(stderr, - "%s: Unable to load IHEX file %s\n", progname, filename); - exit(1); - } - printf("Loaded %d section(s) of ihex\n", cnt); - - for (int ci = 0; ci < cnt; ci++) { - if (chunk[ci].baseaddr < (1*1024*1024)) { - if (fp->flash) { - printf("Ignoring chunk %d, " - "possible flash redefinition %08x, %d\n", - ci, chunk[ci].baseaddr, chunk[ci].size); - free(chunk[ci].data); - chunk[ci].data = NULL; - continue; - } - fp->flash = chunk[ci].data; - fp->flashsize = chunk[ci].size; - fp->flashbase = chunk[ci].baseaddr; - printf("Load HEX flash %08x, %d at %08x\n", - fp->flashbase, fp->flashsize, fp->flashbase); - } else if (chunk[ci].baseaddr >= AVR_SEGMENT_OFFSET_EEPROM || - (chunk[ci].baseaddr + loadBase) >= - AVR_SEGMENT_OFFSET_EEPROM) { - // eeprom! - - if (fp->eeprom) { - - // Converting ELF with .mmcu section will do this. - - printf("Ignoring chunk %d, " - "possible eeprom redefinition %08x, %d\n", - ci, chunk[ci].baseaddr, chunk[ci].size); - free(chunk[ci].data); - chunk[ci].data = NULL; - continue; - } - fp->eeprom = chunk[ci].data; - fp->eesize = chunk[ci].size; - printf("Load HEX eeprom %08x, %d\n", - chunk[ci].baseaddr, fp->eesize); - } - } - free(chunk); - } else { - if (elf_read_firmware(filename, fp) == -1) { - fprintf(stderr, "%s: Unable to load firmware from file %s\n", - progname, filename); - exit(1); - } - } -} - -#ifdef IHEX_TEST -// gcc -std=gnu99 -Isimavr/sim simavr/sim/sim_hex.c -o sim_hex -DIHEX_TEST -Dtest_main=main -int test_main(int argc, char * argv[]) -{ - struct ihex_chunk_t chunk[4]; - - for (int fi = 1; fi < argc; fi++) { - int c = read_ihex_chunks(argv[fi], chunk, 4); - if (c == -1) { - perror(argv[fi]); - continue; - } - for (int ci = 0; ci < c; ci++) { - char n[96]; - sprintf(n, "%s[%d] = %08x", argv[fi], ci, chunk[ci].baseaddr); - hdump(n, chunk[ci].data, chunk[ci].size); - } - } -} -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.h deleted file mode 100644 index e3a1d1f..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_hex.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - sim_hex.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __SIM_HEX_H___ -#define __SIM_HEX_H___ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -// Load a firmware file, ELF or HEX format, ready for use. - -struct elf_firmware_t; // Predeclaration ... - -void -sim_setup_firmware( - const char * filename, // Firmware file - uint32_t loadBase, // Base of load region - struct elf_firmware_t * fp, // Data returned here - const char * progname); // For error messages. - -// parses a hex text string 'src' of at max 'maxlen' characters, decodes it into 'buffer' -int -read_hex_string( - const char * src, - uint8_t * buffer, - int maxlen); - -// a .hex file chunk (base address + size) -typedef struct ihex_chunk_t { - uint32_t baseaddr; // offset it started at in the .hex file - uint8_t * data; // read data - uint32_t size; // read data size -} ihex_chunk_t, *ihex_chunk_p; - -/* - * Read a .hex file, detects the various different chunks in it from their starting - * addresses and allocate an array of ihex_chunk_t returned in 'chunks'. - * Returns the number of chunks found, or -1 if an error occurs. - */ -int -read_ihex_chunks( - const char * fname, - ihex_chunk_p * chunks ); -/* Frees previously allocated chunks */ -void -free_ihex_chunks( - ihex_chunk_p chunks); - -// reads IHEX file 'fname', puts it's decoded size in *'dsize' and returns -// a newly allocated buffer with the binary data (or NULL, if error) -uint8_t * -read_ihex_file( - const char * fname, - uint32_t * dsize, - uint32_t * start); - -// hex dump from pointer 'b' for 'l' bytes with string prefix 'w' -void -hdump( - const char *w, - uint8_t *b, size_t l); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_HEX_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.c deleted file mode 100644 index 9e3ed9c..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - sim_interrupts.c - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include -#include -#include -#include -#include "sim_interrupts.h" -#include "sim_avr.h" -#include "sim_core.h" - -DEFINE_FIFO(avr_int_vector_p, avr_int_pending); - -void -avr_interrupt_init( - avr_t * avr ) -{ - avr_int_table_p table = &avr->interrupts; - memset(table, 0, sizeof(*table)); - - static const char *names[] = { ">avr.int.pending", ">avr.int.running" }; - avr_init_irq(&avr->irq_pool, table->irq, - 0, // base number - AVR_INT_IRQ_COUNT, names); -} - -void -avr_interrupt_reset( - avr_t * avr ) -{ - avr_int_table_p table = &avr->interrupts; - - table->running_ptr = 0; - avr_int_pending_reset(&table->pending); - avr->interrupt_state = 0; - for (int i = 0; i < table->vector_count; i++) - table->vector[i]->pending = 0; -} - -void -avr_register_vector( - avr_t *avr, - avr_int_vector_t * vector) -{ - if (!vector->vector) - return; - - avr_int_table_p table = &avr->interrupts; - - char name0[48], name1[48]; - sprintf(name0, ">avr.int.%02x.pending", vector->vector); - sprintf(name1, ">avr.int.%02x.running", vector->vector); - const char *names[2] = { name0, name1 }; - avr_init_irq(&avr->irq_pool, vector->irq, - vector->vector * 256, // base number - AVR_INT_IRQ_COUNT, names); - table->vector[table->vector_count++] = vector; - if (vector->trace) - printf("IRQ%d registered (enabled %04x:%d)\n", - vector->vector, vector->enable.reg, vector->enable.bit); - - if (!vector->enable.reg) - AVR_LOG(avr, LOG_WARNING, "IRQ%d No 'enable' bit !\n", - vector->vector); -} - -int -avr_has_pending_interrupts( - avr_t * avr) -{ - avr_int_table_p table = &avr->interrupts; - return !avr_int_pending_isempty(&table->pending); -} - -int -avr_is_interrupt_pending( - avr_t * avr, - avr_int_vector_t * vector) -{ - return vector->pending; -} - -int -avr_is_interrupt_enabled( - avr_t * avr, - avr_int_vector_t * vector) -{ - return avr_regbit_get(avr, vector->enable); -} - -int -avr_raise_interrupt( - avr_t * avr, - avr_int_vector_t * vector) -{ - if (!vector || !vector->vector) - return 0; - - if (vector->trace) - printf("IRQ%d raising (enabled %d)\n", - vector->vector, avr_regbit_get(avr, vector->enable)); - - // always mark the 'raised' flag to one, even if the interrupt is disabled - // this allow "polling" for the "raised" flag, like for non-interrupt - // driven UART and so so. These flags are often "write one to clear" - if (vector->raised.reg) - avr_regbit_set(avr, vector->raised); - - if (vector->pending) { - if (vector->trace) - printf("IRQ%d:I=%d already raised (enabled %d) (cycle %lld pc 0x%x)\n", - vector->vector, !!avr->sreg[S_I], avr_regbit_get(avr, vector->enable), - (long long int)avr->cycle, avr->pc); - - return 0; - } - - avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 1); - avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING, vector->vector); - - // If the interrupt is enabled, attempt to wake the core - if (avr_regbit_get(avr, vector->enable)) { - // Mark the interrupt as pending - vector->pending = 1; - - avr_int_table_p table = &avr->interrupts; - - avr_int_pending_write(&table->pending, vector); - - if (avr->sreg[S_I] && avr->interrupt_state == 0) - avr->interrupt_state = 1; - if (avr->state == cpu_Sleeping) { - if (vector->trace) - printf("IRQ%d Waking CPU due to interrupt\n", - vector->vector); - avr->state = cpu_Running; // in case we were sleeping - } - } - // return 'raised' even if it was already pending - return 1; -} - -void -avr_clear_interrupt( - avr_t * avr, - avr_int_vector_t * vector) -{ - if (!vector) - return; - if (vector->trace) - printf("IRQ%d cleared\n", vector->vector); - vector->pending = 0; - - avr_raise_irq(vector->irq + AVR_INT_IRQ_PENDING, 0); - avr_raise_irq_float(avr->interrupts.irq + AVR_INT_IRQ_PENDING, - avr_has_pending_interrupts(avr) ? - avr_int_pending_read_at( - &avr->interrupts.pending, 0)->vector : 0, - avr_has_pending_interrupts(avr)); - - if (vector->raised.reg && !vector->raise_sticky) - avr_regbit_clear(avr, vector->raised); -} - -int -avr_clear_interrupt_if( - avr_t * avr, - avr_int_vector_t * vector, - uint8_t old) -{ - avr_raise_irq(avr->interrupts.irq + AVR_INT_IRQ_PENDING, - avr_has_pending_interrupts(avr)); - if (avr_regbit_get(avr, vector->raised)) { - avr_clear_interrupt(avr, vector); - return 1; - } - avr_regbit_setto(avr, vector->raised, old); - return 0; -} - -avr_irq_t * -avr_get_interrupt_irq( - avr_t * avr, - uint8_t v) -{ - avr_int_table_p table = &avr->interrupts; - if (v == AVR_INT_ANY) - return table->irq; - for (int i = 0; i < table->vector_count; i++) - if (table->vector[i]->vector == v) - return table->vector[i]->irq; - return NULL; -} - -/* this is called upon RETI. */ -void -avr_interrupt_reti( - struct avr_t * avr) -{ - avr_int_table_p table = &avr->interrupts; - if (table->running_ptr) { - avr_int_vector_t * vector = table->running[--table->running_ptr]; - avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 0); - } - avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, - table->running_ptr > 0 ? - table->running[table->running_ptr-1]->vector : 0); -} - -/* - * check whether interrupts are pending. If so, check if the interrupt "latency" is reached, - * and if so triggers the handlers and jump to the vector. - */ -void -avr_service_interrupts( - avr_t * avr) -{ - if (!avr->sreg[S_I] || !avr->interrupt_state) - return; - - if (avr->interrupt_state < 0) { - avr->interrupt_state++; - if (avr->interrupt_state == 0) - avr->interrupt_state = avr_has_pending_interrupts(avr); - return; - } - - avr_int_table_p table = &avr->interrupts; - - // how many are pending... - int cnt = avr_int_pending_get_read_size(&table->pending); - // locate the highest priority one - int min = 0xff; - int mini = 0; - for (int ii = 0; ii < cnt; ii++) { - avr_int_vector_t * v = avr_int_pending_read_at(&table->pending, ii); - if (v->vector < min) { - min = v->vector; - mini = ii; - } - } - avr_int_vector_t * vector = avr_int_pending_read_at(&table->pending, mini); - - // it's possible that the vector being serviced is not at the front of the fifo, because we process interrupts based - // on vector priority rather than position in the fifo. if this is the case, we need to manually swap the vector - // being serviced with the vector at the front of the fifo so that the vector at the front of the fifo can be - // serviced in a following iteration. - avr_int_vector_p fifo_front = avr_int_pending_read(&table->pending); - if (fifo_front->vector != vector->vector) { - // the read into fifo_front above has incremented pending.read, so now mini points 1 beyond the desired - // destination for the swap. - table->pending.buffer[(table->pending.read + mini - 1) % avr_int_pending_fifo_size] = fifo_front; - } - - // if that single interrupt is masked, ignore it and continue - // could also have been disabled, or cleared - if (!avr_regbit_get(avr, vector->enable) || !vector->pending) { - vector->pending = 0; - avr->interrupt_state = avr_has_pending_interrupts(avr); - } else { - if (vector->trace) - printf("IRQ%d calling\n", vector->vector); - _avr_push_addr(avr, avr->pc); - avr_sreg_set(avr, S_I, 0); - avr->pc = vector->vector * avr->vector_size; - - avr_raise_irq(vector->irq + AVR_INT_IRQ_RUNNING, 1); - avr_raise_irq(table->irq + AVR_INT_IRQ_RUNNING, vector->vector); - if (table->running_ptr == ARRAY_SIZE(table->running)) { - AVR_LOG(avr, LOG_ERROR, "%s run out of nested stack!", __func__); - } else { - table->running[table->running_ptr++] = vector; - } - avr_clear_interrupt(avr, vector); - } -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.h deleted file mode 100644 index bebf614..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_interrupts.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - sim_interrupts.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_INTERRUPTS_H__ -#define __SIM_INTERRUPTS_H__ - -#include "sim_avr_types.h" -#include "sim_irq.h" -#include "fifo_declare.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - AVR_INT_IRQ_PENDING = 0, - AVR_INT_IRQ_RUNNING, - AVR_INT_IRQ_COUNT, - AVR_INT_ANY = 0xff, // for avr_get_interrupt_irq() -}; -// interrupt vector for the IO modules -typedef struct avr_int_vector_t { - uint8_t vector; // vector number, zero (reset) is reserved - avr_regbit_t enable; // IO register index for the "interrupt enable" flag for this vector - avr_regbit_t raised; // IO register index for the register where the "raised" flag is (optional) - - uint8_t mask; // Mask for PCINTs. this is needed for chips like the 2560 where PCINT do not align with IRQs - int8_t shift; // PCINT8 = E0, PCINT9-15 are on J0-J6. Shift shifts down (<0) or up (>0) for alignment with IRQ#. - - // 'pending' IRQ, and 'running' status as signaled here - avr_irq_t irq[AVR_INT_IRQ_COUNT]; - uint8_t pending : 1, // 1 while scheduled in the fifo - trace : 1, // only for debug of a vector - raise_sticky : 1; // 1 if the interrupt flag (= the raised regbit) is not cleared - // by the hardware when executing the interrupt routine (see TWINT) -} avr_int_vector_t, *avr_int_vector_p; - -// Size needs to be >= max number of vectors, and a power of two -DECLARE_FIFO(avr_int_vector_p, avr_int_pending, 64); - -// interrupt vectors, and their enable/clear registers -typedef struct avr_int_table_t { - avr_int_vector_t * vector[64]; - uint8_t vector_count; - avr_int_pending_t pending; - uint8_t running_ptr; - avr_int_vector_t *running[64]; // stack of nested interrupts - // global status for pending + running in interrupt context - avr_irq_t irq[AVR_INT_IRQ_COUNT]; -} avr_int_table_t, *avr_int_table_p; - -/* - * Interrupt Helper Functions - */ -// register an interrupt vector. It's only needed if you want to use the "r_raised" flags -void -avr_register_vector( - struct avr_t *avr, - avr_int_vector_t * vector); -// raise an interrupt (if enabled). The interrupt is latched and will be called later -// return non-zero if the interrupt was raised and is now pending -int -avr_raise_interrupt( - struct avr_t * avr, - avr_int_vector_t * vector); -// return non-zero if the AVR core has any pending interrupts -int -avr_has_pending_interrupts( - struct avr_t * avr); -// return nonzero if a specific interrupt vector is pending -int -avr_is_interrupt_pending( - struct avr_t * avr, - avr_int_vector_t * vector); -// clear the "pending" status of an interrupt -void -avr_clear_interrupt( - struct avr_t * avr, - avr_int_vector_t * vector); -// called by the core at each cycle to check whether an interrupt is pending -void -avr_service_interrupts( - struct avr_t * avr); -// called by the core when RETI opcode is ran -void -avr_interrupt_reti( - struct avr_t * avr); -// clear the interrupt (inc pending) if "raised" flag is 1 -int -avr_clear_interrupt_if( - struct avr_t * avr, - avr_int_vector_t * vector, - uint8_t old); - -// return the IRQ that is raised when the vector is enabled and called/cleared -// this allows tracing of pending interrupts -avr_irq_t * -avr_get_interrupt_irq( - struct avr_t * avr, - uint8_t v); - -// Initializes the interrupt table -void -avr_interrupt_init( - struct avr_t * avr ); - -// reset the interrupt table and the fifo -void -avr_interrupt_reset( - struct avr_t * avr ); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_INTERRUPTS_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.c deleted file mode 100644 index 548f030..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.c +++ /dev/null @@ -1,298 +0,0 @@ -/* - sim_io.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#include -#include -#include -#include -#include -#include "sim_io.h" - -int -avr_ioctl( - avr_t *avr, - uint32_t ctl, - void * io_param) -{ - avr_io_t * port = avr->io_port; - int res = -1; - while (port && res == -1) { - if (port->ioctl) - res = port->ioctl(port, ctl, io_param); - port = port->next; - } - return res; -} - -void -avr_register_io( - avr_t *avr, - avr_io_t * io) -{ - io->next = avr->io_port; - io->avr = avr; - avr->io_port = io; -} - -void -avr_register_io_read( - avr_t *avr, - avr_io_addr_t addr, - avr_io_read_t readp, - void * param) -{ - avr_io_addr_t a = AVR_DATA_TO_IO(addr); - if (avr->io[a].r.param || avr->io[a].r.c) { - if (avr->io[a].r.param != param || avr->io[a].r.c != readp) { - AVR_LOG(avr, LOG_ERROR, - "IO: %s(): Already registered, refusing to override.\n", - __func__); - AVR_LOG(avr, LOG_ERROR, - "IO: %s(%04x : %p/%p): %p/%p\n", - __func__, a, - avr->io[a].r.c, avr->io[a].r.param, readp, param); - abort(); - } - } - avr->io[a].r.param = param; - avr->io[a].r.c = readp; -} - -static void -_avr_io_mux_write( - avr_t * avr, - avr_io_addr_t addr, - uint8_t v, - void * param) -{ - int io = (intptr_t)param; - for (int i = 0; i < avr->io_shared_io[io].used; i++) { - avr_io_write_t c = avr->io_shared_io[io].io[i].c; - if (c) - c(avr, addr, v, avr->io_shared_io[io].io[i].param); - } -} - -void -avr_register_io_write( - avr_t *avr, - avr_io_addr_t addr, - avr_io_write_t writep, - void * param) -{ - avr_io_addr_t a = AVR_DATA_TO_IO(addr); - - if (a >= MAX_IOs) { - AVR_LOG(avr, LOG_ERROR, - "IO: %s(): IO address 0x%04x out of range (max 0x%04x).\n", - __func__, a, MAX_IOs); - abort(); - } - /* - * Verifying that some other piece of code is not installed to watch write - * on this address. If there is, this code installs a "dispatcher" callback - * instead to handle multiple clients, otherwise, it continues as usual - */ - if (avr->io[a].w.param || avr->io[a].w.c) { - if (avr->io[a].w.param != param || avr->io[a].w.c != writep) { - // if the muxer not already installed, allocate a new slot - if (avr->io[a].w.c != _avr_io_mux_write) { - int no = avr->io_shared_io_count++; - if (avr->io_shared_io_count > ARRAY_SIZE(avr->io_shared_io)) { - AVR_LOG(avr, LOG_ERROR, - "IO: %s(): Too many shared IO registers.\n", __func__); - abort(); - } - AVR_LOG(avr, LOG_TRACE, - "IO: %s(%04x): Installing muxer on register.\n", - __func__, addr); - avr->io_shared_io[no].used = 1; - avr->io_shared_io[no].io[0].param = avr->io[a].w.param; - avr->io_shared_io[no].io[0].c = avr->io[a].w.c; - avr->io[a].w.param = (void*)(intptr_t)no; - avr->io[a].w.c = _avr_io_mux_write; - } - int no = (intptr_t)avr->io[a].w.param; - int d = avr->io_shared_io[no].used++; - if (avr->io_shared_io[no].used > ARRAY_SIZE(avr->io_shared_io[0].io)) { - AVR_LOG(avr, LOG_ERROR, - "IO: %s(): Too many callbacks on %04x.\n", - __func__, addr); - abort(); - } - avr->io_shared_io[no].io[d].param = param; - avr->io_shared_io[no].io[d].c = writep; - return; - } - } - - avr->io[a].w.param = param; - avr->io[a].w.c = writep; -} - -avr_irq_t * -avr_io_getirq( - avr_t * avr, - uint32_t ctl, - int index) -{ - avr_io_t * port = avr->io_port; - while (port) { - if (port->irq && port->irq_ioctl_get == ctl && port->irq_count > index) - return port->irq + index; - port = port->next; - } - return NULL; -} - -avr_irq_t * -avr_iomem_getirq( - avr_t * avr, - avr_io_addr_t addr, - const char * name, - int index) -{ - if (index > 8) - return NULL; - avr_io_addr_t a = AVR_DATA_TO_IO(addr); - if (avr->io[a].irq == NULL) { - /* - * Prepare an array of names for the io IRQs. Ideally we'd love to have - * a proper name for these, but it's not possible at this time. - */ - char names[9 * 20]; - char * d = names; - const char * namep[9]; - for (int ni = 0; ni < 9; ni++) { - if (ni < 8) - sprintf(d, "=avr.io.%04x.%d", addr, ni); - else - sprintf(d, "8=avr.io.%04x.all", addr); - namep[ni] = d; - d += strlen(d) + 1; - } - avr->io[a].irq = avr_alloc_irq(&avr->irq_pool, 0, 9, namep); - // mark the pin ones as filtered, so they only are raised when changing - for (int i = 0; i < 8; i++) - avr->io[a].irq[i].flags |= IRQ_FLAG_FILTERED; - } - // if given a name, replace the default one... - if (name) { - int l = strlen(name); - char n[l + 10]; - sprintf(n, "avr.io.%s", name); - free((void*)avr->io[a].irq[index].name); - avr->io[a].irq[index].name = strdup(n); - } - return avr->io[a].irq + index; -} - -avr_irq_t * -avr_io_setirqs( - avr_io_t * io, - uint32_t ctl, - int count, - avr_irq_t * irqs ) -{ - // allocate this module's IRQ - io->irq_count = count; - - if (!irqs) { - const char ** irq_names = NULL; - - if (io->irq_names) { - irq_names = malloc(count * sizeof(char*)); - memset(irq_names, 0, count * sizeof(char*)); - char buf[64]; - for (int i = 0; i < count; i++) { - /* - * this bit takes the io module 'kind' ("port") - * the IRQ name ("=0") and the last character of the ioctl ('p','o','r','A') - * to create a full name "=porta.0" - */ - char * dst = buf; - // copy the 'flags' of the name out - const char * kind = io->irq_names[i]; - while (isdigit(*kind)) - *dst++ = *kind++; - while (!isalpha(*kind)) - *dst++ = *kind++; - // add avr name -// strcpy(dst, io->avr->mmcu); - strcpy(dst, "avr"); - dst += strlen(dst); - *dst ++ = '.'; - // add module 'kind' - strcpy(dst, io->kind); - dst += strlen(dst); - // add port name, if any - if ((ctl & 0xff) > ' ') - *dst ++ = tolower(ctl & 0xff); - *dst ++ = '.'; - // add the rest of the irq name - strcpy(dst, kind); - dst += strlen(dst); - *dst = 0; - -// printf("%s\n", buf); - irq_names[i] = strdup(buf); - } - } - irqs = avr_alloc_irq(&io->avr->irq_pool, 0, - count, irq_names); - if (irq_names) { - for (int i = 0; i < count; i++) - free((char*)irq_names[i]); - free((char*)irq_names); - } - } - - io->irq = irqs; - io->irq_ioctl_get = ctl; - return io->irq; -} - -static void -avr_deallocate_io( - avr_io_t * io) -{ - if (io->dealloc) - io->dealloc(io); - avr_free_irq(io->irq, io->irq_count); - io->irq_count = 0; - io->irq_ioctl_get = 0; - io->avr = NULL; - io->next = NULL; -} - -void -avr_deallocate_ios( - avr_t * avr) -{ - avr_io_t * port = avr->io_port; - while (port) { - avr_io_t * next = port->next; - avr_deallocate_io(port); - port = next; - } - avr->io_port = NULL; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.h deleted file mode 100644 index cfd2fdb..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_io.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - sim_io.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_IO_H__ -#define __SIM_IO_H__ - -#include "sim_avr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * used by the ioports to implement their own features - * see avr_eeprom.* for an example, and avr_ioctl(). - */ -#define AVR_IOCTL_DEF(_a,_b,_c,_d) \ - (((_a) << 24)|((_b) << 16)|((_c) << 8)|((_d))) - -/* - * IO module base struct - * Modules uses that as their first member in their own struct - */ -typedef struct avr_io_t { - struct avr_io_t * next; - avr_t * avr; // avr we are attached to - const char * kind; // pretty name, for debug - - const char ** irq_names; // IRQ names - - uint32_t irq_ioctl_get; // used to get irqs from this module - int irq_count; // number of (optional) irqs - struct avr_irq_t * irq; // optional external IRQs - // called at reset time - void (*reset)(struct avr_io_t *io); - // called externally. allow access to io modules and so on - int (*ioctl)(struct avr_io_t *io, uint32_t ctl, void *io_param); - - // optional, a function to free up allocated system resources - void (*dealloc)(struct avr_io_t *io); -} avr_io_t; - -/* - * IO modules helper functions - */ - -// registers an IO module, so it's run(), reset() etc are called -// this is called by the AVR core init functions, you /could/ register an external -// one after instantiation, for whatever purpose... -void -avr_register_io( - avr_t *avr, - avr_io_t * io); -// Sets an IO module "official" IRQs and the ioctl used to get to them. if 'irqs' is NULL, -// 'count' will be allocated -avr_irq_t * -avr_io_setirqs( - avr_io_t * io, - uint32_t ctl, - int count, - avr_irq_t * irqs ); - -// register a callback for when IO register "addr" is read -void -avr_register_io_read( - avr_t *avr, - avr_io_addr_t addr, - avr_io_read_t read, - void * param); -// register a callback for when the IO register is written. callback has to set the memory itself -void -avr_register_io_write( - avr_t *avr, - avr_io_addr_t addr, - avr_io_write_t write, - void * param); -// call every IO modules until one responds to this -int -avr_ioctl( - avr_t *avr, - uint32_t ctl, - void * io_param); -// get the specific irq for a module, check AVR_IOCTL_IOPORT_GETIRQ for example -struct avr_irq_t * -avr_io_getirq( - avr_t * avr, - uint32_t ctl, - int index); - -// get the IRQ for an absolute IO address -// this allows any code to hook an IRQ in any io address, for example -// tracing changes of values into a register -// Note that the values do not "magically" change, they change only -// when the AVR code attempt to read and write at that address -// -// the "index" is a bit number, or ALL bits if index == 8 -#define AVR_IOMEM_IRQ_ALL 8 -avr_irq_t * -avr_iomem_getirq( - avr_t * avr, - avr_io_addr_t addr, - const char * name /* Optional, if NULL, "ioXXXX" will be used */ , - int index); - -// Terminates all IOs and remove from them from the io chain -void -avr_deallocate_ios( - avr_t *avr); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_IO_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.c deleted file mode 100644 index 6d175cf..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - sim_irq.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include "sim_irq.h" - -// internal structure for a hook, never seen by the notify procs -typedef struct avr_irq_hook_t { - struct avr_irq_hook_t * next; - int busy; // prevent reentrance of callbacks - - struct avr_irq_t * chain; // raise the IRQ on this too - optional if "notify" is on - avr_irq_notify_t notify; // called when IRQ is raised - optional if "chain" is on - void * param; // "notify" parameter -} avr_irq_hook_t; - -static void -_avr_irq_pool_add( - avr_irq_pool_t * pool, - avr_irq_t * irq) -{ - int insert = 0; - /* lookup a slot */ - for (; insert < pool->count && pool->irq[insert]; insert++) - ; - if (insert == pool->count) { - if ((pool->count & 0xf) == 0) { - pool->irq = (avr_irq_t**)realloc(pool->irq, - (pool->count + 16) * sizeof(avr_irq_t *)); - } - pool->count++; - } - pool->irq[insert] = irq; - irq->pool = pool; -} - -static void -_avr_irq_pool_remove( - avr_irq_pool_t * pool, - avr_irq_t * irq) -{ - for (int i = 0; i < pool->count; i++) - if (pool->irq[i] == irq) { - pool->irq[i] = 0; - return; - } -} - -void -avr_init_irq( - avr_irq_pool_t * pool, - avr_irq_t * irq, - uint32_t base, - uint32_t count, - const char ** names /* optional */) -{ - memset(irq, 0, sizeof(avr_irq_t) * count); - - for (int i = 0; i < count; i++) { - irq[i].irq = base + i; - irq[i].flags = IRQ_FLAG_INIT; - if (pool) - _avr_irq_pool_add(pool, &irq[i]); - if (names && names[i]) - irq[i].name = strdup(names[i]); - else { - printf("WARNING %s() with NULL name for irq %d.\n", __func__, irq[i].irq); - } - } -} - -avr_irq_t * -avr_alloc_irq( - avr_irq_pool_t * pool, - uint32_t base, - uint32_t count, - const char ** names /* optional */) -{ - avr_irq_t * irq = (avr_irq_t*)malloc(sizeof(avr_irq_t) * count); - avr_init_irq(pool, irq, base, count, names); - for (int i = 0; i < count; i++) - irq[i].flags |= IRQ_FLAG_ALLOC; - return irq; -} - -static avr_irq_hook_t * -_avr_alloc_irq_hook( - avr_irq_t * irq) -{ - avr_irq_hook_t *hook = malloc(sizeof(avr_irq_hook_t)); - memset(hook, 0, sizeof(avr_irq_hook_t)); - hook->next = irq->hook; - irq->hook = hook; - return hook; -} - -void -avr_free_irq( - avr_irq_t * irq, - uint32_t count) -{ - if (!irq || !count) - return; - for (int i = 0; i < count; i++) { - avr_irq_t * iq = irq + i; - if (iq->pool) - _avr_irq_pool_remove(iq->pool, iq); - if (iq->name) - free((char*)iq->name); - iq->name = NULL; - // purge hooks - avr_irq_hook_t *hook = iq->hook; - while (hook) { - avr_irq_hook_t * next = hook->next; - free(hook); - hook = next; - } - iq->hook = NULL; - } - // if that irq list was allocated by us, free it - if (irq->flags & IRQ_FLAG_ALLOC) - free(irq); -} - -void -avr_irq_register_notify( - avr_irq_t * irq, - avr_irq_notify_t notify, - void * param) -{ - if (!irq || !notify) - return; - - avr_irq_hook_t *hook = irq->hook; - while (hook) { - if (hook->notify == notify && hook->param == param) - return; // already there - hook = hook->next; - } - hook = _avr_alloc_irq_hook(irq); - hook->notify = notify; - hook->param = param; -} - -void -avr_irq_unregister_notify( - avr_irq_t * irq, - avr_irq_notify_t notify, - void * param) -{ - avr_irq_hook_t *hook, *prev; - if (!irq || !notify) - return; - - hook = irq->hook; - prev = NULL; - while (hook) { - if (hook->notify == notify && hook->param == param) { - if ( prev ) - prev->next = hook->next; - else - irq->hook = hook->next; - free(hook); - return; - } - prev = hook; - hook = hook->next; - } -} - -void -avr_raise_irq_float( - avr_irq_t * irq, - uint32_t value, - int floating) -{ - if (!irq) - return ; - uint32_t output = (irq->flags & IRQ_FLAG_NOT) ? !value : value; - // if value is the same but it's the first time, raise it anyway - if (irq->value == output && - (irq->flags & IRQ_FLAG_FILTERED) && !(irq->flags & IRQ_FLAG_INIT)) - return; - irq->flags &= ~(IRQ_FLAG_INIT | IRQ_FLAG_FLOATING); - if (floating) - irq->flags |= IRQ_FLAG_FLOATING; - avr_irq_hook_t *hook = irq->hook; - while (hook) { - avr_irq_hook_t * next = hook->next; - // prevents reentrance / endless calling loops - if (hook->busy == 0) { - hook->busy++; - if (hook->notify) - hook->notify(irq, output, hook->param); - if (hook->chain) - avr_raise_irq_float(hook->chain, output, floating); - hook->busy--; - } - hook = next; - } - // the value is set after the callbacks are called, so the callbacks - // can themselves compare for old/new values between their parameter - // they are passed (new value) and the previous irq->value - irq->value = output; -} - -void -avr_raise_irq( - avr_irq_t * irq, - uint32_t value) -{ - avr_raise_irq_float(irq, value, !!(irq->flags & IRQ_FLAG_FLOATING)); -} - -void -avr_connect_irq( - avr_irq_t * src, - avr_irq_t * dst) -{ - if (!src || !dst || src == dst) { - fprintf(stderr, "error: %s invalid irq %p/%p", __FUNCTION__, src, dst); - return; - } - avr_irq_hook_t *hook = src->hook; - while (hook) { - if (hook->chain == dst) - return; // already there - hook = hook->next; - } - hook = _avr_alloc_irq_hook(src); - hook->chain = dst; -} - -void -avr_unconnect_irq( - avr_irq_t * src, - avr_irq_t * dst) -{ - avr_irq_hook_t *hook, *prev; - - if (!src || !dst || src == dst) { - fprintf(stderr, "error: %s invalid irq %p/%p", __FUNCTION__, src, dst); - return; - } - hook = src->hook; - prev = NULL; - while (hook) { - if (hook->chain == dst) { - if ( prev ) - prev->next = hook->next; - else - src->hook = hook->next; - free(hook); - return; - } - prev = hook; - hook = hook->next; - } -} - -uint8_t -avr_irq_get_flags( - avr_irq_t * irq ) -{ - return irq->flags; -} - -void -avr_irq_set_flags( - avr_irq_t * irq, - uint8_t flags ) -{ - irq->flags = flags; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.h deleted file mode 100644 index b96fd47..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_irq.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - sim_irq.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_IRQ_H__ -#define __SIM_IRQ_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Internal IRQ system - * - * This subsystem allows any piece of code to "register" a hook to be called when an IRQ is - * raised. The IRQ definition is up to the module defining it, for example a IOPORT pin change - * might be an IRQ in which case any piece of code can be notified when a pin has changed state - * - * The notify hooks are chained, and duplicates are filtered out so you can't register a - * notify hook twice on one particular IRQ - * - * IRQ calling order is not defined, so don't rely on it. - * - * IRQ hook needs to be registered in reset() handlers, ie after all modules init() bits - * have been called, to prevent race condition of the initialization order. - */ -struct avr_irq_t; - -typedef void (*avr_irq_notify_t)( - struct avr_irq_t * irq, - uint32_t value, - void * param); - - -enum { - IRQ_FLAG_NOT = (1 << 0), //!< change polarity of the IRQ - IRQ_FLAG_FILTERED = (1 << 1), //!< do not "notify" if "value" is the same as previous raise - IRQ_FLAG_ALLOC = (1 << 2), //!< this irq structure was malloced via avr_alloc_irq - IRQ_FLAG_INIT = (1 << 3), //!< this irq hasn't been used yet - IRQ_FLAG_FLOATING = (1 << 4), //!< this 'pin'/signal is floating - IRQ_FLAG_USER = (1 << 5), //!< Can be used by irq users -}; - -/* - * IRQ Pool structure - */ -typedef struct avr_irq_pool_t { - int count; //!< number of irqs living in the pool - struct avr_irq_t ** irq; //!< irqs belonging in this pool -} avr_irq_pool_t; - -/*! - * Public IRQ structure - */ -typedef struct avr_irq_t { - struct avr_irq_pool_t * pool; - const char * name; - uint32_t irq; //!< any value the user needs - uint32_t value; //!< current value - uint8_t flags; //!< IRQ_* flags - struct avr_irq_hook_t * hook; //!< list of hooks to be notified -} avr_irq_t; - -//! allocates 'count' IRQs, initializes their "irq" starting from 'base' and increment -avr_irq_t * -avr_alloc_irq( - avr_irq_pool_t * pool, - uint32_t base, - uint32_t count, - const char ** names /* optional */); -void -avr_free_irq( - avr_irq_t * irq, - uint32_t count); - -//! init 'count' IRQs, initializes their "irq" starting from 'base' and increment -void -avr_init_irq( - avr_irq_pool_t * pool, - avr_irq_t * irq, - uint32_t base, - uint32_t count, - const char ** names /* optional */); -//! Returns the current IRQ flags -uint8_t -avr_irq_get_flags( - avr_irq_t * irq ); -//! Sets this irq's flags -void -avr_irq_set_flags( - avr_irq_t * irq, - uint8_t flags ); -//! 'raise' an IRQ. Ie call their 'hooks', and raise any chained IRQs, and set the new 'value' -void -avr_raise_irq( - avr_irq_t * irq, - uint32_t value); -//! Same as avr_raise_irq(), but also allow setting the float status -void -avr_raise_irq_float( - avr_irq_t * irq, - uint32_t value, - int floating); -//! this connects a "source" IRQ to a "destination" IRQ -void -avr_connect_irq( - avr_irq_t * src, - avr_irq_t * dst); -void -avr_unconnect_irq( - avr_irq_t * src, - avr_irq_t * dst); - -//! register a notification 'hook' for 'irq' -- 'param' is anything that your want passed back as argument -void -avr_irq_register_notify( - avr_irq_t * irq, - avr_irq_notify_t notify, - void * param); - -void -avr_irq_unregister_notify( - avr_irq_t * irq, - avr_irq_notify_t notify, - void * param); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_IRQ_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_network.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_network.h deleted file mode 100644 index da4600a..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_network.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - sim_network.h - - Copyright 2012 Stephan Veigl - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_NETWORK_H__ -#define __SIM_NETWORK_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __MINGW32__ - -// Windows with MinGW - -#include -#include -#include - -#define send(sockfd, buf, len, flags) \ - (ssize_t)send( (sockfd), (const char *)(buf), (len), (flags)) -#define setsockopt(sockfd, level, optname, optval, optlen) \ - setsockopt( (sockfd), (level), (optname), (void *)(optval), (optlen)) -#define recv(sockfd, buf, len, flags) \ - (ssize_t)recv( (sockfd), (char *)(buf), (len), (flags)) -#define sleep(x) Sleep((x)*1000) - -static inline int network_init(void) -{ - // Windows requires WinSock to be init before use - WSADATA wsaData; - if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) ) - return -1; - - return 0; -} - -static inline void network_release(void) -{ - // close WinSock - WSACleanup(); -} - -#else - -// native Linux - -#include -#include -#include -#include -#include -#include - -static inline int network_init(void) -{ - // nothing to do - return 0; -} - -static inline void network_release(void) -{ - // nothing to do -} - -#endif - -#ifdef __cplusplus -}; -#endif - -#endif /*__SIM_NETWORK_H__*/ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_regbit.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_regbit.h deleted file mode 100644 index 862f490..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_regbit.h +++ /dev/null @@ -1,199 +0,0 @@ -/* - sim_regbit.h - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_REGBIT_H__ -#define __SIM_REGBIT_H__ - -#include "sim_avr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ARRAY_SIZE(_aa) (sizeof(_aa) / sizeof((_aa)[0])) - - -/* - * These accessors are inlined and are used to perform the operations on - * avr_regbit_t definitions. This is the "official" way to access bits into registers - * The small footprint costs brings much better versatility for functions/bits that are - * not always defined in the same place on real AVR cores - */ -/* - * set/get/clear io register bits in one operation - */ -static inline uint8_t -avr_regbit_set( - avr_t * avr, - avr_regbit_t rb) -{ - uint16_t a = rb.reg; - uint8_t m; - - if (!a) - return 0; - m = (uint8_t)(rb.mask << rb.bit); - avr_core_watch_write(avr, a, (uint8_t)(avr->data[a] | m)); - return (uint8_t)((avr->data[a] >> rb.bit) & rb.mask); -} - -static inline uint8_t -avr_regbit_setto( - avr_t * avr, - avr_regbit_t rb, - uint8_t v) -{ - uint16_t a = rb.reg; - uint8_t m; - - if (!a) - return 0; - m = (uint8_t)(rb.mask << rb.bit); - avr_core_watch_write(avr, a, - (uint8_t)((avr->data[a] & ~(m)) | - ((v << rb.bit) & m))); - return (uint8_t)((avr->data[a] >> rb.bit) & rb.mask); -} - -/* - * Set the 'raw' bits, if 'v' is the unshifted value of the bits - */ -static inline uint8_t -avr_regbit_setto_raw( - avr_t * avr, - avr_regbit_t rb, - uint8_t v) -{ - uint16_t a = rb.reg; - uint8_t m; - - if (!a) - return 0; - m = (uint8_t)(rb.mask << rb.bit); - avr_core_watch_write(avr, a, - (uint8_t)((avr->data[a] & ~(m)) | ((v) & m))); - return (uint8_t)((avr->data[a]) & (rb.mask << rb.bit)); -} - -static inline uint8_t -avr_regbit_get( - avr_t * avr, - avr_regbit_t rb) -{ - uint16_t a = rb.reg; - if (!a) - return 0; - //uint8_t m = rb.mask << rb.bit; - return (uint8_t)((avr->data[a] >> rb.bit) & rb.mask); -} - -/* - * Using regbit from value eliminates some of the - * set to test then clear register operations. - * makes cheking register bits before setting easier. - */ -static inline uint8_t -avr_regbit_from_value( - avr_t * avr __attribute__((unused)), - avr_regbit_t rb, - uint8_t value) -{ - uint16_t a = rb.reg; - if (!a) - return 0; - return (uint8_t)((value >> rb.bit) & rb.mask); -} - -/* - * Return the bit(s) 'in position' instead of zero based - */ -static inline uint8_t -avr_regbit_get_raw( - avr_t * avr, - avr_regbit_t rb) -{ - uint16_t a = rb.reg; - if (!a) - return 0; - //uint8_t m = rb.mask << rb.bit; - return (uint8_t)((avr->data[a]) & (rb.mask << rb.bit)); -} - -static inline uint8_t -avr_regbit_clear( - avr_t * avr, - avr_regbit_t rb) -{ - uint16_t a = rb.reg; - if (!a) - return 0; - uint8_t m = (uint8_t)(rb.mask << rb.bit); - avr_core_watch_write(avr, a, (uint8_t)(avr->data[a] & ~m)); - return avr->data[a]; -} - - -/* - * This reads the bits for an array of avr_regbit_t, make up a "byte" with them. - * This allows reading bits like CS0, CS1, CS2 etc even if they are not in the same - * physical IO register. - */ -static inline uint8_t -avr_regbit_get_array( - avr_t * avr, - avr_regbit_t *rb, - int count) -{ - uint8_t res = 0; - int i; - - for (i = 0; i < count; i++, rb++) if (rb->reg) { - uint16_t a = rb->reg; - res |= (uint8_t)(((avr->data[a] >> rb->bit) & rb->mask) << i); - } - return res; -} - -/* - * Does the reverse of avr_regbit_get_array - */ -static inline void -avr_regbit_set_array_from_value( - avr_t * avr, - avr_regbit_t * rb, - uint8_t count, - uint8_t value) -{ - int i; - for (i = 0; i < count; i++, rb++) if (rb->reg) { - uint8_t rbv = (value >> (count - i)) & 1; - avr_regbit_setto(avr, *rb, rbv); - } -} - -#define AVR_IO_REGBIT(_io, _bit) { . reg = (_io), .bit = (_bit), .mask = 1 } -#define AVR_IO_REGBITS(_io, _bit, _mask) { . reg = (_io), .bit = (_bit), .mask = (_mask) } - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_REGBIT_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_time.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_time.h deleted file mode 100644 index 4b81f43..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_time.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - sim_time.h - - Copyright 2008-2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __SIM_TIME_H___ -#define __SIM_TIME_H___ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "sim_avr.h" - -// converts a number of usec to a number of machine cycles, at current speed -static inline avr_cycle_count_t -avr_usec_to_cycles(struct avr_t * avr, uint32_t usec) -{ - return avr->frequency * (avr_cycle_count_t)usec / 1000000; -} - -// converts back a number of cycles to usecs (for usleep) -static inline uint32_t -avr_cycles_to_usec(struct avr_t * avr, avr_cycle_count_t cycles) -{ - return 1000000L * cycles / avr->frequency; -} - -// converts back a number of cycles to nsecs -static inline uint64_t -avr_cycles_to_nsec(struct avr_t * avr, avr_cycle_count_t cycles) -{ - return (uint64_t)1E6 * (uint64_t)cycles / (avr->frequency/1000); -} - -// converts a number of hz (to megahertz etc) to a number of cycle -static inline avr_cycle_count_t -avr_hz_to_cycles(avr_t * avr, uint32_t hz) -{ - return avr->frequency / hz; -} - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_TIME_H___ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.c deleted file mode 100644 index eeb4986..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - sim_utils.c - - Implements a Value Change Dump file outout to generate - traces & curves and display them in gtkwave. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include - -#include "sim_utils.h" - -static argv_p -argv_realloc( - argv_p argv, - uint32_t size ) -{ - argv = realloc(argv, - sizeof(argv_t) + (size * sizeof(argv->argv[0]))); - argv->size = size; - return argv; -} - -argv_p -argv_parse( - argv_p argv, - char * line ) -{ - if (!argv) - argv = argv_realloc(argv, 8); - argv->argc = 0; - - /* strip end of lines and trailing spaces */ - char *d = line + strlen(line); - while ((d - line) > 0 && *(--d) <= ' ') - *d = 0; - /* stop spaces + tabs */ - char *s = line; - while (*s && *s <= ' ') - s++; - argv->line = s; - char * a = NULL; - do { - if (argv->argc == argv->size) - argv = argv_realloc(argv, argv->size + 8); - if ((a = strsep(&s, " \t")) != NULL) - argv->argv[argv->argc++] = a; - } while (a); - argv->argv[argv->argc] = NULL; - return argv; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.h deleted file mode 100644 index 44cb2c5..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_utils.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - sim_utils.h - - Implements a Value Change Dump file outout to generate - traces & curves and display them in gtkwave. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_UTILS_H__ -#define __SIM_UTILS_H__ - -#include - -typedef struct argv_t { - uint32_t size, argc; - char * line; - char * argv[]; -} argv_t, *argv_p; - -/* - * Allocate a argv_t structure, split 'line' into words (destructively) - * and fills up argc, and argv fields with pointers to the individual - * words. The line is stripped of any \r\n as well - * You can pass an already allocated argv_t for it to be reused (and - * grown to fit). - * - * You are still responsible, as the caller, to (free) the resulting - * pointer, and the 'line' text, if appropriate, no duplication is made - */ -argv_p -argv_parse( - argv_p argv, - char * line ); - -#endif /* __SIM_UTILS_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.c deleted file mode 100644 index 16e4d25..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.c +++ /dev/null @@ -1,630 +0,0 @@ -/* - sim_vcd_file.c - - Implements a Value Change Dump file outout to generate - traces & curves and display them in gtkwave. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include "sim_vcd_file.h" -#include "sim_avr.h" -#include "sim_time.h" -#include "sim_utils.h" -#include "sim_core_config.h" - -DEFINE_FIFO(avr_vcd_log_t, avr_vcd_fifo); - -#define strdupa(__s) strcpy(alloca(strlen(__s)+1), __s) - -static void -_avr_vcd_notify( - struct avr_irq_t * irq, - uint32_t value, - void * param); - -int -avr_vcd_init( - struct avr_t * avr, - const char * filename, - avr_vcd_t * vcd, - uint32_t period) -{ - memset(vcd, 0, sizeof(avr_vcd_t)); - vcd->avr = avr; - vcd->filename = strdup(filename); - vcd->period = avr_usec_to_cycles(vcd->avr, period); - return 0; -} - -/* - * Parse a VCD 'timing' line. The lines are assumed to be: - * #[\n][| - * b[x/z/0/1]?argc == 0) - return res; - - if (v->argv[0][0] == '#') { - res = atoll(v->argv[0] + 1) * vcd->vcd_to_ns; - vcd->start = vcd->period; - vcd->period = res; - vi++; - } - for (int i = vi; i < v->argc; i++) { - char * a = v->argv[i]; - uint32_t val = 0; - int floating = 0; - char name = 0; - int sigindex; - - if (*a == 'b' || *a == 'B') { // Binary string - a++; - while (*a) { - if (*a == 'x' || *a == 'z') { - val <<= 1; - floating |= (floating << 1) | 1; - } else if (*a == '0' || *a == '1') { - val = (val << 1) | (*a - '0'); - floating <<= 1; - } else { - name = *a; - break; - } - a++; - } - } else if (*a == '0' || *a == '1' || *a == 'x' || *a == 'z') { - if (*a == 'x' || *a == 'z') - floating = 1; - else - val = *a++ - '0'; - if (*a && *a > ' ') - name = *a; - } else if (*a == 'r' || *a == 'R') { - val = (uint32_t)strtod(++a, NULL); - } - - if (!name && (i < v->argc - 1)) { - const char *n = v->argv[i+1]; - if (strlen(n) == 1) { - // we've got a name, it was not attached - name = *n; - i++; // skip that one - } - } - sigindex = -1; - if (name) { - for (int si = 0; - si < vcd->signal_count && - sigindex == -1; si++) { - if (vcd->signal[si].alias == name) - sigindex = si; - } - } - if (sigindex == -1) { - printf("Signal name '%c' value %x not found\n", - name? name : '?', val); - continue; - } - avr_vcd_log_t e = { - .when = vcd->period, - .sigindex = sigindex, - .floating = !!floating, - .value = val, - }; - // printf("%10u %d\n", e.when, e.value); - avr_vcd_fifo_write(&vcd->log, e); - } - return res; -} - -/* - * Read some signals from the file and fill the FIFO with it, we read - * a completely arbitrary amount of stuff to fill the FIFO reasonably well - */ -static int -avr_vcd_input_read( - avr_vcd_t * vcd ) -{ - char line[1024]; - - while (fgets(line, sizeof(line), vcd->input)) { - // printf("%s", line); - if (!line[0]) // technically can't happen, but make sure next line works - continue; - vcd->input_line = argv_parse(vcd->input_line, line); - avr_vcd_input_parse_line(vcd, vcd->input_line); - /* stop once the fifo is full enough */ - if (avr_vcd_fifo_get_read_size(&vcd->log) >= 128) - break; - } - return avr_vcd_fifo_isempty(&vcd->log); -} - -/* - * This is called when we need to change the state of one or more IRQ, - * so look in the FIFO to know 'our' stamp time, read as much as we can - * that is still on that same timestamp. - * When when the FIFO content has too far in the future, re-schedule the - * timer for that time and shoot off. - * Also try to top up the FIFO with new read stuff when it's drained - */ -static avr_cycle_count_t -_avr_vcd_input_timer( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_cycle_count_t next; - avr_vcd_t * vcd = param; - -again: - // get some more if needed - if (avr_vcd_fifo_get_read_size(&vcd->log) < (vcd->signal_count * 16)) - avr_vcd_input_read(vcd); - - if (avr_vcd_fifo_isempty(&vcd->log)) { - printf("%s DONE but why are we here?\n", __func__); - return 0; - } - - avr_vcd_log_t log = avr_vcd_fifo_read_at(&vcd->log, 0); - uint64_t stamp = log.when; - while (!avr_vcd_fifo_isempty(&vcd->log)) { - log = avr_vcd_fifo_read_at(&vcd->log, 0); - if (log.when != stamp) // leave those in the FIFO - break; - // we already have it - avr_vcd_fifo_read_offset(&vcd->log, 1); - avr_vcd_signal_p signal = &vcd->signal[log.sigindex]; - avr_raise_irq_float(&signal->irq, log.value, log.floating); - } - - if (avr_vcd_fifo_isempty(&vcd->log)) { - AVR_LOG(vcd->avr, LOG_TRACE, - "%s Finished reading, ending simavr\n", - vcd->filename); - avr->state = cpu_Done; - return 0; - } - log = avr_vcd_fifo_read_at(&vcd->log, 0); - - next = (log.when * avr->frequency) / (1000*1000*1000); - if (next <= when) - goto again; - return next; -} - -int -avr_vcd_init_input( - struct avr_t * avr, - const char * filename, // filename to read - avr_vcd_t * vcd ) // vcd struct to initialize -{ - memset(vcd, 0, sizeof(avr_vcd_t)); - vcd->avr = avr; - vcd->filename = strdup(filename); - - vcd->input = fopen(vcd->filename, "r"); - if (!vcd->input) { - perror(filename); - return -1; - } - char line[1024]; - argv_p v = NULL; - - while (fgets(line, sizeof(line), vcd->input)) { - if (!line[0]) // technically can't happen, but make sure next line works - continue; - v = argv_parse(v, line); - - // we are done reading headers, got our first timestamp - if (v->line[0] == '#') { - uint64_t when; - - vcd->start = 0; - avr_vcd_input_parse_line(vcd, v); - when = (vcd->period * vcd->avr->frequency) / - (1000*1000*1000); - avr_cycle_timer_register(vcd->avr, when, - _avr_vcd_input_timer, vcd); - break; - } - // ignore multiline stuff - if (v->line[0] != '$') - continue; - - const char * end = !strcmp(v->argv[v->argc - 1], "$end") ? - v->argv[v->argc - 1] : NULL; - const char *keyword = v->argv[0]; - - if (keyword == end) - keyword = NULL; - if (!keyword) - continue; - - if (!strcmp(keyword, "$timescale")) { - // sim_vcd header allows only integer factors of ns: 1ns, 2us, 3ms, 10s, ... - uint64_t cnt = 0; - char *si = v->argv[1]; - - vcd->vcd_to_ns = 1; - while (si && *si && isdigit(*si)) - cnt = (cnt * 10) + (*si++ - '0'); - while (si && *si == ' ') - si++; - if (si && !*si) - si = v->argv[2]; - if (!strcmp(si, "ns")) { - // no calculation here - vcd->vcd_to_ns = cnt; - } else if (!strcmp(si, "us")) { - cnt*=1000; - vcd->vcd_to_ns = cnt; - } else if (!strcmp(si, "ms")) { - cnt*=1000*1000; - vcd->vcd_to_ns = cnt; - } else if (!strcmp(si, "s")) { - cnt*=1000*1000*1000; - vcd->vcd_to_ns = cnt; - } - // printf("cnt %dus; unit %s\n", (int)cnt, si); - } else if (!strcmp(keyword, "$var")) { - const char *name = v->argv[4]; - - vcd->signal[vcd->signal_count].alias = v->argv[3][0]; - vcd->signal[vcd->signal_count].size = atoi(v->argv[2]); - strncpy(vcd->signal[vcd->signal_count].name, name, - sizeof(vcd->signal[0].name)); - - vcd->signal_count++; - } - } - // reuse this one - vcd->input_line = v; - - for (int i = 0; i < vcd->signal_count; i++) { - AVR_LOG(vcd->avr, LOG_TRACE, "%s %2d '%c' %s : size %d\n", - __func__, i, - vcd->signal[i].alias, vcd->signal[i].name, - vcd->signal[i].size); - /* format is [_] */ - if (strlen(vcd->signal[i].name) >= 4) { - char *dup = strdupa(vcd->signal[i].name); - char *ioctl = strsep(&dup, "_"); - int index = 0; - if (dup) - index = atoi(dup); - if (strlen(ioctl) == 4) { - uint32_t ioc = AVR_IOCTL_DEF( - ioctl[0], ioctl[1], ioctl[2], ioctl[3]); - avr_irq_t * irq = avr_io_getirq(vcd->avr, ioc, index); - if (irq) { - vcd->signal[i].irq.flags = IRQ_FLAG_INIT; - avr_connect_irq(&vcd->signal[i].irq, irq); - } else { - AVR_LOG(vcd->avr, LOG_WARNING, - "%s IRQ was not found\n", - vcd->signal[i].name); - } - continue; - } - AVR_LOG(vcd->avr, LOG_WARNING, - "%s is an invalid IRQ format\n", - vcd->signal[i].name); - } - } - return 0; -} - -void -avr_vcd_close( - avr_vcd_t * vcd) -{ - avr_vcd_stop(vcd); - - /* dispose of any link and hooks */ - for (int i = 0; i < vcd->signal_count; i++) { - avr_vcd_signal_t * s = &vcd->signal[i]; - - avr_free_irq(&s->irq, 1); - } - - if (vcd->filename) { - free(vcd->filename); - vcd->filename = NULL; - } -} - -static char * -_avr_vcd_get_float_signal_text( - avr_vcd_signal_t * s, - char * out) -{ - char * dst = out; - - if (s->size > 1) - *dst++ = 'b'; - - for (int i = s->size; i > 0; i--) - *dst++ = 'x'; - if (s->size > 1) - *dst++ = ' '; - *dst++ = s->alias; - *dst = 0; - return out; -} - -static char * -_avr_vcd_get_signal_text( - avr_vcd_signal_t * s, - char * out, - uint32_t value) -{ - char * dst = out; - - if (s->size > 1) - *dst++ = 'b'; - - for (int i = s->size; i > 0; i--) - *dst++ = value & (1 << (i-1)) ? '1' : '0'; - if (s->size > 1) - *dst++ = ' '; - *dst++ = s->alias; - *dst = 0; - return out; -} - -/* Write queued output to the VCD file. */ - -static void -avr_vcd_flush_log( - avr_vcd_t * vcd) -{ -#if AVR_VCD_MAX_SIGNALS > 32 - uint64_t seen = 0; -#else - uint32_t seen = 0; -#endif - uint64_t oldbase = 0; // make sure it's different - char out[48]; - - if (avr_vcd_fifo_isempty(&vcd->log) || !vcd->output) - return; - - while (!avr_vcd_fifo_isempty(&vcd->log)) { - avr_vcd_log_t l = avr_vcd_fifo_read(&vcd->log); - // 10ns base -- 100MHz should be enough - uint64_t base = avr_cycles_to_nsec(vcd->avr, l.when - vcd->start) / 10; - - /* - * if that trace was seen in this nsec already, we fudge the - * base time to make sure the new value is offset by one nsec, - * to make sure we get at least a small pulse on the waveform. - * - * This is a bit of a fudge, but it is the only way to represent - * very short "pulses" that are still visible on the waveform. - */ - if (base == oldbase && - (seen & (1 << l.sigindex))) - base++; // this forces a new timestamp - - if (base > oldbase || !seen) { - seen = 0; - fprintf(vcd->output, "#%" PRIu64 "\n", base); - oldbase = base; - } - // mark this trace as seen for this timestamp - seen |= (1 << l.sigindex); - fprintf(vcd->output, "%s\n", - l.floating ? - _avr_vcd_get_float_signal_text( - &vcd->signal[l.sigindex], - out) : - _avr_vcd_get_signal_text( - &vcd->signal[l.sigindex], - out, l.value)); - } -} - -/* Cycle timer for writing queued output. */ - -static avr_cycle_count_t -_avr_vcd_timer( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - avr_vcd_t * vcd = param; - avr_vcd_flush_log(vcd); - return when + vcd->period; -} - -/* Called for an IRQ that is being recorded. */ - -static void -_avr_vcd_notify( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - avr_vcd_t * vcd = (avr_vcd_t *)param; - - if (!vcd->output) { - AVR_LOG(vcd->avr, LOG_WARNING, - "%s: no output\n", - __FUNCTION__); - return; - } - - avr_vcd_signal_t * s = (avr_vcd_signal_t*)irq; - avr_vcd_log_t l = { - .sigindex = s->irq.irq, - .when = vcd->avr->cycle, - .value = value, - .floating = !!(avr_irq_get_flags(irq) & IRQ_FLAG_FLOATING), - }; - if (avr_vcd_fifo_isfull(&vcd->log)) { - AVR_LOG(vcd->avr, LOG_WARNING, - "%s FIFO Overload, flushing!\n", - __func__); - /* Decrease period by a quarter, for next time */ - vcd->period -= vcd->period >> 2; - avr_vcd_flush_log(vcd); - } - avr_vcd_fifo_write(&vcd->log, l); -} - -/* Register an IRQ whose value is to be logged. */ - -int -avr_vcd_add_signal( - avr_vcd_t * vcd, - avr_irq_t * signal_irq, - int signal_bit_size, - const char * name ) -{ - if (vcd->signal_count == AVR_VCD_MAX_SIGNALS) { - AVR_LOG(vcd->avr, LOG_ERROR, - " %s: unable add signal '%s'\n", - __FUNCTION__, name); - return -1; - } - int index = vcd->signal_count++; - avr_vcd_signal_t * s = &vcd->signal[index]; - strncpy(s->name, name, sizeof(s->name)); - s->size = signal_bit_size; - s->alias = ' ' + vcd->signal_count ; - - /* manufacture a nice IRQ name */ - int l = strlen(name); - char iname[10 + l + 1]; - if (signal_bit_size > 1) - sprintf(iname, "%d>vcd.%s", signal_bit_size, name); - else - sprintf(iname, ">vcd.%s", name); - - const char * names[1] = { iname }; - avr_init_irq(&vcd->avr->irq_pool, &s->irq, index, 1, names); - avr_irq_register_notify(&s->irq, _avr_vcd_notify, vcd); - - avr_connect_irq(signal_irq, &s->irq); - return 0; -} - -/* Open the VCD output file and write header. Does nothing for input. */ - -int -avr_vcd_start( - avr_vcd_t * vcd) -{ - time_t now; - - vcd->start = vcd->avr->cycle; - avr_vcd_fifo_reset(&vcd->log); - - if (vcd->input) { - /* - * nothing to do here, the first cycle timer will take care - * if it. - */ - return 0; - } - if (vcd->output) - avr_vcd_stop(vcd); - vcd->output = fopen(vcd->filename, "w"); - if (vcd->output == NULL) { - perror(vcd->filename); - return -1; - } - - time(&now); - fprintf(vcd->output, "$date %s$end\n", ctime(&now)); - fprintf(vcd->output, - "$version Simavr " CONFIG_SIMAVR_VERSION " $end\n"); - fprintf(vcd->output, "$timescale 10ns $end\n"); // 10ns base, aka 100MHz - fprintf(vcd->output, "$scope module logic $end\n"); - - for (int i = 0; i < vcd->signal_count; i++) { - fprintf(vcd->output, "$var wire %d %c %s $end\n", - vcd->signal[i].size, vcd->signal[i].alias, vcd->signal[i].name); - } - - fprintf(vcd->output, "$upscope $end\n"); - fprintf(vcd->output, "$enddefinitions $end\n"); - - fprintf(vcd->output, "$dumpvars\n"); - for (int i = 0; i < vcd->signal_count; i++) { - avr_vcd_signal_t * s = &vcd->signal[i]; - char out[48]; - fprintf(vcd->output, "%s\n", - _avr_vcd_get_float_signal_text(s, out)); - } - fprintf(vcd->output, "$end\n"); - avr_cycle_timer_register(vcd->avr, vcd->period, _avr_vcd_timer, vcd); - return 0; -} - -int -avr_vcd_stop( - avr_vcd_t * vcd) -{ - avr_cycle_timer_cancel(vcd->avr, _avr_vcd_timer, vcd); - avr_cycle_timer_cancel(vcd->avr, _avr_vcd_input_timer, vcd); - - avr_vcd_flush_log(vcd); - - if (vcd->input_line) - free(vcd->input_line); - vcd->input_line = NULL; - if (vcd->input) - fclose(vcd->input); - vcd->input = NULL; - if (vcd->output) - fclose(vcd->output); - vcd->output = NULL; - return 0; -} - - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.h deleted file mode 100644 index 2dd6219..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simavr/sim/sim_vcd_file.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - sim_vcd_file.c - - Implements a Value Change Dump file outout to generate - traces & curves and display them in gtkwave. - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#ifndef __SIM_VCD_FILE_H__ -#define __SIM_VCD_FILE_H__ - -#include -#include "sim_irq.h" -#include "fifo_declare.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Value Change dump module for simavr. - * - * This structure registers IRQ change hooks to various "source" IRQs - * and dumps their values (if changed) at certain intervals into the VCD - * file. - * - * It can also do the reverse, load a VCD file generated by for example - * sigrock signal analyzer, and 'replay' digital input with the proper - * timing. - * - * TODO: Add support for 'looping' a VCD input. - */ - -#define AVR_VCD_MAX_SIGNALS 64 - -typedef struct avr_vcd_signal_t { - /* - * For VCD output this is the IRQ we receive new values from. - * For VCD input, this is the IRQ we broadcast the values to - */ - avr_irq_t irq; - char alias; // vcd one character alias - uint8_t size; // in bits - char name[32]; // full human name -} avr_vcd_signal_t, *avr_vcd_signal_p; - -typedef struct avr_vcd_log_t { - uint64_t when; // Cycles for output, - // nS for input. - uint64_t sigindex : 8, // index in signal table - floating : 1, - value : 32; -} avr_vcd_log_t, *avr_vcd_log_p; - -DECLARE_FIFO(avr_vcd_log_t, avr_vcd_fifo, 256); - -struct argv_t; - -typedef struct avr_vcd_t { - struct avr_t * avr; // AVR we are attaching timers to.. - - char * filename; // .vcd filename - /* can be input OR output, not both */ - FILE * output; - FILE * input; - struct argv_t * input_line; - - int signal_count; - avr_vcd_signal_t signal[AVR_VCD_MAX_SIGNALS]; - - uint64_t start; - uint64_t period; // for output cycles - uint64_t vcd_to_ns; // for input unit mapping - - avr_vcd_fifo_t log; -} avr_vcd_t; - -// initializes a new VCD trace file, and returns zero if all is well -int -avr_vcd_init( - struct avr_t * avr, - const char * filename, // filename to write - avr_vcd_t * vcd, // vcd struct to initialize - uint32_t period ); // file flushing period is in usec -int -avr_vcd_init_input( - struct avr_t * avr, - const char * filename, // filename to read - avr_vcd_t * vcd ); // vcd struct to initialize -void -avr_vcd_close( - avr_vcd_t * vcd ); - -// Add a trace signal to the vcd file. Must be called before avr_vcd_start() -int -avr_vcd_add_signal( - avr_vcd_t * vcd, - avr_irq_t * signal_irq, - int signal_bit_size, - const char * name ); - -// Starts recording the signal value into the file -int -avr_vcd_start( - avr_vcd_t * vcd); -// stops recording signal values into the file -int -avr_vcd_stop( - avr_vcd_t * vcd); - -#ifdef __cplusplus -}; -#endif - -#endif /* __SIM_VCD_FILE_H__ */ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/simuc b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/simuc deleted file mode 100755 index 966bd1f..0000000 Binary files a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/simuc and /dev/null differ diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/main.cpp b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/main.cpp deleted file mode 100644 index 0af4178..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/main.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include - -#include "sim/sim.h" -#include "simavr/simavr.h" - -void printHelp () { - printf("simuc V1.0.0 (%s,%s)\n", __DATE__, __TIME__); - printf("usage: simuc [options] elf-file\n\n"); - printf(" available options:\n"); - printf(" --board ... set board (arduino, sure, evws1)\n"); - printf(" --sync sync elapsed µC-time with real time\n\n"); - printf(" --mmcu ... set target device type\n"); - printf(" --frequency ... set target frequency in Hz\n"); - printf(" --pc ... set start program counter (default is 0)\n"); - printf(" --vcc ... set voltage VCC in Volt\n"); - printf(" --avcc ... set voltage AVCC in Volt\n"); - printf(" --aref ... set voltage AREF in Volt\n\n"); - printf(" example:\n"); - printf(" simuc --mmcu atmega328p --frequency 16000000 --pc 0x7000 a.out\n\n"); - printf(" simuc --board arduino a.out\n\n"); -} - -int main (int argc, char **argv) { - struct StartParameters params = { - filename: NULL, - gdbPort: -1, - frequency: -1, - mmcu: NULL, - board: BoardUnknown, - vcc: -1, - avcc: -1, - aref: -1 - }; - - if (argc <= 1) { - printHelp(); - return 1; - } - - for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - if (strcmp(argv[i], "--help") == 0) { - printHelp(); - return 0; - } else if (strcmp(argv[i], "--board") == 0 && argc >= (i + 1)) { - i++; - if (strcmp("arduino", argv[i]) == 0) { - params.board = BoardNano; - params.mmcu = "atmega328p"; - params.frequency = 16000000; - params.vcc = 5000; - params.avcc = 5000; - params.aref = 2500; - } else if (strcmp("sure", argv[i]) == 0) { - params.board = BoardSure; - params.mmcu = "atmega16"; - params.frequency = 12000000; - params.vcc = 5000; - params.avcc = 5000; - params.aref = 2500; - } else if (strcmp("evws1", argv[i]) == 0) { - params.board = BoardEWS1; - params.mmcu = "atmega324p"; - params.frequency = 20000000; - params.vcc = 5000; - params.avcc = 5000; - params.aref = 2500; - } else { - fprintf(stderr, "ERROR: invalid board %s, use --help to show usage\n\n", argv[i]); - return 1; - } - - } else if (strcmp(argv[i], "--mmcu") == 0) { - params.mmcu = argv[++i]; - } else if (strcmp(argv[i], "--port") == 0) { - sscanf(argv[++i], "%d", ¶ms.gdbPort); - } else if (strcmp(argv[i], "--frequency") == 0) { - sscanf(argv[++i], "%" PRIu64, ¶ms.frequency); - } else if (strcmp(argv[i], "--pc") == 0) { - i++; - if (argv[i][0] == '0' && argv[i][1] == 'x') { - sscanf(&argv[i][2], "%x", ¶ms.pc); - } else { - sscanf(argv[++i], "%d", ¶ms.pc); - } - } else if (strcmp(argv[i], "--vcc") == 0) { - sscanf(argv[++i], "%d", ¶ms.vcc); - } else if (strcmp(argv[i], "--avcc") == 0) { - sscanf(argv[++i], "%d", ¶ms.avcc); - } else if (strcmp(argv[i], "--aref") == 0) { - sscanf(argv[++i], "%d", ¶ms.aref); - } else { - fprintf(stderr, "ERROR: invalid option %s, use --help to show usage\n\n", argv[i]); - return 1; - } - continue; - } - params.filename = argv[i]; - break; - } - - if (params.filename == NULL) { - printf("ERROR: missing target elf file, use --help to show usage\n\n"); - return 1; - } - - init(¶ms); - if (errno == 1) { - return 1; - } - printf("init done - press key to start\n"); - getchar(); - start(); - - // int cnt = 0; - char *line = NULL; - size_t size = 0; - while (1) { - // struct SimAvrEvent ev = waitForEvent(); - // printf("%10.03lf: event %s (%d) received \r", ev.cycle / 20E6, eventText((EnumSimEvent)ev.event), ev.event); - // fflush(stdout); - // if (++cnt == 10000) { - // stop(); - // shutdown(); - // break; - // } - - if (getline(&line, &size, stdin) > 0) { - const char *commands[] = { "interrupt", "continue", "stack" }; - try { - int foundIndex = -1; - int foundCnt = 0; - size_t length = strlen(line) - 1; - if (length > 0 && size >= (length + 1)) { - line[length] = 0; - for (long unsigned int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { - const char *cmd = commands[i]; - size_t max = strlen(cmd); - bool ok = true; - for (size_t j = 0; j < length; j++) { - if (j >= max || line[j] != cmd[j]) { - ok = false; - break; - } - } - if (ok) { - foundCnt++; - foundIndex = i; - } - } - } - // printf("foundCnt=%d foundIndex=%d command=%s\n", foundCnt, foundIndex, foundIndex >= 0 ? commands[foundIndex] : ""); - if (foundCnt == 1 || length == 0) { - setCommand((EnumSimAvrCommand)(foundCnt > 0 ? foundIndex + 2 : 1), NULL); - while (1) { - struct SimAvrEvent ev = waitForEvent(); - if (ev.event == EventCommandExecuted) { - break; - } - } - - } else { - printf("invalid command, valid commands are for status and:"); - for (long unsigned int i = 0; i < sizeof(commands) / sizeof(commands[0]); i++) { - printf(" %s", commands[i]); - } - printf("\n"); - continue; - } - - } catch (std::exception& e) { - printf("ERROR\n"); - } - - } - - } - while (1) { - struct SimAvrEvent ev = waitForEvent(); - printf("event %s (%d) received\n", eventText((EnumSimEvent)ev.event), ev.event); - if (ev.event == EventShutdown) { - break; - } - } - - usleep(10000); - return 0; -} \ No newline at end of file diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.cpp b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.cpp deleted file mode 100644 index f59ddbd..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "error.h" -#include - -std::string error (const char *location, const char *format, ...) { - va_list args; - va_start (args, format); - int length = std::vsnprintf (NULL, 0, format, args); - va_end (args); - - va_start (args, format); - char* str = new char[length + 1]; // one more character for null terminator - std::vsnprintf (str, length + 1, format, args); - std::string rv = "Error at " + std::string(location) + " -> " + str; - delete[] str; - va_end (args); - - return rv; -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.h deleted file mode 100644 index 80d5682..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/error.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ERROR_H -#define ERROR_H - -#include - -#define STRINGIFY(x) #x -#define TOSTRING(x) STRINGIFY(x) -#define AT __FILE__ ":" TOSTRING(__LINE__) -std::string error (const char *location, const char *format, ...); - -#endif // ERROR_H diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.cpp b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.cpp deleted file mode 100644 index 32a23b6..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.cpp +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sim.h" -#include "error.h" - - - -// https://github.com/java-native-access/jna/blob/master/www/CallbacksAndClosures.md#callbacks-function-pointers-and-closures - - -int SIGUSR1 = 30; - -// avr_t * avr = NULL; -SimAvr simavr; -std::string lastErrorMessage; - -static int fdStdOut = -1, fdStdErr = -1; -// static fpos_t posStdOut, posStdErr; - -void switchStdOut (const char * filename) { - fflush(stdout); - // fgetpos(stdout, &posStdOut); - if (filename == NULL) { - int fd = open("/dev/null", O_WRONLY); - fdStdOut = dup2(fd, fileno(stdout)); - } else { - fdStdOut = dup(fileno(stdout)); - } -} - -void switchStdErr (const char * filename) { - fflush(stderr); - // fgetpos(stderr, &posStdErr); - if (filename == NULL) { - int fd = open("/dev/null", O_WRONLY); - fdStdErr = dup2(fd, fileno(stderr)); - } else { - fdStdErr = dup(fileno(stderr)); - } -} - -void revertStdErrOut () { - if (fdStdOut >= 0) { - fflush(stdout); - dup2(fdStdOut, fileno(stdout)); - close(fdStdOut); - fdStdOut = -1; - clearerr(stdout); - // fsetpos(stdout, &posStdOut); - } - if (fdStdErr >= 0) { - fflush(stderr); - dup2(fdStdErr, fileno(stderr)); - close(fdStdErr); - fdStdErr = -1; - clearerr(stderr); - // fsetpos(stderr, &posStdErr); - } -} - -const char * lastError () { - return lastErrorMessage.c_str(); -} - - -// static void handleWritePortB (struct avr_t * avr, __attribute__((unused)) avr_io_addr_t addr, uint8_t v, SimAvr *simavr) { -// static int value = 0; -// if (value != v) { -// value = v; -// if (simavr != NULL) { -// if ((value << PORTB0) != 0) { -// simavr->addEvent(EventLedOn); -// } else { -// simavr->addEvent(EventLedOff); -// } -// } -// } -// } - -std::vector gdbFromUartBuffer; -std::vector gdbToUartBuffer; - -__attribute__((unused)) static void fromGdbUart (uint8_t b) { - static int cnt = 0; - if (b == '$') { - cnt = 1; - } else if (cnt > 0 && b == '#') { - cnt = -1; - } else if (cnt < 0) { - cnt--; - } - gdbFromUartBuffer.push_back(b); - - if (cnt <= -3 || (cnt == 0 && b == '+')) { - printf("\n\rgdb-uart OUT -> "); - for (uint8_t c : gdbFromUartBuffer) { - putchar(c); - } - printf("\n\r"); - gdbFromUartBuffer.clear(); - } -} - -__attribute__((unused)) static void toGdbUart (uint8_t b) { - static int cnt = 0; - if (b == '$') { - cnt = 1; - } else if (cnt > 0 && b == '#') { - cnt = -1; - } else if (cnt < 0) { - cnt--; - } - gdbToUartBuffer.push_back(b); - - if (cnt <= -3 || (cnt == 0 && b == '+')) { - printf("\n\rgdb-uart IN <-- "); - for (uint8_t c : gdbToUartBuffer) { - putchar(c); - } - printf("\n\r"); - gdbToUartBuffer.clear(); - } - -} - -void init (struct StartParameters *param) { - try { - // switchStdOut(NULL); - // switchStdErr(NULL); - // std::cout.rdbuf(0); - // std::cerr.rdbuf(0); - const char *filename = param->filename != NULL - ? param->filename - // : "../gdb-stub-sm_atmega324p/sim/dist/gdb-stub-sm_atmega324p.axf"; - : "../gdb-stub-sm_atmega324p/sim/dist/gdb-stub-sm_atmega324p.axf"; - printf("firmware file \"%s\"\n", filename); - simavr.load(param); - if (strcmp(simavr.getTargetDeviceName(), "atmega324p") != 0) { - std::logic_error(error(AT, "invalid target device %s", simavr.getTargetDeviceName())); - } - - simavr.setUartDumpEnabled(false); - // simavr.registerIoWrite(PORTB, handleWritePortB); - simavr.setUartPtyEnabled(0, true); - int uartCnt = 1; - if (strcmp(simavr.getTargetDeviceName(), "atmega324p") == 0) { - simavr.setUartPtyEnabled(1, true); - simavr.setUartPtyHook(1, fromGdbUart, toGdbUart); - uartCnt = 2; - } - // printf("uart0 -> picocom --imap lfcrlf -b 115200 %s\n", simavr.getUartPtyDeviceName(0)); - // printf("uart1 -> picocom --imap lfcrlf -b 115200 %s\n", simavr.getUartPtyDeviceName(1)); - - printf("device %s\n", simavr.getTargetDeviceName()); - printf("frequency %.2lfMHz\n", simavr.getTargetFrequency() / 1E6); - - for (int i = 0; i < uartCnt; i++) { - char s[128]; - snprintf(s, 128, "/tmp/sim-megaavr-%s-uart%1d", simavr.getTargetDeviceName(), i); - FILE *f = fopen(s, "w"); - if (f == NULL) { - std::logic_error(error(AT, "cannot write file %s", s)); - } - printf("uart%1d -> picocom %s (see file %s)\n", i, simavr.getUartPtyDeviceName(i), s); - fprintf(f, "%s\n", simavr.getUartPtyDeviceName(i)); - fclose(f); - } - - } catch (std::exception& e) { - lastErrorMessage = "init() fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -void shutdown () { - try { - simavr.shutdown(); - } catch (std::exception& e) { - lastErrorMessage = "shutdown() fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -void start () { - try { - simavr.start(); - - } catch (std::exception& e) { - lastErrorMessage = "start() fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -void stop () { - try { - simavr.stop(); - - } catch (std::exception& e) { - lastErrorMessage = "stop() fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -void setCommand (EnumSimAvrCommand cmd, void *param) { - try { - simavr.setCommand(cmd, param); - - } catch (std::exception& e) { - lastErrorMessage = "setCommand(..) fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - throw e; - } - -} - -void addEvent (EnumSimEvent event) { - try { - simavr.addEvent(event); - - } catch (std::exception& e) { - lastErrorMessage = "addEvent(..) fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -void setTimeSync (bool sync) { - try { - simavr.setTimeSync(sync); - - } catch (std::exception& e) { - lastErrorMessage = "setTimeSync() fails, caused by " + std::string(e.what()); - std::cerr << lastErrorMessage << "\n"; - errno = 1; - } -} - -struct SimAvrStatus getStatus () { - return simavr.getStatus();; -} - -struct SimAvrEvent waitForEvent () { - return simavr.waitForEvent(); -} - -const char *eventText (EnumSimEvent event) { - const char *rv = simavr.eventText((EnumSimAvrEvent)event); - if (rv != NULL) { - return rv; - } else { - switch (event) { - case EventLedOff: return "LedOff"; - case EventLedOn: return "LedOn"; - default: return "?"; - } - } -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.h deleted file mode 100644 index d980f26..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/sim/sim.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef SIM_H -#define SIM_H - -#include "../simavr/simavr.h" - -// #define _AVR_IO_H_ -// #define _SFR_IO8(reg) (0x20 + reg) -// #include "iom324p.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - EventInterrupt = 1, - EventLedOff = 10, - EventLedOn = 11 -} EnumSimEvent; - - - -extern void init (struct StartParameters *param); -extern void shutdown (); -extern const char * lastError (); -extern void start (); -extern void stop (); -extern void setCommand (EnumSimAvrCommand cmd, void *param); -extern void addEvent (EnumSimEvent event); -extern void setTimeSync (bool sync); -extern struct SimAvrStatus getStatus (); -extern struct SimAvrEvent waitForEvent (); -extern const char *eventText (EnumSimEvent event); - -typedef void (*NotificationListener)(char *, int); -void callbackTrigger(const NotificationListener l); -void getDeviceRandomStatus(char *answer, int sizeOfChars); -int randNum( int min, int max); - -#ifdef __cplusplus -} -#endif - -#endif // SIM_H diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/fifo_declare.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/fifo_declare.h deleted file mode 100644 index 8a3b2fb..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/fifo_declare.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - fido_declare.h - Copyright (C) 2003-2012 Michel Pollet - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/* - * FIFO helpers, aka circular buffers - * - * these macros define accessories for FIFOs of any name, type and - * any (power of two) size - */ - -#ifndef __FIFO_DECLARE__ -#define __FIFO_DECLARE__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - doing a : - DECLARE_FIFO(uint8_t, myfifo, 128); - - will declare : - enum : myfifo_overflow_f - type : myfifo_t - functions: - // write a byte into the fifo, return 1 if there was room, 0 if there wasn't - int myfifo_write(myfifo_t *c, uint8_t b); - // reads a byte from the fifo, return 0 if empty. Use myfifo_isempty() to check beforehand - uint8_t myfifo_read(myfifo_t *c); - int myfifo_isfull(myfifo_t *c); - int myfifo_isempty(myfifo_t *c); - // returns number of items to read now - uint16_t myfifo_get_read_size(myfifo_t *c); - // read item at offset o from read cursor, no cursor advance - uint8_t myfifo_read_at(myfifo_t *c, uint16_t o); - // write b at offset o compared to current write cursor, no cursor advance - void myfifo_write_at(myfifo_t *c, uint16_t o, uint8_t b); - - In your .c you need to 'implement' the fifo: - DEFINE_FIFO(uint8_t, myfifo) - - To use the fifo, you must declare at least one : - myfifo_t fifo = FIFO_NULL; - - while (!myfifo_isfull(&fifo)) - myfifo_write(&fifo, 0xaa); - .... - while (!myfifo_isempty(&fifo)) - b = myfifo_read(&fifo); - */ - -#include - -#if __AVR__ -#define FIFO_CURSOR_TYPE uint8_t -#define FIFO_BOOL_TYPE char -#define FIFO_INLINE -#define FIFO_SYNC -#endif - -#ifndef FIFO_CURSOR_TYPE -#define FIFO_CURSOR_TYPE uint16_t -#endif -#ifndef FIFO_BOOL_TYPE -#define FIFO_BOOL_TYPE int -#endif -#ifndef FIFO_INLINE -#define FIFO_INLINE inline -#endif - -/* We should not need volatile */ -#ifndef FIFO_VOLATILE -#define FIFO_VOLATILE -#endif -#ifndef FIFO_SYNC -#define FIFO_SYNC __sync_synchronize() -#endif - -#ifndef FIFO_ZERO_INIT -#define FIFO_ZERO_INIT {0} -#endif -#define FIFO_NULL { FIFO_ZERO_INIT, 0, 0, 0 } - -/* New compilers don't like unused static functions. However, - * we do like 'static inlines' for these small accessors, - * so we mark them as 'unused'. It stops it complaining */ -#ifdef __GNUC__ -#define FIFO_DECL static __attribute__ ((unused)) -#else -#define FIFO_DECL static -#endif - -#define DECLARE_FIFO(__type, __name, __size) \ -enum { __name##_overflow_f = (1 << 0) }; \ -enum { __name##_fifo_size = (__size) }; \ -typedef struct __name##_t { \ - __type buffer[__name##_fifo_size]; \ - FIFO_VOLATILE FIFO_CURSOR_TYPE read; \ - FIFO_VOLATILE FIFO_CURSOR_TYPE write; \ - FIFO_VOLATILE uint8_t flags; \ -} __name##_t - -#define DEFINE_FIFO(__type, __name) \ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_write(__name##_t * c, __type b)\ -{\ - FIFO_CURSOR_TYPE now = c->write;\ - FIFO_CURSOR_TYPE next = (now + 1) & (__name##_fifo_size-1);\ - if (c->read != next) { \ - c->buffer[now] = b;\ - FIFO_SYNC; \ - c->write = next;\ - return 1;\ - }\ - return 0;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_isfull(__name##_t *c)\ -{\ - FIFO_CURSOR_TYPE next = (c->write + 1) & (__name##_fifo_size-1);\ - return c->read == next;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_BOOL_TYPE __name##_isempty(__name##_t * c)\ -{\ - return c->read == c->write;\ -}\ -FIFO_DECL FIFO_INLINE __type __name##_read(__name##_t * c)\ -{\ - __type res = FIFO_ZERO_INIT; \ - FIFO_CURSOR_TYPE read = c->read;\ - if (read == c->write)\ - return res;\ - res = c->buffer[read];\ - FIFO_SYNC; \ - c->read = (read + 1) & (__name##_fifo_size-1);\ - return res;\ -}\ -FIFO_DECL FIFO_INLINE FIFO_CURSOR_TYPE __name##_get_read_size(__name##_t *c)\ -{\ - return ((c->write + __name##_fifo_size) - c->read) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE FIFO_CURSOR_TYPE __name##_get_write_size(__name##_t *c)\ -{\ - return (__name##_fifo_size-1) - __name##_get_read_size(c);\ -}\ -FIFO_DECL FIFO_INLINE void __name##_read_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - FIFO_SYNC; \ - c->read = (c->read + o) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE __type __name##_read_at(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - return c->buffer[(c->read + o) & (__name##_fifo_size-1)];\ -}\ -FIFO_DECL FIFO_INLINE void __name##_write_at(__name##_t *c, FIFO_CURSOR_TYPE o, __type b)\ -{\ - c->buffer[(c->write + o) & (__name##_fifo_size-1)] = b;\ -}\ -FIFO_DECL FIFO_INLINE void __name##_write_offset(__name##_t *c, FIFO_CURSOR_TYPE o)\ -{\ - FIFO_SYNC; \ - c->write = (c->write + o) & (__name##_fifo_size-1);\ -}\ -FIFO_DECL FIFO_INLINE void __name##_reset(__name##_t *c)\ -{\ - FIFO_SYNC; \ - c->read = c->write = c->flags = 0;\ -}\ -struct __name##_t - -#ifdef __cplusplus -}; -#endif - -#endif diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.c b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.c deleted file mode 100644 index a283fef..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - uart_pty.c - - Copyright 2008, 2009 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -#elif defined (__FreeBSD__) -#include -#include -#include -#include -#else -#include -#endif - -#include "uart_pty.h" -#include -#include -#include - -DEFINE_FIFO(uint8_t,uart_pty_fifo); - -//#define TRACE(_w) _w -#ifndef TRACE -#define TRACE(_w) -#endif - -TRACE(static const char * -uart_pty_toPrintableChar( - uint32_t value) -{ - static char rv[2] = ""; - if (value >= ' ' && value <= 126) { - rv[0] = (char)value; - rv[1] = 0; - } else if (value == '\n') { - return "\\n"; - } else if (value == '\r') { - return "\\r"; - } else { - rv[0] = 0; - } - return rv; -}) - - -/* - * called when a byte is send via the uart on the AVR - */ -static void -uart_pty_in_hook( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - uart_pty_t * p = (uart_pty_t*)param; - TRACE(printf("uart_pty_in_hook %02x %s\n", value, uart_pty_toPrintableChar(value));) - if (p->port[0].crlf && value == '\n') { - uart_pty_fifo_write(&p->port[0].in, '\r'); - } - uart_pty_fifo_write(&p->pty.in, value); - if (p->port[0].hook_from_uart != NULL) { - p->port[0].hook_from_uart(value); - } else if (p->hook_from_uart != NULL) { - p->hook_from_uart(value); - } - - if (p->tap.s) { - if (p->tap.crlf && value == '\n') - uart_pty_fifo_write(&p->tap.in, '\r'); - uart_pty_fifo_write(&p->tap.in, value); - } -} - -// try to empty our fifo, the uart_pty_xoff_hook() will be called when -// other side is full -static void -uart_pty_flush_incoming( - uart_pty_t * p) -{ - while (p->xon && !uart_pty_fifo_isempty(&p->pty.out)) { - TRACE(int r = p->pty.out.read;) - uint8_t byte = uart_pty_fifo_read(&p->pty.out); - TRACE(printf("uart_pty_flush_incoming send r %03d:%02x\n", r, byte);) - avr_raise_irq(p->irq + IRQ_UART_PTY_BYTE_OUT, byte); - - if (p->tap.s) { - if (p->tap.crlf && byte == '\n') - uart_pty_fifo_write(&p->tap.in, '\r'); - uart_pty_fifo_write(&p->tap.in, byte); - } - } - if (p->tap.s) { - while (p->xon && !uart_pty_fifo_isempty(&p->tap.out)) { - uint8_t byte = uart_pty_fifo_read(&p->tap.out); - if (p->tap.crlf && byte == '\r') { - uart_pty_fifo_write(&p->tap.in, '\n'); - } - if (byte == '\n') - continue; - uart_pty_fifo_write(&p->tap.in, byte); - avr_raise_irq(p->irq + IRQ_UART_PTY_BYTE_OUT, byte); - } - } -} - -avr_cycle_count_t -uart_pty_flush_timer( - struct avr_t * avr, - avr_cycle_count_t when, - void * param) -{ - uart_pty_t * p = (uart_pty_t*)param; - - uart_pty_flush_incoming(p); - /* always return a cycle NUMBER not a cycle count */ - return p->xon ? when + avr_hz_to_cycles(p->avr, 1000) : 0; -} - -/* - * Called when the uart has room in it's input buffer. This is called repeateadly - * if necessary, while the xoff is called only when the uart fifo is FULL - */ -static void -uart_pty_xon_hook( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - uart_pty_t * p = (uart_pty_t*)param; - TRACE(if (!p->xon) printf("uart_pty_xon_hook\n");) - p->xon = 1; - - uart_pty_flush_incoming(p); - - // if the buffer is not flushed, try to do it later - if (p->xon) - avr_cycle_timer_register(p->avr, avr_hz_to_cycles(p->avr, 1000), - uart_pty_flush_timer, param); -} - -/* - * Called when the uart ran out of room in it's input buffer - */ -static void -uart_pty_xoff_hook( - struct avr_irq_t * irq, - uint32_t value, - void * param) -{ - uart_pty_t * p = (uart_pty_t*)param; - TRACE(if (p->xon) printf("uart_pty_xoff_hook\n");) - p->xon = 0; - avr_cycle_timer_cancel(p->avr, uart_pty_flush_timer, param); -} - -static void * -uart_pty_thread( - void * param) -{ - uart_pty_t * p = (uart_pty_t*)param; - - while (1) { - fd_set read_set, write_set; - int max = 0; - FD_ZERO(&read_set); - FD_ZERO(&write_set); - - for (int ti = 0; ti < 2; ti++) if (p->port[ti].s) { - // read more only if buffer was flushed - if (p->port[ti].buffer_len == p->port[ti].buffer_done) { - FD_SET(p->port[ti].s, &read_set); - max = p->port[ti].s > max ? p->port[ti].s : max; - } - if (!uart_pty_fifo_isempty(&p->port[ti].in)) { - FD_SET(p->port[ti].s, &write_set); - max = p->port[ti].s > max ? p->port[ti].s : max; - } - } - - // short, but not too short interval - struct timeval timo = { 0, 500 }; - int ret = select(max+1, &read_set, &write_set, NULL, &timo); - - if (ret < 0) - break; - - for (int ti = 0; ti < 2; ti++) if (p->port[ti].s) { - if (FD_ISSET(p->port[ti].s, &read_set)) { - ssize_t r = read(p->port[ti].s, p->port[ti].buffer, - sizeof(p->port[ti].buffer)-1); - p->port[ti].buffer_len = r; - p->port[ti].buffer_done = 0; - TRACE(if (!p->port[ti].tap) - hdump("pty recv", p->port[ti].buffer, r);) - } - if (p->port[ti].buffer_done < p->port[ti].buffer_len) { - // write them in fifo - while (p->port[ti].buffer_done < p->port[ti].buffer_len && - !uart_pty_fifo_isfull(&p->port[ti].out)) { - int index = p->port[ti].buffer_done++; - TRACE(int wi = p->port[ti].out.write;) - uart_pty_fifo_write(&p->port[ti].out, - p->port[ti].buffer[index]); - TRACE(printf("w %3d:%02x (%d/%d) %s\n", - wi, p->port[ti].buffer[index], - p->port[ti].out.read, - p->port[ti].out.write, - p->xon ? "XON" : "XOFF");) - if (p->port[ti].hook_to_uart != NULL) { - p->port[ti].hook_to_uart(p->port[ti].buffer[index]); - } else if (p->hook_to_uart != NULL) { - p->hook_to_uart(p->port[ti].buffer[index]); - } - } - } - if (FD_ISSET(p->port[ti].s, &write_set)) { - uint8_t buffer[512]; - // write them in fifo - uint8_t * dst = buffer; - while (!uart_pty_fifo_isempty(&p->port[ti].in) && - (dst - buffer) < sizeof(buffer)) { - *dst = uart_pty_fifo_read(&p->port[ti].in); - dst++; - } - size_t len = dst - buffer; - TRACE(size_t r =) write(p->port[ti].s, buffer, len); - TRACE(if (!p->port[ti].tap) hdump("pty send", buffer, r);) - } - } - /* DO NOT call this, this create a concurency issue with the - * FIFO that can't be solved cleanly with a memory barrier - uart_pty_flush_incoming(p); - */ - } - return NULL; -} - -static const char * irq_names[IRQ_UART_PTY_COUNT] = { - [IRQ_UART_PTY_BYTE_IN] = "8avr = avr; - p->irq = avr_alloc_irq(&avr->irq_pool, 0, IRQ_UART_PTY_COUNT, irq_names); - avr_irq_register_notify(p->irq + IRQ_UART_PTY_BYTE_IN, uart_pty_in_hook, p); - - const int hastap = (getenv("SIMAVR_UART_TAP") && atoi(getenv("SIMAVR_UART_TAP"))) || - (getenv("SIMAVR_UART_XTERM") && atoi(getenv("SIMAVR_UART_XTERM"))); - p->hastap = hastap; - p->hook_from_uart = NULL; - p->hook_to_uart = NULL; - - for (int ti = 0; ti < 1 + hastap; ti++) { - int m, s; - - if (openpty(&m, &s, p->port[ti].slavename, NULL, NULL) < 0) { - fprintf(stderr, "%s: Can't create pty: %s", __FUNCTION__, strerror(errno)); - return; - } - struct termios tio; - tcgetattr(m, &tio); - cfmakeraw(&tio); - tio.c_cflag &= ~(ECHO | ECHONL); // no input echo - // tio.c_oflag |= (OPOST | ONLCR); // LF -> CRLF - tcsetattr(m, TCSANOW, &tio); - p->port[ti].s = m; - p->port[ti].tap = ti != 0; - // p->port[ti].crlf = ti != 0; - p->port[ti].crlf = 1; - p->port[ti].hook_from_uart = NULL; - p->port[ti].hook_to_uart = NULL; - if (ti > 0) { - printf("uart_pty_init %s on port *** %s ***\n", - ti == 0 ? "bridge" : "tap", p->port[ti].slavename); - } - } - - pthread_create(&p->thread, NULL, uart_pty_thread, p); - -} - -void -uart_pty_stop( - uart_pty_t * p) -{ - puts(__func__); - pthread_kill(p->thread, SIGINT); - for (int ti = 0; ti < 2; ti++) - if (p->port[ti].s) - close(p->port[ti].s); - void * ret; - pthread_join(p->thread, &ret); -} - -void -uart_pty_connect( - uart_pty_t * p, - char uart) -{ - // disable the stdio dump, as we are sending binary there - uint32_t f = 0; - avr_ioctl(p->avr, AVR_IOCTL_UART_GET_FLAGS(uart), &f); - f &= ~AVR_UART_FLAG_STDIO; - avr_ioctl(p->avr, AVR_IOCTL_UART_SET_FLAGS(uart), &f); - - avr_irq_t * src = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUTPUT); - avr_irq_t * dst = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_INPUT); - avr_irq_t * xon = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XON); - avr_irq_t * xoff = avr_io_getirq(p->avr, AVR_IOCTL_UART_GETIRQ(uart), UART_IRQ_OUT_XOFF); - - if (src && dst) { - avr_connect_irq(src, p->irq + IRQ_UART_PTY_BYTE_IN); - avr_connect_irq(p->irq + IRQ_UART_PTY_BYTE_OUT, dst); - } - if (xon) - avr_irq_register_notify(xon, uart_pty_xon_hook, p); - if (xoff) - avr_irq_register_notify(xoff, uart_pty_xoff_hook, p); - - for (int ti = 0; ti < 1+(p->hastap?1:0); ti++) if (p->port[ti].s) { - char link[128]; - snprintf(link, sizeof(link), "/tmp/simavr-uart%c%s", uart, ti == 1 ? "-tap" : ""); - unlink(link); - if (symlink(p->port[ti].slavename, link) != 0) { - fprintf(stderr, "WARN %s: Can't create %s: %s", __func__, link, strerror(errno)); - } else { - // printf("%s: %s now points to %s\n", __func__, link, p->port[ti].slavename); - } - } - if (getenv("SIMAVR_UART_XTERM") && atoi(getenv("SIMAVR_UART_XTERM"))) { - char cmd[256]; - sprintf(cmd, "xterm -e picocom -b 115200 %s >/dev/null 2>&1 &", - p->tap.slavename); - system(cmd); - } else { - // printf("note: export SIMAVR_UART_XTERM=1 and install picocom to get a terminal\n"); - } -} diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.h deleted file mode 100644 index 482de7d..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/parts/uart_pty.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - uart_pty.h - - Copyright 2012 Michel Pollet - - This file is part of simavr. - - simavr 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 3 of the License, or - (at your option) any later version. - - simavr 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. - - You should have received a copy of the GNU General Public License - along with simavr. If not, see . - */ - - -#ifndef __UART_PTY_H___ -#define __UART_PTY_H___ - -#include -#include -#include "fifo_declare.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { - IRQ_UART_PTY_BYTE_IN = 0, - IRQ_UART_PTY_BYTE_OUT, - IRQ_UART_PTY_COUNT -}; - -DECLARE_FIFO(uint8_t,uart_pty_fifo, 512); - -typedef struct uart_pty_port_t { - unsigned int tap : 1, crlf : 1; - int s; // socket we chat on - char slavename[64]; - uart_pty_fifo_t in; - uart_pty_fifo_t out; - uint8_t buffer[512]; - size_t buffer_len, buffer_done; - void (*hook_from_uart)(uint8_t); - void (*hook_to_uart)(uint8_t); -} uart_pty_port_t, *uart_pty_port_p; - -typedef struct uart_pty_t { - avr_irq_t * irq; // irq list - struct avr_t *avr; // keep it around so we can pause it - - pthread_t thread; - int xon; - int hastap; - - union { - struct { - uart_pty_port_t pty; - uart_pty_port_t tap; - }; - uart_pty_port_t port[2]; - }; - void (*hook_from_uart)(uint8_t); - void (*hook_to_uart)(uint8_t); -} uart_pty_t; - -void -uart_pty_init( - struct avr_t * avr, - uart_pty_t * b); -void -uart_pty_stop(uart_pty_t * p); - -void -uart_pty_connect( - uart_pty_t * p, - char uart); - -#ifdef __cplusplus -} -#endif - -#endif /* __UART_PTY_H___ */ - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/semaphore.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/semaphore.h deleted file mode 100644 index 289a45d..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/semaphore.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SEMAPHORE_H -#define SEMAPHORE_H - -#include -#include - -class Semaphore { - public: - Semaphore (int count_ = 0) : count(count_) { - } - - inline void notify () { - std::unique_lock lock(mtx); - count++; - //notify the waiting thread - cv.notify_one(); - } - inline void wait () { - std::unique_lock lock(mtx); - while(count == 0) { - //wait on the mutex until notify is called - cv.wait(lock); - } - count--; - } - private: - std::mutex mtx; - std::condition_variable cv; - int count; -}; - -#endif // SEMAPHORE_H diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.cpp b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.cpp deleted file mode 100644 index ba63390..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.cpp +++ /dev/null @@ -1,749 +0,0 @@ -#include "simavr.h" -#include "../sim/error.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - - -SimAvr::SimAvr () { - memset(&status, 0, sizeof(status)); -} - -SimAvr::~SimAvr () { - if (firmware != NULL) { - free(firmware); - firmware = NULL; - } - if (avr != NULL) { - free(avr); - avr = NULL; - } -} - -void SimAvr::shutdown () { - // if (pthread_mutex_lock(&lock)) { - // throw std::logic_error(error(AT, "shutdown() fails caused by mutex error")); - // } - // cancelThread = true; - // isShutdown = true; - // pthread_mutex_unlock(&lock); - addEvent(EventShutdown); -} - - -void SimAvr::load (struct StartParameters *params) { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "load() fails caused by mutex error")); - } - try { - if (isShutdown) { - throw std::logic_error(error(AT, "cannot load after simavr shutdown")); - } - if (firmware != NULL) { - throw std::logic_error(error(AT, "firmware already loaded")); - } - - startParameters = params; - firmware = (elf_firmware_t *) malloc(sizeof(elf_firmware_t)); - std::string filename = std::string(params->filename); - if (firmware == NULL || elf_read_firmware(filename.c_str(), firmware) != 0) { - throw std::logic_error(error(AT, "elf_read_firmware() from %s fails", filename.c_str())); - } - if (params->mmcu != NULL) { - strncpy(firmware->mmcu, params->mmcu, sizeof(firmware->mmcu)); - } - if (params->frequency > 0) { - firmware->frequency = (uint32_t)params->frequency; - } - if (params->vcc > 0) { - firmware->vcc = (uint32_t)params->vcc; - } - if (params->avcc > 0) { - firmware->avcc = (uint32_t)params->avcc; - } - if (params->aref > 0) { - firmware->aref = (uint32_t)params->aref; - } - - // strncpy(firmware->mmcu, "atmega324p", sizeof(firmware->mmcu)); - // firmware->frequency = 20000000L; - if (firmware->frequency == 0) { - firmware->frequency = 8000000L; - } - if (firmware->vcc == 0) { - firmware->vcc = 5000; - } - if (firmware->avcc == 0) { - firmware->avcc = 5000; - } - if (firmware->aref == 0) { - firmware->aref = 2500; - } - if (firmware->mmcu[0] == 0) { - throw std::logic_error(error(AT, "missing cpu type, use --mmcu ... to set mmcu manually)", firmware->mmcu)); - } - - avr = avr_make_mcu_by_name(firmware->mmcu); - if (!avr) { - throw std::logic_error(error(AT, "avr_make_mcu_by_name() fails (mmcu=%s)", firmware->mmcu)); - } - if (params->gdbPort > 0) { - avr->gdb_port = params->gdbPort; - } else { - avr->gdb_port = 1234; - } - printf("init with port=%d, mmcu=%s, f=%u, vcc=%d, avcc=%d, aref=%d, pc=0x%04x\n", - avr->gdb_port, firmware->mmcu, firmware->frequency, firmware->vcc, firmware->avcc, firmware->aref, params->pc < 0 ? 0 : params->pc); - status.freqHz = firmware->frequency; - - if (avr_init(avr) != 0) { - throw std::logic_error(error(AT, "avr_init() fails")); - } - - - firmware->eeprom = (uint8_t *)malloc(1024); - for (int i = 0; i < 1024; i++) { - firmware->eeprom[i] = 0xff; - } - firmware->eeprom[0] = 0xf0; - firmware->eesize = 1024; - - avr_load_firmware(avr, firmware); - status.state = StateLoaded; - - avr->fuse[AVR_FUSE_LOW] = 0xe7; - avr->fuse[AVR_FUSE_HIGH] = 0xd8; - avr->fuse[AVR_FUSE_EXT] = 0xff; - avr->lockbits = 0xff; - - avr->gdb_port = 1234; - avr_gdb_init(avr); - if (params->pc >= 0) { - avr->pc = params->pc; - } - - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } - addEvent(EventLoad); -} - -// enabled/disable character output on stdout in case of avr uart write -void SimAvr::setUartDumpEnabled (bool enabled) { - if (avr == NULL) { - throw std::logic_error(error(AT, "setUartDumpEnabled() fails because no avr available")); - } - uint32_t f = 0; - avr_ioctl(avr, AVR_IOCTL_UART_GET_FLAGS('0'), &f); - f = enabled ? f | AVR_UART_FLAG_STDIO : f & ~AVR_UART_FLAG_STDIO; - avr_ioctl(avr, AVR_IOCTL_UART_SET_FLAGS('0'), &f); - avr_ioctl(avr, AVR_IOCTL_UART_GET_FLAGS('1'), &f); - f = enabled ? f | AVR_UART_FLAG_STDIO : f & ~AVR_UART_FLAG_STDIO; - avr_ioctl(avr, AVR_IOCTL_UART_SET_FLAGS('1'), &f); -} - -void SimAvr::registerIoWrite (avr_io_addr_t addr, avrsim_io_write_callback_t callback) { - avr_register_io_write(avr, addr, (avr_io_write_t)callback, this); -} - -void SimAvr::setUartPtyEnabled (int uart, bool enable) { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "start() fails caused by mutex error")); - } - uart_pty_t *p = NULL; - try { - if (uart < 0 || uart > 1) { - throw std::logic_error(error(AT, "setUartPtyEnabled() fails (invalid uart %d)", uart)); - } - if (enable && uartPty[uart] != NULL) { - throw std::logic_error(error(AT, "enableUartPty() fails (uart %d already enabled)", uart)); - } - if (!enable && uartPty[uart] == NULL) { - throw std::logic_error(error(AT, "enableUartPty() fails (uart %d not enabled)", uart)); - } - if (avr == NULL) { - throw std::logic_error(error(AT, "enableUartPty() fails (avr not ready)")); - } - if (enable) { - p = (uart_pty_t *)malloc(sizeof(uart_pty_t)); - if (p == NULL) { - throw std::logic_error(error(AT, "enableUartPty() fails (malloc fails)")); - } - memset(p, 0, sizeof(uart_pty_t)); - // setenv("SIMAVR_UART_TAP", "1", 1); - uart_pty_init(avr, p); - uart_pty_connect(p, uart + '0'); - uartPty[uart] = p; - } else { - uart_pty_stop(uartPty[uart]); - free(uartPty[uart]); - uartPty[uart] = NULL; - } - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - if (p != NULL) { - free(p); - } - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -void SimAvr::setUartPtyHook (int uart, void (*fromUart)(uint8_t), void (*toUart)(uint8_t)) { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "setUartPtyHook() fails caused by mutex error")); - } - try { - if (uart < 0 || uart > 1) { - throw std::logic_error(error(AT, "setUartPtyHook() fails (invalid uart %d)", uart)); - } - if (uartPty[uart] == NULL) { - throw std::logic_error(error(AT, "setUartPtyHook() fails (uart %d not enabled)", uart)); - } - uartPty[uart]->hook_from_uart = fromUart; - uartPty[uart]->hook_to_uart = toUart; - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -const char *SimAvr::getUartPtyDeviceName (int uart) { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "start() fails caused by mutex error")); - } - try { - if (uart < 0 || uart > 1) { - throw std::logic_error(error(AT, "getUartPtyDeviceName() fails (invalid uart %d)", uart)); - } - uart_pty_t *p = uartPty[uart]; - pthread_mutex_unlock(&lock); - return p == NULL ? NULL : p->port[0].slavename; - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -const char *SimAvr::getTargetDeviceName () { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "start() fails caused by mutex error")); - } - try { - if (firmware == NULL) { - throw std::logic_error(error(AT, "getTargetDeviceName() fails (no firmware loaded)")); - } - pthread_mutex_unlock(&lock); - return firmware->mmcu; - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -uint32_t SimAvr::getTargetFrequency () { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "start() fails caused by mutex error")); - } - try { - if (firmware == NULL) { - throw std::logic_error(error(AT, "getTargetDeviceName() fails (no firmware loaded)")); - } - pthread_mutex_unlock(&lock); - return firmware->frequency; - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -void SimAvr::start () { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "start() fails caused by mutex error")); - } - try { - if (isShutdown) { - throw std::logic_error("start() not allowed after shutdown"); - } - if (avrRunThread != NULL) { - throw std::logic_error("simavr already started"); - } - if (avr == NULL) { - throw std::logic_error("avr not ready (check if load done)"); - } - syncTime[0] = !syncTime[1]; - avrRunThread = new std::thread(&SimAvr::avrRun, this); - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } - addEvent(EventStart); -} - - -void SimAvr::stop () { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "stop() fails caused by mutex error")); - } - try { - if (avrRunThread == NULL) { - throw std::logic_error("simavr not started"); - } - cancelThread = true; - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } - addEvent(EventStop); -} - -void SimAvr::setCommand (EnumSimAvrCommand cmd, void *param) { - if (command != ReadyForNewCommand) { - throw std::logic_error("another command pending"); - } - command = cmd; -} - -void SimAvr::addEvent (int event) { - struct timeval tp; - gettimeofday(&tp, NULL); - SimAvrEvent *p = (SimAvrEvent *)malloc(sizeof(SimAvrEvent)); - if (p != NULL) { - p->epochMillis = tp.tv_sec * 1000 + (long)tp.tv_usec / 1000; - p->event = event; - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "addEvent() fails caused by mutex error")); - } - try { - p->cycle = avr->cycle; - if (!isShutdown) { - events.push_back(p); - eventCount.notify(); - } - pthread_mutex_unlock(&lock); - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } - } -} - - -void SimAvr::setTimeSync (bool sync) { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "setTimeSync() fails caused by mutex error")); - } - try { - syncTime[1] = sync; - pthread_mutex_unlock(&lock); - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - - -struct SimAvrEvent SimAvr::waitForEvent () { - eventCount.wait(); - - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "waitForEvent() fails caused by mutex error")); - } - try { - struct SimAvrEvent rv = { epochMillis: 0, event: EventUnknown }; - struct SimAvrEvent *p = NULL; - if (events.size() > 0) { - p = events.front(); - rv = *p; - if (p->event != EventShutdown) { - events.pop_front(); - free(p); - } - if (p->event == EventShutdown) { - cancelThread = true; - isShutdown = true; - } - } - pthread_mutex_unlock(&lock); - return rv; - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } -} - -const char *SimAvr::eventText (EnumSimAvrEvent event) { - switch (event) { - case EventUnknown: return "Unknown"; - case EventShutdown: return "Shutdown"; - case EventLoad: return "Load"; - case EventStart: return "Start"; - case EventStop: return "Stop"; - default: return NULL; - } -} - -struct SimAvrStatus SimAvr::getStatus () { - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "getStatus() fails caused by mutex error")); - } - struct SimAvrStatus rv = status; - pthread_mutex_unlock(&lock); - return rv; -} - -void SimAvr::printCyclesAndElapsedTime () { - uint64_t time = avr->cycle * 1000000000L / avr->frequency; - uint16_t nanos = time % 1000; time = time / 1000; - uint16_t micros = time % 1000; time = time / 1000; - uint16_t millis = time % 1000; time = time / 1000; - uint16_t seconds = time % 1000; time = time / 1000; - printf("cycle %" PRIu64 " = %ds %03dms %03dµs %03dns", avr->cycle, seconds, millis, micros, nanos); -} - -void SimAvr::avrRun () { - long cnt = 0; - int lastAvrState = -1; - _avr_sp_set(avr, 0); - while (1) { - try { - if (avr->state != lastAvrState) { - switch (avr->state) { - case cpu_Stopped: { - printf("\ncpu stopped at 0x%04x on ", avr->pc); - printCyclesAndElapsedTime(); - char sfr[9]; - sfr[7] = avr->sreg[0] ? 'C' : '-'; - sfr[6] = avr->sreg[1] ? 'Z' : '-'; - sfr[5] = avr->sreg[2] ? 'N' : '-'; - sfr[4] = avr->sreg[3] ? 'V' : '-'; - sfr[3] = avr->sreg[4] ? 'S' : '-'; - sfr[2] = avr->sreg[5] ? 'H' : '-'; - sfr[1] = avr->sreg[6] ? 'T' : '-'; - sfr[0] = avr->sreg[7] ? 'I' : '-'; - sfr[8] = 0; - printf(" SFR: %s\n ", sfr); - uint16_t x = 0, y = 0, z = 0; - for (int i = 0; i < 32; i++) { - uint8_t b = avr->data[i]; - printf(" r%02d=%02x", i, b); - switch (i) { - case 0x0f: printf("\n "); break; - case 0x1a: x = (x & 0xff00) | b; break; - case 0x1b: x = (x & 0x00ff) | (b << 8); break; - case 0x1c: y = (y & 0xff00) | b; break; - case 0x1d: y = (y & 0x00ff) | (b << 8); break; - case 0x1e: z = (z & 0xff00) | b; break; - case 0x1f: z = (z & 0x00ff) | (b << 8); break; - } - } - printf("\n X=0x%04x Y=0x%04x Z=0x%04x\n", x, y, z); - - uint16_t sp = _avr_sp_get(avr); - printf(" Stack (SP=0x%04x)", sp); - int printHeader = 1; - for (int i = 0; i < 16; i++) { - uint16_t addr = sp + 1 + i; - if (addr <= avr->ioend) { continue; } - if (addr > avr->ramend) { break; } - if (printHeader) { - printf(" -> SRAM 0x%04x:", addr); - printHeader = 0; - } - uint8_t b = avr_core_watch_read(avr, addr); - printf(" %02x", b); - - } - printf(printHeader ? "\n" : "\n"); - - printf(" Arduino LED L: "); - printf((avr->data[0x24] & 0x20) && (avr->data[0x25] & 0x20) ? "ON\n" : "OFF\n"); - - printf("\n"); - break; - } - case cpu_Sleeping: printf("cpu enter sleep mode at cycle %" PRIu64 "\n", avr->cycle); break; - case cpu_Running: printf("cpu starts running at cycle %" PRIu64 "\n", avr->cycle); break; - case cpu_Step: printf("cpu step\n"); break; - case cpu_StepDone: printf("cpu step done\n"); break; - case cpu_Done: printf("cpu done\n"); break; - case cpu_Crashed: printf("cpu crashed\n"); break; - default: printf("cpu enter unknown mode at cycle %" PRIu64 "\n", avr->cycle); break; - } - lastAvrState = avr->state; - } - - if (startParameters != NULL) { - switch (startParameters->board) { - case BoardNano: { - static int8_t ledL = -1; // pin floating - uint8_t ddrb = avr->data[0x24]; - uint8_t portb = avr->data[0x25]; - int8_t nextLedL = -1; - if (ddrb & 0x20) { - nextLedL = portb & 0x20 ? 1 : 0; - } - if (nextLedL != ledL) { - ledL = nextLedL; - printCyclesAndElapsedTime(); - printf(": LED L = %c\n", ledL ? 'X' : '.'); - } - break; - } - case BoardSure: { - static int8_t led[4] = { -1, -1, -1, -1 }; // pin floating - uint8_t ddra = avr->data[0x3a]; - uint8_t porta = avr->data[0x3b]; - int change = 0; - for (int i = 0; i < 4; i++) { - int8_t nextLed = -1; - if (ddra & (1 << i)) { - nextLed = porta & (1 << i) ? 0 : 1; - } - if (nextLed != led[i]) { - change = 1; - led[i] = nextLed; - } - } - if (change) { - printCyclesAndElapsedTime(); printf(": "); - printf(" LED PA[3210] ="); - for (int i = 3; i >= 0; i--) { - printf(" %c", led[i] ? 'X' : '.'); - } - printf("\n"); - } - break; - } - case BoardEWS1: { - static int8_t led = -1; // pin floating - uint8_t ddrb = avr->data[0x24]; - uint8_t portb = avr->data[0x25]; - int8_t nextLed = -1; - if (ddrb & 0x01) { - nextLed = portb & 0x01 ? 1 : 0; - } - if (nextLed != led) { - led = nextLed; - printCyclesAndElapsedTime(); - printf(": LED1 (PB0) = %c\n", led ? 'X' : '.'); - } - break; - } - default: break; - } - } - - if (cnt <= 0) { - // usleep(10000); - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "avrRun() fails caused by mutex error (1)")); - } - try { - status.cycle = avr->cycle; - status.state = StateRunning; - status.running = true; - switch (avr->state) { - case cpu_Done: status.state = StateDone; break; - case cpu_Running: status.state = StateRunning; break; - case cpu_Crashed: status.state = StateCrashed; break; - default: status.state = StateOthers; break; - } - if (cancelThread) { - cnt = -1; - cancelThread = false; - } else { - if (syncTime[0] != syncTime[1]) { - syncTime[0] = syncTime[1]; - if (syncTime[0]) { - cyclesOnSyncStart = avr->cycle; - struct timeval tp; - gettimeofday(&tp, NULL); - timeMicrosOnSyncStart = tp.tv_usec + (uint64_t)tp.tv_sec * 1000000L; - } else { - cyclesOnSyncStart = -1; - timeMicrosOnSyncStart = 0; - } - } - if (syncTime[0]) { - uint64_t ucMicros = (uint64_t)(status.cycle - cyclesOnSyncStart) * 1000000L / status.freqHz ; - struct timeval tp; - gettimeofday(&tp, NULL); - const uint64_t timeMicros = tp.tv_usec + (uint64_t)tp.tv_sec * 1000000L - timeMicrosOnSyncStart; - - if (ucMicros > 3000000) { - ucMicros++; - } - - int64_t dt = ucMicros - timeMicros; - if (dt > 0) { - int us = dt > INT_MAX ? INT_MAX : (int)dt; - if (us > 1000) { - timeval ts; - ts.tv_sec = 0; - ts.tv_usec = us; - select(0, 0, 0, 0, &ts); - } - } - } - } - if (avr->state == cpu_Done) { - cnt = -1; - } else if (avr->state == cpu_Crashed) { - throw std::logic_error(error(AT, "avr state is cpu_Crashed")); - } - pthread_mutex_unlock(&lock); - - } catch (std::exception& e) { - status.state = StateError; - pthread_mutex_unlock(&lock); - throw; - } - } - - if (avr->state == cpu_Stopped) { - timeval ts; - ts.tv_sec = 0; - ts.tv_usec = 1000; - select(0, 0, 0, 0, &ts); - } - - if (cnt < 0) { - cyclesOnSyncStart = -1; - timeMicrosOnSyncStart = 0; - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "avrRun() fails caused by mutex error (2)")); - } - try { - if (avrRunThread != NULL) { - avrRunThread->detach(); - delete avrRunThread; - avrRunThread = NULL; - } - pthread_mutex_unlock(&lock); - return; - } catch (std::exception& e) { - pthread_mutex_unlock(&lock); - status.state = StateError; - throw; - } - - } else if (++cnt >= 100000) { - cnt = 0; - } - - if (command != ReadyForNewCommand) { - switch (command) { - case CommandStatus: { - printCyclesAndElapsedTime(); - printf("\n"); - break; - } - case CommandInterrupt: { - if (avr->state == cpu_Running) { - avr->state = cpu_Stopped; - } - break; - } - case CommandContinue: { - if (avr->state == cpu_Stopped) { - avr->state = cpu_Running; - } - break; - } - case CommandStack: { - uint16_t sp = _avr_sp_get(avr); - printf("Stack: SP=0x%04x:\n", sp); - for (uint16_t addr = ((sp + 1) / 16) * 16; addr <= avr->ramend; addr++) { - if (addr % 16 == 0) { - printf(" 0x%04x:", addr); - } - if (addr % 4 == 0) { - printf(" "); - } - if (addr <= sp) { - printf(" "); - } else { - uint8_t b = avr_core_watch_read(avr, addr); - printf(" %02x", b); - } - if (addr % 16 == 15) { - printf("\n"); - } - } - printf("\n"); - break; - } - - default: break; - } - command = ReadyForNewCommand; - addEvent(EventCommandExecuted); - } - - avr_run(avr); - - } catch (std::exception& e) { - status.state = StateError; - cyclesOnSyncStart = -1; - timeMicrosOnSyncStart = 0; - if (pthread_mutex_lock(&lock)) { - throw std::logic_error(error(AT, "avrRun() fails caused by mutex error (2)")); - } - try { - if (avrRunThread != NULL) { - avrRunThread->detach(); - delete avrRunThread; - avrRunThread = NULL; - } - pthread_mutex_unlock(&lock); - throw; - } catch (std::exception& e) { - pthread_mutex_unlock(&lock); - status.state = StateError; - throw; - } - - } - } -} - diff --git a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.h b/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.h deleted file mode 100644 index e1455b7..0000000 --- a/examples/simuc/dpkg/htl-simuc_version_arch/usr/share/htl-simuc/simuc/src/simavr/simavr.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef SIMAVR_H -#define SIMAVR_H - -#include "semaphore.h" -#include "parts/uart_pty.h" - -#include -#include -#include - -#include -#include -#include - -typedef enum { - BoardUnknown = 0, - BoardNano, - BoardSure, - BoardEWS1 -} EnumStartParameterBoard; - - -struct StartParameters { - char *filename; - int gdbPort; - int64_t frequency; - const char *mmcu; - EnumStartParameterBoard board; - int32_t pc; - int32_t vcc; - int32_t avcc; - int32_t aref; -}; - -enum SimAvrState { - StateInit = 0, - StateError = 1, - StateLoaded = 10, - StateRunning = 11, - StateDone = 12, - StateCrashed = 20, - StateOthers = 99, - StateUnknown = 100 -}; - -typedef enum { - EventUnknown = 0, - EventShutdown = -1, - EventLoad = -2, - EventStart = -3, - EventStop = -4, - EventCommandExecuted = -5 -} EnumSimAvrEvent; - -typedef enum { - ReadyForNewCommand = 0, - CommandStatus, - CommandInterrupt, - CommandContinue, - CommandStack -} EnumSimAvrCommand; - -struct SimAvrStatus { - long long freqHz; - long long cycle; - enum SimAvrState state; - bool running; -}; - -struct SimAvrEvent { - long long epochMillis; - long long cycle; - int event; -}; - - -class SimAvr; -typedef void (*avrsim_io_write_callback_t)(avr_t *avr, avr_io_addr_t addr, uint8_t value, SimAvr *simavr); - -class SimAvr { - -public: - SimAvr (); - ~SimAvr (); - - struct SimAvrStatus getStatus (); - struct SimAvrEvent waitForEvent (); - const char *eventText (EnumSimAvrEvent event); - -public: - void load (struct StartParameters *params); - void shutdown (); - void start (); - void stop (); - void addEvent (int event); - void setUartDumpEnabled (bool enabled); - void setUartPtyEnabled (int uart, bool enabled); - void setUartPtyHook (int uart, void (*fromUart)(uint8_t), void (*toUart)(uint8_t)); - void registerIoWrite (avr_io_addr_t addr, avrsim_io_write_callback_t callback); - - const char *getTargetDeviceName (); - uint32_t getTargetFrequency (); - const char *getUartPtyDeviceName (int uart); - - void avrRun (); - void setLed (bool on); - void setTimeSync (bool sync); - void setCommand (EnumSimAvrCommand cmd, void *param); - -private: - elf_firmware_t *firmware = NULL; - avr_t *avr = NULL;; - StartParameters *startParameters = NULL;; - pthread_mutex_t lock; - std::list events; - EnumSimAvrCommand command; - struct SimAvrStatus status; - bool cancelThread = false; - bool isShutdown = false; - bool syncTime[2] = { false, true }; - std::thread *avrRunThread = NULL; - long cyclesOnSyncStart = -1; - uint64_t timeMicrosOnSyncStart = 0; - Semaphore eventCount; - uart_pty_t *uartPty[2] = { NULL, NULL }; - void printCyclesAndElapsedTime (); -}; - - - - -#endif // SIMAVR_H \ No newline at end of file