2008-07-29 11:08:54 +00:00
|
|
|
(NOTE: view this file with a monospaced font)
|
|
|
|
|
2008-08-08 12:56:29 +00:00
|
|
|
eLua platform modules
|
2008-07-29 11:08:54 +00:00
|
|
|
================================================================================
|
|
|
|
|
2008-09-02 10:55:35 +00:00
|
|
|
(NOTE: after reading this, check also the "generic_modules.txt" file to
|
|
|
|
learn about the generic (not platform specific) modules from eLua).
|
|
|
|
|
2008-07-29 11:08:54 +00:00
|
|
|
In order to make eLua usable on different platform, eLua provides a number of
|
|
|
|
"platform modules" that link the language with the hardware platform. They're
|
|
|
|
mainly tied up with the platform peripherals (PIO, UART, SPI and others).
|
2008-09-02 10:55:35 +00:00
|
|
|
They are loaded when Lua starts (just like the "standard" modules like os, math,
|
|
|
|
string).
|
2008-07-29 11:08:54 +00:00
|
|
|
|
|
|
|
All the platform modules have two parts: the generic part (the one that is
|
|
|
|
exposed directly to Lua and it's supposed to be platform independent) and the
|
|
|
|
platform specific part (the one that links the module operations to actual
|
|
|
|
hardware operations). Consequently, when adding a new platform, one doesn't need
|
|
|
|
to rewrite the whole module, just the platform-dependent part. The "platform
|
|
|
|
interface.txt" file shows the conenction between platform modules and platform
|
|
|
|
interface functions. For example, the "pio" module (src/modules/pio.c) needs 3
|
|
|
|
functions for interfacing with a specific platform: platform_pio_has_port,
|
|
|
|
platform_pio_has_pin and platform_pio_op.
|
|
|
|
|
|
|
|
All the modules are located in the "src/modules" directory. Besides their
|
|
|
|
actual implementation, the "src/modules/auxmods.h" file contains the Lua
|
|
|
|
compatible description of all the modules in the system.
|
|
|
|
|
|
|
|
Sometimes it doesn't make sense to include all the modules for a particular
|
|
|
|
platform. For example, for the i386 platform it doesn't make sense to include
|
|
|
|
the "pio" module (although this is technically possible by providing "bogus"
|
|
|
|
platform interface functions, the module won't be able to do anything on a i386
|
|
|
|
CPU, unless you want to "emulate" it via the parallel port or some other
|
2008-10-31 21:32:15 +00:00
|
|
|
peripheral). To accomodate this, each platform must provide a "platform_conf.h"
|
|
|
|
(src/platform/<your platform>) which (amongst other things) lists the modules
|
|
|
|
that are used for that specific platform. For example, if we want to enable
|
|
|
|
only the PIO module for the AT91SAM7X platform, the "platform_conf.h" file
|
|
|
|
would look like this:
|
2008-07-29 11:08:54 +00:00
|
|
|
|
2008-10-31 21:32:15 +00:00
|
|
|
(BEGIN src/platform/at91sam7x/platform_conf.h)
|
2008-07-29 11:08:54 +00:00
|
|
|
// Auxiliary libraries that will be compiled for this platform
|
|
|
|
|
2008-10-31 21:32:15 +00:00
|
|
|
#ifndef __PLATFORM_CONF_H__
|
|
|
|
#define __PLATFORM_CONF_H__
|
2008-07-29 11:08:54 +00:00
|
|
|
|
|
|
|
#include "auxmods.h"
|
|
|
|
|
2008-10-31 21:32:15 +00:00
|
|
|
...............................................................
|
|
|
|
|
2008-07-29 11:08:54 +00:00
|
|
|
#define LUA_PLATFORM_LIBS\
|
|
|
|
{ AUXLIB_PIO, luaopen_pio }
|
|
|
|
|
|
|
|
#endif
|
2008-10-31 21:32:15 +00:00
|
|
|
(END src/platform/at91sam7x/platform_conf.h)
|
2008-07-29 11:08:54 +00:00
|
|
|
|
2008-09-10 18:52:26 +00:00
|
|
|
On the other hand, for a platform that doesn't need to enable any modules at
|
2008-10-31 21:32:15 +00:00
|
|
|
all, you don't even need to define the LUA_PLATFORM_LIBS macro.
|
2008-07-29 11:08:54 +00:00
|
|
|
This is why some of platform functions described in "platform interface.txt" are
|
|
|
|
optional. If there are no modules that use them in one platform, then you don't
|
|
|
|
need to define them at all for that platform, not even as "bogus" functions.
|
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The PIO module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
The PIO module lets Lua access the programmable input/output (PIO) pins of the
|
|
|
|
microcontroller. It exposes symbolic name for ports (pio.PA, pio.PB, ... pio.PF)
|
2008-09-02 10:55:35 +00:00
|
|
|
and symbolic names for port pins (pio.PA_0, pio.PA_1, ... pio.PB_30, ...). Also,
|
2008-07-29 11:08:54 +00:00
|
|
|
it exposes functions to access both ports and pins:
|
|
|
|
|
|
|
|
pio.setpin( value, Pin1, Pin2 ... ): set the value to all the pins in the list
|
|
|
|
to "value" (0 or 1).
|
|
|
|
|
|
|
|
pio.set( Pin1, Pin2, ... ): set the value of all the pins in the list to 1.
|
|
|
|
|
|
|
|
Val1, Val2, ... = pio.get( Pin1, Pin2, ... ): reads one or more pins and returns
|
|
|
|
their values (0 or 1).
|
2008-09-02 10:55:35 +00:00
|
|
|
|
|
|
|
pio.clear( Pin1, Pin2, ... ): set the value of all the pins in the list to 0.
|
2008-07-29 11:08:54 +00:00
|
|
|
|
|
|
|
pio.input( Pin1, Pin2, ... ): set the specified pin(s) as input(s).
|
|
|
|
|
|
|
|
pio.output( Pin1, Pin2, ... ): set the specified pin(s) as output(s).
|
|
|
|
|
|
|
|
pio.setport( value, Port1, Port2, ... ): set the value of all the ports in the
|
|
|
|
list to "value".
|
|
|
|
|
|
|
|
Val1, Val2, ... = pio.getport( Port1, Port2, ... ): reads one or more ports and
|
|
|
|
returns their values.
|
|
|
|
|
|
|
|
pio.port_input( Port1, Port2, ... ): set the specified port(s) as input(s).
|
|
|
|
|
|
|
|
pio.port_output( Port1, Port2, ... ): set the specified port(s) as output(s).
|
|
|
|
|
2008-09-02 10:55:35 +00:00
|
|
|
pio.pullup( Pin1, Pin2, ... ): enable internal pullups on the specified pins.
|
|
|
|
Note that some CPUs might not provide this feature.
|
|
|
|
|
|
|
|
pio.pulldown( Pin1, Pin2, ... ): enable internal pulldowns on the specified
|
|
|
|
pins. Note that some CPUs might not provide this feature.
|
|
|
|
|
|
|
|
pio.nopull( Pin1, Pin2, ... ): disable the pullups/pulldowns on the specified
|
|
|
|
pins. Note that some CPUs might not provide this feature.
|
|
|
|
|
|
|
|
Port = pio.port( code ): return the physical port number associated with the
|
|
|
|
given code. For example, "pio.port( pio.P0_20 )" will return 0.
|
|
|
|
|
|
|
|
Pin = pio.pin( code ): return the physical port number associated with the
|
|
|
|
given code. For example, "pio.pin( pio.P0_20 )" will return 20.
|
|
|
|
|
2008-07-29 11:08:54 +00:00
|
|
|
================================================================================
|
|
|
|
=== The SPI module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
The SPI module lets Lua access the SPI interfaces of the target CPU. It exposes
|
|
|
|
functions for SPI setup and sending/receiving data, selecting/unselecting slave
|
|
|
|
devices, as well as different SPI specific constants.
|
|
|
|
|
|
|
|
Actual_clock = spi.setup( id, spi.MASTER | spi.SLAVE, clock, cpol, cpha,
|
|
|
|
databits): set the SPI interface with the given parameters, returns the clock
|
|
|
|
that was set for the interface.
|
|
|
|
|
|
|
|
spi.select( id ): sets the SS line of the given interface.
|
|
|
|
|
|
|
|
spi.unselect( id ): clears the SS line of the given interface.
|
|
|
|
|
|
|
|
spi.send( id, Data1, Data2, ... ): sends all the data to the specified SPI
|
|
|
|
interface.
|
|
|
|
|
|
|
|
In1, In2, ... = spi.send_recv( id, Out1, Out2, ... ): sends all the "out" bytes
|
|
|
|
to the specified SPI interface and returts the data read after each sent byte.
|
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The UART module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
The UART module lets Lua access the UART interfaces of the target CPU. It
|
|
|
|
exposes functions for UART setup and sending/receiving data, as well as some
|
|
|
|
UART specific constants.
|
|
|
|
|
|
|
|
Actual_baud = uart.setup( id, baud, databits,
|
|
|
|
uart.PAR_EVEN |uart.PAR_ODD | uart.PAR_NONE,
|
|
|
|
uart.STOP_1 | uart.SSTOP_1_5 | uart.STOP_2 ): set the UART interface with the
|
|
|
|
given parameters, returns the baud rate that was set for the UART.
|
|
|
|
|
|
|
|
uart.send( id, Data1, Data2, ... ): send all the data to the specified UART
|
|
|
|
interface.
|
|
|
|
|
|
|
|
Data = uart.recv( id, uart.NO_TIMEOUT | uart.INF_TIMEOUT | timeout ): reads a
|
|
|
|
byte from the specified UART interface.
|
|
|
|
|
2008-08-08 15:55:03 +00:00
|
|
|
uart.sendstr( id, str1, str2, ... ): this is similar to "uart.send", but its
|
|
|
|
parameters are string.
|
2008-07-29 11:08:54 +00:00
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The timer module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
It allows Lua to execute timer specific operations (delay, read timer value,
|
|
|
|
start timer, get time difference).
|
|
|
|
|
|
|
|
tmr.delay( id, delay ): uses timer 'id' to wait for 'delay' us.
|
|
|
|
|
|
|
|
Data = tmr.read( id ): reads the value of timer 'id'. The returned value is
|
|
|
|
platform dependent.
|
|
|
|
|
|
|
|
Data = tmr.start( id ): start the timer 'id', and also returns its value at
|
|
|
|
the moment of start. The returned value is platform dependent.
|
|
|
|
|
|
|
|
diff = tmr.diff( id, end, start ): returns the time difference (in us) between
|
|
|
|
the timer values 'end' and 'start' (obtained from calling tmr.start or
|
|
|
|
tmr.read). The order of end/start is irrelevant.
|
|
|
|
|
|
|
|
Data = tmr.mindelay( id ): returns the minimum delay (in us ) that can be
|
|
|
|
achieved by calling the tmr.delay function. If the return value is 0, the
|
|
|
|
platform layer is capable of executing sub-microsecond delays.
|
|
|
|
|
|
|
|
Data = tmr.maxdelay( id ): returns the maximum delay (in us) that can be
|
|
|
|
achieved by calling the tmr.delay function.
|
|
|
|
|
|
|
|
Data = tmr.setclock( id, clock ): sets the clock of the given timer. Returns the
|
|
|
|
actual clock set for the timer.
|
|
|
|
|
|
|
|
Data = tmr.getclock( id ): return the clock of the given timer.
|
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The platform data module
|
|
|
|
================================================================================
|
|
|
|
|
2008-09-02 10:55:35 +00:00
|
|
|
It allows Lua to identify the platform on which it runs.
|
2008-07-29 11:08:54 +00:00
|
|
|
|
2008-08-03 13:56:22 +00:00
|
|
|
Platform = pd.platform(): returns the platform name (f.e. LM3S)
|
2008-08-02 22:04:39 +00:00
|
|
|
|
|
|
|
Cpu = pd.cpu(): returns the CPU name (f.e. LM3S8962)
|
2008-07-29 11:08:54 +00:00
|
|
|
|
2008-09-02 10:55:35 +00:00
|
|
|
Board = pd.board(): returns the CPU board (f.e. EK-LM3S8962)
|
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The PWM module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
It allows Lua to use the PWM blocks on the target CPU.
|
|
|
|
|
|
|
|
Data = pwm.setup( id, frequency, duty ): sets the PWM block 'id' to generate the
|
|
|
|
specified frequency with the specified duty cycle (duty is an integer number
|
|
|
|
from 0 to 100, specifying the duty cycle in percents). It returns the actual
|
|
|
|
frequency set on the PWM block.
|
|
|
|
|
|
|
|
pwm.start( id ): start the PWM block 'id'.
|
|
|
|
|
|
|
|
pwm.stop( id ): stop the PWM block 'id'.
|
|
|
|
|
|
|
|
Data = pwm.setclock( id, clock ): set the base clock of the PWM block 'id' to
|
|
|
|
the given clock. In returns the actual clock set on the PWM block.
|
|
|
|
|
|
|
|
Data = pwm.getclock( id ): returns the base clock of the PWM block 'id'.
|
2008-10-31 21:32:15 +00:00
|
|
|
|
|
|
|
================================================================================
|
|
|
|
=== The CPU module
|
|
|
|
================================================================================
|
|
|
|
|
|
|
|
It brings low level CPU access to Lua (read/write memory, enable/disable
|
|
|
|
interrupts).
|
|
|
|
|
|
|
|
w32( address, data ) : write the 32-bit data at the specified address
|
|
|
|
|
|
|
|
w16( address, data ) : write the 16-bit data at the specified address
|
|
|
|
|
|
|
|
w8( address, data ) : write the 8-bit data at the specified address
|
|
|
|
|
|
|
|
Data = r32( address ) : reads 32-bit data from the specified address
|
|
|
|
|
|
|
|
Data = r16( address ) : reads 16-bit data from the specified address
|
|
|
|
|
|
|
|
Data = r8( address ) : reads 8-bit data from the specified address
|
|
|
|
|
|
|
|
cli(): disable CPU interrupts
|
|
|
|
|
|
|
|
sei(): enable CPU interrupts
|
|
|
|
|
|
|
|
Clock = clock(): returns the CPU frequency
|
|
|
|
|
|
|
|
Also, you can expose as many CPU constants (for example memory mapped registers)
|
|
|
|
as you want to this module. You might want to use this feature to access some
|
|
|
|
CPU memory areas (as defined in the CPU header files from the CPU support
|
|
|
|
package) directly from Lua. To do this, you'll need to define the
|
|
|
|
PLATFORM_CPU_CONSTANTS macro in the platform's platform_conf.h file
|
|
|
|
(src/platform/<platform name>/platform_conf.h). Include all your constants in a
|
|
|
|
_C( <constant name> ) definition, and then build your project.
|
|
|
|
For example, let's suppose that your CPU's interrupt controler has 3 memory
|
|
|
|
mapped registers: INT_REG_ENABLE, INT_REG_DISABLE and INT_REG_MASK. If you want
|
|
|
|
to access them from Lua, locate the header that defines the values of these
|
|
|
|
registers (I'll assume its name is "cpu.h") and add these lines to the
|
|
|
|
platform_conf.h:
|
|
|
|
|
|
|
|
#include "cpu.h"
|
|
|
|
|
|
|
|
#define PLATFORM_CPU_CONSTANTS\
|
|
|
|
_C( INT_REG_ENABLE ),\
|
|
|
|
_C( INT_REG_DISABLE ),\
|
|
|
|
_C( INT_REG_MASK )
|
|
|
|
|
|
|
|
After this you'll be able to access the regs directly from Lua, like this:
|
|
|
|
|
|
|
|
data = cpu.r32( cpu.INT_REG_ENABLE )
|
|
|
|
cpu.w32( cpu.INT_REG_ENABLE, data )
|
|
|
|
|
|
|
|
For a "real-life" example, see the src/platform/lm3s/platform_conf.h file.
|