ryansuchocki / microscheme

A Scheme subset for Atmel microcontrollers.

Home Page:http://ryansuchocki.github.io/microscheme/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Type exceptions triggered erronously when using vectors

technomancy opened this issue · comments

In my own code I can't seem to get any programs using vectors or lists to execute without hitting exception 5 or exception 6.

(define column-pins (vector 11 12 15 14 10 4 7 8 9 5 6))

(for-each-vector input column-pins)
(for-each-vector high column-pins)

(pause 500)

Replacing the vector/for-each-vector with list/for-each doesn't make a difference.

A more elaborate example is at https://github.com/technomancy/menelaus/blob/master/menelaus.scm in which I have a couple places where vector-using code causes exceptions but unrolled loops work fine.

I could be wrong, but I don't think this is a microscheme bug.

In minelaus.scm (as of current commit):

  • column-pins is defined as a list, then used as a vector
  • On lines 45 and 46, you have (for-each-vector vect proc) rather than (for-each-vector proc vect
  • column-pins has 11 elements, while layout has 10. This is the source of the 'Out Of Bounds' error when your (loop) tries to access them in tandem. i.e. (for 0 10 .....) makes exactly 11 iterations.

Hah, well... can't even blame that on a late night. Still, the example in the body of the issue above produces exception 6, and I can't find a problem with it. Any ideas?

Not sure if this is related, but I get exception 2 from this:

(define pressed 0)

(define (loop)
  (set! pressed 0)
  (for 0 10 (lambda (n) 0))
  (loop))

(loop)

OK I think I've got to the bottom of this.

The problem seems to be with the interrupt handlers. Microscheme doesn't use interrupts at all, but the C keyboard library obviously uses interrupts for what I assume is some very important USB stuff...

The trouble is: Those ISRs can be triggered at any point, i.e. when microscheme code is running. In those cases, the C code screws up the microscheme special registers, which in turn leads to seemingly random microscheme exceptions...

I've made a quick fix for this, which is to make sure that the global interrupt flag is disabled whenever ms code is running. (pushed just now)

This seems to be enough to get menelaus running for me. (With the corrections from my last comment too.) By which, I mean that it seems to spew out predictable characters when I pull the column pins low...

Oh, one last thing...

The code uses a (lambda ...) inside the infinite (loop)... This will cause the program to fail very quickly, because every time that lambda is evaluated, it places a closure on the heap. Since ms has no garbage collection, ~2 KB of heap runs out very quickly...

Quick fix: wrap the for loop with a (free! ...)
Better fix: eliminate the lambda, just push 'n' to scan-column...

i.e.

(define (scan-column n)
  (if (and (= 0 pressed) (low? (vector-ref column-pins n)))
      (set! pressed (vector-ref layout n))))

...

(for 0 9 scan-column)

RE your third comment, the exception here is also coming from memory overflow.

Fix:

(define pressed 0)

(define (loop)
  (set! pressed 0)
  (free! (for 0 10 (lambda (n) 0)))
  (loop))

(loop)

I just realised I haven't actually documented (free! ) anywhere. All the language documentation needs an overhaul...

For your benefit:

(free! code ...) means: evaluate 'code ...', and then re-claim any memory that was allocated while doing so.

In other words: avoiding garbage collection by occasionally setting fire to the trash can. :)

Thanks for looking into this; it has helped a lot.

I'm still getting unexplainable failures though. The code below works fine, but if I replace any single value in one of the vectors, it causes exception 2: http://p.hagelb.org/menelaus-fold-bug.scm.html

Do you think this might be related, or is it a different bug?

I'm still chasing at least one bug...
Can you wrap your (let ....) with (free! ...), pull the latest commit, and see if it still does that?

That takes care of this exception; thanks!