It appears uLisp does not offer access to MMIO. For example, it is not possible to read/write a byte to/from a particular offset. Is this correct or am I misunderstanding? Thank you.
I’m not sure it’s useful on the platforms that uLisp supports, but I’m sure it would be easy to add support for it; see Adding your own functions.
MMIO is generally how the platforms that uLisp supports are programmed. A majority of the datasheets are dedicated to MMIO offsets and their functions. The registers are used to control every MCU function. The relevant macros/functions for avr are in <avr/sfr_defs.h>. These are selectively included in <avr/io.h> based on the -mmcu flag. What it all boils down to is declaring a variable at a particular offset. <avr/io.h> creates device specific variables which are convenient but not necessary because we can just “int *var = (int*)0x00;” for whatever register offset we need.
A specific example… If I wanted to do PWM via uLisp on atmega328p I would not be able to because enabling PWM requires me to write to the WGM0 and COM0 registers.
Is it correct that I cannot read/write to/from any device registers via uLisp? Would I have to write a C wrapper function for each specific read/write sequence?
I am interested in this functionality because it would be convenient to be able to read/write registers from a terminal. AFAIK no other system allows this but uLisp seems singularly positioned to do so.
I think you could provide general uLisp functions write-register and read-register that would allow you to write to and read from any memory-mapped register. For example, on the ATmega328P you could then do:
(write-register #x24 #x03)
to set register TCCR0A at #x24 to 3.
That’s exactly what I’m referring to. Was surprised to not find such functions in the uLisp reference. Are there any plans to make this part of core uLisp? Seems really useful. Would allow terminal control as mentioned previously, register control via composable lisp functions, and probably many other things that I’m not thinking of.
Generally uLisp’s philosophy is to hide the low-level processor-specific functionality, and provide high-level functions, such as for writing to an I2C port, that you can use irrespective of what platform you’re on.
However, there’s no reason you shouldn’t add these functions yourself. You might find this a useful starting point:
but note that in the latest version of uLisp you need to use checkinteger() rather than integer(), with the appropriate symbol (eg PEEK or POKE) as the first parameter.
It would also be useful to provide a set of defvar statements such as:
(defvar TCCR0A #x24)
Thank you. Great info. I had been searching for MMIO. Not familiar with the peek/poke terminology but exactly what I’m looking for.
I wonder if instead of doing defvar for each register there is a way to leverage the fact that platform specific register names are already defined in <avr/io.h>. Hmmm…