Skip to content

Commit

Permalink
prepare for quicklisp submission; add gdb support
Browse files Browse the repository at this point in the history
  • Loading branch information
markasoftware committed Jul 24, 2020
1 parent af1e895 commit 46c1689
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 14 deletions.
2 changes: 2 additions & 0 deletions examples/analog-to-serial.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
(defun analog-to-serial ()
"Test that the analog voltage gets sent over serial UART."

(load-foreign-libraries)

(in-suite analog-to-serial)

(runtest "Sends Hello World on boot"
Expand Down
2 changes: 2 additions & 0 deletions examples/at-least-two.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
(defun at-least-two ()
"Test that an LED turns on when at least two of three buttons are depressed."

(load-foreign-libraries)

(in-suite at-least-two)

(runtest "Light starts in the off state"
Expand Down
2 changes: 2 additions & 0 deletions examples/blink.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"Test that a blinking LED on the Arduino UNO actually blinks."
;; light starts off, turns on after .5s, then turns off after .5s, etc.

(load-foreign-libraries)

(in-suite blink)

(runtest "Light starts in the off state."
Expand Down
2 changes: 2 additions & 0 deletions examples/serial-spongebob.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"Test that our text gets spongebobified, and explore some nuances of uart
simulation"

(load-foreign-libraries)

;; Two compounding issues: simavr is bugged and thinks 8N1 has 11 bits per
;; byte instead of 10, and 115200 has a -3.5% error at 16MHz.
(let ((*suite* 'serial-spongebob)
Expand Down
4 changes: 2 additions & 2 deletions gooptest.asd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
:description "A microcontroller testing framework."
:author "Mark Polyakov"
:license "GPL-3.0"
:version "0.0.1"
:version "0.1.0"
:serial t
:depends-on (#:cffi #:cl-autowrap #:cl-plus-c #:alexandria #:uiop #:babel)
:components ((:file "package")
Expand All @@ -29,7 +29,7 @@
:description "Examples for a microcontroller testing framework."
:author "Mark Polyakov"
:license "GPL-3.0"
:version "0.0.1"
:version "0.1.0"
:serial t
:depends-on (#:gooptest)
:pathname "examples"
Expand Down
10 changes: 8 additions & 2 deletions package.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#:uart-send
#:uart-string
#:until-uart
#:set-spi-handler
#:spi-handle

#:defsuite
#:in-suite
Expand Down Expand Up @@ -60,9 +62,13 @@
#:plus-c)
(:export #:make-core

;; non-functions
#:avr-core ; class
#:load-foreign-libraries

#:make-arduino-uno
#:make-arduino-nano

;; non-functions
#:avr-core ; class

#:*gdb-port*
))
31 changes: 29 additions & 2 deletions src/gooptest-avr.lisp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
(in-package :gooptest-avr)

(cffi:load-foreign-library "libelf.so")
(cffi:load-foreign-library "libsimavr.so")
(defun load-foreign-libraries ()
(cffi:load-foreign-library "libelf.so")
(cffi:load-foreign-library "libsimavr.so"))

(defclass avr-core (core)
((avr-ptr :accessor get-ptr :type avr-t)
Expand All @@ -11,6 +12,10 @@
or a vector of unsigned bytes, representing everything received over
that uart so far.")))

(defvar *gdb-port* nil
"When non-nil, simulations will not start until a GDB debugger attaches to the
given port.")

(defun avr-ioctl-def (c1 c2 c3 c4)
"See simavr/sim_io.h"
(flet ((intify (arg)
Expand Down Expand Up @@ -191,6 +196,22 @@ cffi:get-callback)"
)
fifo-space-p))

(defmethod core-spi-default-channel ((instance avr-core))
0)

(defmethod core-spi-set-handler ((instance avr-core) handler channel)
"Channel is an integer indicating the SPI port as understood by simavr."
(declare ((integer 0) channel))
(let* ((irq-def (avr-ioctl-def #\s #\p #\i channel))
;; TODO: replace with +spi-irq-input+ (and output, later)
(output-irq (avr-io-getirq irq-def 0))
(input-irq (avr-io-getirq irq-def 1)))
(avr-irq-register-notify
input-irq
(make-irq-callback byte
`(avr-raise-irq ,output-irq (funcall ,handler byte)))
(cffi:null-pointer))))

(defmethod core-one-cycle ((instance avr-core))
(avr-run (get-ptr instance))
(setf (core-elapsed instance) (c-ref (get-ptr instance) avr-t :cycle))
Expand Down Expand Up @@ -241,6 +262,12 @@ cffi:get-callback)"
(setf (c-ref (get-ptr instance) avr-t :avcc) (floor (* 1000 vcc)))
)

(when *gdb-port*
(setf (c-ref (get-ptr instance) avr-t :gdb-port) *gdb-port*)
;; prevents core from starting until gdb attaches
(setf (c-ref (get-ptr instance) avr-t :state) +cpu-stopped+)
(avr-gdb-init (get-ptr instance)))

;; TODO
;; (trivial-garbage:finalize instance (lambda ()
;; ()))
Expand Down
26 changes: 18 additions & 8 deletions src/gooptest.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -247,24 +247,34 @@ Respects *core*."
do (cycles-rel ,skip))
(cycles-abs ,finally)))))

(defun pin-duty-cycle (p stop &optional (skip *skip*))
(defun pin-duty-cycle (p &key stop (skip *skip*) pull)
"Returns the duty cycle of the given pin, as a fraction. Records for the
length given by the timespec. Works for digital output pins; will throw an error
if a pin state other than :high or :low is detected. skip-timespec can be used
to improve performance by specifying how many cycles to let pass between polling
the pin.
if a pin state other than :high or :low is detected. pull can be :up or :down to
measure as if there's a pullup or pulldown resistor. skip can be used to improve
performance by specifying how many cycles to let pass between polling the pin.
Respects *core*"
(declare ((or (member :up :down) null) pull))
;; required key arguments :|
(assert stop)
(resolve-timespecs (stop) (skip)
;; TODO: verify off-by-one errors (i.e, does it stop one poll-timespec
;; before timespec? Or after? Does it always run exactly timespec cycles?)
(loop
with positive-samples = 0
for total-samples from 1
;; use ecase to throw errors on non-digital values.
when (ecase (pin p)
(:high t)
(:low nil))
when (ecase pull
((nil) (ecase (pin p)
(:high t)
(:low nil)))
(:up (ecase (pin p)
(:low t)
(:float nil)))
(:down (ecase (pin p)
(:high t)
(:float nil))))
do (incf positive-samples)
while (<= (+ (elapsed) skip) stop)
do (cycles-rel skip)
Expand Down Expand Up @@ -314,7 +324,7 @@ the delay between characters. If finally is non-nil (the default), will wait at
the end of transmission the equivalent of one characters length, so that it is
safe to call (uart-send) multiple times in a row.
Respects *core*"
Respects *core*."
(setf data
(etypecase data
((or string character) (babel:string-to-octets (string data)))
Expand Down

0 comments on commit 46c1689

Please sign in to comment.