mirror of
https://github.com/elua/elua.git
synced 2025-01-25 01:02:54 +08:00
Merge branch 'master' into newsite
- resolve conflicts arising from merge
This commit is contained in:
commit
bd116fae17
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,4 +15,6 @@ mux*
|
||||
rfs_server*
|
||||
doc/dist
|
||||
doc/cache
|
||||
|
||||
*~
|
||||
*.*~
|
||||
luac.cross*
|
||||
|
@ -1,3 +1,10 @@
|
||||
xx.yy.zzzz Bogdan Marinescu <bogdan.marinescu@gmail.com>
|
||||
Dado Sutter <dadosutter@gmail.com>
|
||||
James Snyder <jbsnyder@gmail.com>
|
||||
|
||||
* Official release 0.9
|
||||
* New feature: system timer ([TODO] add link)
|
||||
|
||||
02.02.2011 Bogdan Marinescu <bogdan.marinescu@gmail.com>
|
||||
Dado Sutter <dadosutter@gmail.com>
|
||||
James Snyder <jbsnyder@gmail.com>
|
||||
|
116
SConstruct
116
SConstruct
@ -1,5 +1,6 @@
|
||||
import os, sys, shutil, string
|
||||
import platform as syspl
|
||||
import platform as syspl
|
||||
import glob
|
||||
|
||||
# Helper: "normalize" a name to make it a suitable C macro name
|
||||
def cnorm( name ):
|
||||
@ -79,14 +80,14 @@ toolchain_list['devkitarm'] = toolchain_list['arm-eabi-gcc']
|
||||
# (the one that will be used if none is specified)
|
||||
platform_list = {
|
||||
'at91sam7x' : { 'cpus' : [ 'AT91SAM7X256', 'AT91SAM7X512' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'lm3s' : { 'cpus' : [ 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'lm3s' : { 'cpus' : [ 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92', 'LM3S9D92' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'str9' : { 'cpus' : [ 'STR912FAW44' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'i386' : { 'cpus' : [ 'I386' ], 'toolchains' : [ 'i686-gcc' ] },
|
||||
'sim' : { 'cpus' : [ 'LINUX' ], 'toolchains' : [ 'i686-gcc' ] },
|
||||
'lpc288x' : { 'cpus' : [ 'LPC2888' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'str7' : { 'cpus' : [ 'STR711FR2' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'stm32' : { 'cpus' : [ 'STM32F103ZE', 'STM32F103RE' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'avr32' : { 'cpus' : [ 'AT32UC3A0512', 'AT32UC3A0128', 'AT32UC3B0256' ], 'toolchains' : [ 'avr32-gcc', 'avr32-unknown-none-gcc' ] },
|
||||
'avr32' : { 'cpus' : [ 'AT32UC3A0512', 'AT32UC3A0256', 'AT32UC3A0128', 'AT32UC3B0256' ], 'toolchains' : [ 'avr32-gcc', 'avr32-unknown-none-gcc' ] },
|
||||
'lpc24xx' : { 'cpus' : [ 'LPC2468' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] },
|
||||
'lpc17xx' : { 'cpus' : [ 'LPC1768' ], 'toolchains' : [ 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' ] }
|
||||
}
|
||||
@ -97,6 +98,7 @@ board_list = { 'SAM7-EX256' : [ 'AT91SAM7X256', 'AT91SAM7X512' ],
|
||||
'EK-LM3S8962' : [ 'LM3S8962' ],
|
||||
'EK-LM3S6965' : [ 'LM3S6965' ],
|
||||
'EK-LM3S9B92' : [ 'LM3S9B92' ],
|
||||
'SOLDERCORE' : [ 'LM3S9D92' ],
|
||||
'STR9-COMSTICK' : [ 'STR912FAW44' ],
|
||||
'STR-E912' : [ 'STR912FAW44' ],
|
||||
'PC' : [ 'I386' ],
|
||||
@ -110,95 +112,12 @@ board_list = { 'SAM7-EX256' : [ 'AT91SAM7X256', 'AT91SAM7X512' ],
|
||||
'EAGLE-100' : [ 'LM3S6918' ],
|
||||
'ELUA-PUC' : ['LPC2468' ],
|
||||
'MBED' : ['LPC1768'],
|
||||
'MIZAR32' : [ 'AT32UC3A0128' ],
|
||||
'MIZAR32' : [ 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', ],
|
||||
'NETDUINO' : [ 'AT91SAM7X512' ],
|
||||
}
|
||||
|
||||
cpu_list = sum([board_list[i] for i in board_list],[])
|
||||
|
||||
|
||||
# ROMFS file list "groups"
|
||||
# To include a file in a ROMFS build, include it in a group here (or create one
|
||||
# if you need) and make sure the group is included on your platform's file_list
|
||||
# definition (right after this).
|
||||
|
||||
# The following table will be left here just as an example
|
||||
# eLua examples were removed from the distro since v0.8
|
||||
#romfs = { 'bisect' : [ 'bisect.lua' ],
|
||||
# 'hangman' : [ 'hangman.lua' ],
|
||||
# 'lhttpd' : [ 'index.pht', 'lhttpd.lua', 'test.lua' ],
|
||||
# 'led' : [ 'led.lua' ],
|
||||
# 'piano' : [ 'piano.lua' ],
|
||||
# 'pwmled' : [ 'pwmled.lua' ],
|
||||
# 'tvbgone' : [ 'tvbgone.lua', 'codes.bin' ],
|
||||
# 'hello' : [ 'hello.lua' ],
|
||||
# 'info' : [ 'info.lua' ],
|
||||
# 'morse' : [ 'morse.lua' ],
|
||||
# 'dualpwm' : [ 'dualpwm.lua' ],
|
||||
# 'adcscope' : [ 'adcscope.lua' ],
|
||||
# 'adcpoll' : [ 'adcpoll.lua' ],
|
||||
# 'life' : [ 'life.lua' ],
|
||||
# 'logo' : ['logo.lua', 'logo.bin' ],
|
||||
# 'pong' : [ 'pong.lua' ],
|
||||
# 'spaceship' : [ 'spaceship.lua' ],
|
||||
# 'tetrives' : [ 'tetrives.lua' ],
|
||||
# 'snake' : [ 'snake.lua' ],
|
||||
# 'dataflash' : [ 'dataflash.lua' ],
|
||||
# 'pachube' : [ 'pachube_demo.lua' ],
|
||||
# 'inttest' : [ 'inttest.lua' ]
|
||||
# }
|
||||
|
||||
romfs = {
|
||||
}
|
||||
|
||||
# List of board/romfs data combinations
|
||||
# The following table will be left here just as an example
|
||||
# eLua examples were removed from the distro since v0.8
|
||||
#file_list = { 'SAM7-EX256' : [ 'bisect', 'hangman' , 'led', 'piano', 'hello', 'info', 'morse' ],
|
||||
# 'EK-LM3S1968' : [ 'bisect', 'hangman', 'pong', 'led', 'piano', 'pwmled', 'hello', 'info', 'morse', 'adcscope', 'adcpoll', 'logo', 'spaceship', 'tetrives', 'snake' ],
|
||||
# 'EK-LM3S8962' : [ 'lhttpd','bisect', 'led', 'pachube' ],
|
||||
# 'EK-LM3S6965' : [ 'bisect', 'hangman', 'pong', 'led', 'piano', 'pwmled', 'hello', 'info', 'morse', 'adcscope', 'adcpoll', 'logo', 'tetrives' ],
|
||||
# 'EK-LM3S9B92' : [ 'bisect', 'hangman', 'led', 'pwmled', 'hello', 'info', 'adcscope','adcpoll', 'life' ],
|
||||
# 'STR9-COMSTICK' : [ 'bisect', 'hangman', 'led', 'hello', 'info' ],
|
||||
# 'STR-E912' : [ 'bisect', 'hangman', 'led', 'hello', 'info', 'piano', 'adcscope' ],
|
||||
# 'PC' : [ 'bisect', 'hello', 'info', 'life', 'hangman' ],
|
||||
# 'SIM' : [ 'bisect', 'hello', 'info', 'life', 'hangman' ],
|
||||
# 'LPC-H2888' : [ 'bisect', 'hangman', 'led', 'hello', 'info' ],
|
||||
# 'MOD711' : [ 'bisect', 'hangman', 'led', 'hello', 'info', 'dualpwm' ],
|
||||
# 'STM3210E-EVAL' : [ 'bisect', 'hello', 'info' ],
|
||||
# 'ATEVK1100' : [ 'bisect', 'hangman', 'led', 'hello', 'info', 'dataflash' ],
|
||||
# 'ATEVK1101' : [ 'bisect', 'led', 'hello', 'info', 'dataflash' ],
|
||||
# 'ET-STM32' : [ 't' ],
|
||||
# 'EAGLE-100' : [ 'bisect', 'hangman', 'lhttpd', 'led', 'hello', 'info' ],
|
||||
# 'ELUA-PUC' : [ 'bisect', 'hangman', 'led', 'hello', 'info', 'pwmled', 'adcscope', 'adcpoll', 'inttest' ],
|
||||
# 'MBED' : [ 'bisect', 'hangman', 'hello', 'info', 'led', 'pwmled', 'dualpwm', 'life', 'adcscope', 'adcpoll' ],
|
||||
# 'MIZAR32' : [ ],
|
||||
# 'NETDUINO': [ ],
|
||||
#}
|
||||
|
||||
file_list = { 'SAM7-EX256' : [ ],
|
||||
'EK-LM3S1968' : [ ],
|
||||
'EK-LM3S8962' : [ ],
|
||||
'EK-LM3S6965' : [ ],
|
||||
'EK-LM3S9B92' : [ ],
|
||||
'STR9-COMSTICK' : [ ],
|
||||
'STR-E912' : [ ],
|
||||
'PC' : [ ],
|
||||
'SIM' : [ ],
|
||||
'LPC-H2888' : [ ],
|
||||
'MOD711' : [ ],
|
||||
'STM3210E-EVAL' : [ ],
|
||||
'ATEVK1100' : [ ],
|
||||
'ATEVK1101' : [ ],
|
||||
'ET-STM32' : [ ],
|
||||
'EAGLE-100' : [ ],
|
||||
'ELUA-PUC' : [ ],
|
||||
'MBED' : [ ],
|
||||
'MIZAR32' : [ ],
|
||||
'NETDUINO': [ ],
|
||||
}
|
||||
|
||||
|
||||
comp = Environment( tools = [],
|
||||
OBJSUFFIX = ".o",
|
||||
PROGSUFFIX = ".elf",
|
||||
@ -243,9 +162,9 @@ vars.AddVariables(
|
||||
'none',
|
||||
allowed_values = [ 'none', 'emblod' ] ),
|
||||
MatchEnumVariable('target',
|
||||
'build "regular" float lua or integer-only "lualong"',
|
||||
'build "regular" float lua, 32 bit integer-only "lualong" or 64-bit integer-only "lualonglong"',
|
||||
'lua',
|
||||
allowed_values = [ 'lua', 'lualong' ] ),
|
||||
allowed_values = [ 'lua', 'lualong', 'lualonglong' ] ),
|
||||
MatchEnumVariable('cpu',
|
||||
'build for the specified CPU (board will be inferred, if possible)',
|
||||
'auto',
|
||||
@ -358,6 +277,9 @@ if not GetOption( 'help' ):
|
||||
# Build the compilation command now
|
||||
compcmd = ''
|
||||
if comp['romfs'] == 'compile':
|
||||
if comp['target'] == 'lualonglong':
|
||||
print "Cross-compilation is not yet supported in 64-bit mode"
|
||||
Exit( -1 )
|
||||
if syspl.system() == 'Windows':
|
||||
suffix = '.exe'
|
||||
else:
|
||||
@ -417,8 +339,10 @@ if not GetOption( 'help' ):
|
||||
lua_full_files = " " + " ".join( [ "src/lua/%s" % name for name in lua_files.split() ] )
|
||||
|
||||
comp.Append(CPPPATH = ['inc', 'inc/newlib', 'inc/remotefs', 'src/platform', 'src/lua'])
|
||||
if comp['target'] == 'lualong':
|
||||
if comp['target'] == 'lualong' or comp['target'] == 'lualonglong':
|
||||
conf.env.Append(CPPDEFINES = ['LUA_NUMBER_INTEGRAL'])
|
||||
if comp['target'] == 'lualonglong':
|
||||
conf.env.Append(CPPDEFINES = ['LUA_INTEGRAL_LONGLONG'])
|
||||
|
||||
conf.env.Append(CPPPATH = ['src/modules', 'src/platform/%s' % platform])
|
||||
conf.env.Append(CPPDEFINES = {"LUA_OPTIMIZE_MEMORY" : ( comp['optram'] != 0 and 2 or 0 ) } )
|
||||
@ -466,15 +390,19 @@ if not GetOption( 'help' ):
|
||||
|
||||
comp = conf.Finish()
|
||||
|
||||
romfs_exclude = [ '.DS_Store' ]
|
||||
|
||||
# Make ROM File System first
|
||||
if not GetOption( 'clean' ):
|
||||
print "Building ROM File System..."
|
||||
romdir = "romfs"
|
||||
flist = []
|
||||
for sample in file_list[ comp['board'] ]:
|
||||
flist += romfs[ sample ]
|
||||
os.chdir( "romfs" );
|
||||
for sample in glob.glob("*"):
|
||||
if sample not in romfs_exclude:
|
||||
flist += [ sample ]
|
||||
os.chdir( ".." )
|
||||
import mkfs
|
||||
mkfs.mkfs( romdir, "romfiles", flist, comp['romfs'], compcmd )
|
||||
mkfs.mkfs( "romfs", "romfiles", flist, comp['romfs'], compcmd )
|
||||
print
|
||||
if os.path.exists( "inc/romfiles.h" ):
|
||||
os.remove( "inc/romfiles.h" )
|
||||
|
129
build_elua.lua
129
build_elua.lua
@ -157,14 +157,14 @@ toolchain_list[ 'devkitarm' ] = toolchain_list[ 'arm-eabi-gcc' ]
|
||||
local platform_list =
|
||||
{
|
||||
at91sam7x = { cpus = { 'AT91SAM7X256', 'AT91SAM7X512' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
lm3s = { cpus = { 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
lm3s = { cpus = { 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92', 'LM3S9D92' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
str9 = { cpus = { 'STR912FAW44' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
i386 = { cpus = { 'I386' }, toolchains = { 'i686-gcc' } },
|
||||
sim = { cpus = { 'LINUX' }, toolchains = { 'i686-gcc' } },
|
||||
lpc288x = { cpus = { 'LPC2888' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
str7 = { cpus = { 'STR711FR2' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
avr32 = { cpus = { 'AT32UC3A0512', 'AT32UC3A0128', 'AT32UC3B0256' }, toolchains = { 'avr32-gcc', 'avr32-unknown-none-gcc' } },
|
||||
avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, toolchains = { 'avr32-gcc', 'avr32-unknown-none-gcc' } },
|
||||
lpc24xx = { cpus = { 'LPC2468' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } },
|
||||
lpc17xx = { cpus = { 'LPC1768' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' } }
|
||||
}
|
||||
@ -177,6 +177,7 @@ local board_list =
|
||||
[ 'EK-LM3S8962' ] = { 'LM3S8962' },
|
||||
[ 'EK-LM3S6965' ] = { 'LM3S6965' },
|
||||
[ 'EK-LM3S9B92' ] = { 'LM3S9B92' },
|
||||
[ 'SOLDERCORE' ] = { 'LM3S9D92' },
|
||||
[ 'STR9-COMSTICK' ] = { 'STR912FAW44' },
|
||||
[ 'STR-E912' ] = { 'STR912FAW44' },
|
||||
[ 'PC' ] = { 'I386' },
|
||||
@ -190,7 +191,7 @@ local board_list =
|
||||
[ 'EAGLE-100' ] = { 'LM3S6918' },
|
||||
[ 'ELUA-PUC' ] = { 'LPC2468' },
|
||||
[ 'MBED' ] = { 'LPC1768' },
|
||||
[ 'MIZAR32' ] = { 'AT32UC3A0128' },
|
||||
[ 'MIZAR32' ] = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512' },
|
||||
[ 'NETDUINO' ] = { 'AT91SAM7X512' },
|
||||
}
|
||||
|
||||
@ -205,97 +206,7 @@ for k, v in pairs( board_list ) do
|
||||
end
|
||||
end
|
||||
|
||||
-- ROMFS file list "groups"
|
||||
-- To include a file in a ROMFS build, include it in a group here (or create one
|
||||
-- if you need) and make sure the group is included on your platform's file_list
|
||||
-- definition (right after this).
|
||||
|
||||
-- The following table will be left here just as an example
|
||||
-- eLua examples were removed from the distro since v0.8
|
||||
--[[
|
||||
local romfs =
|
||||
{
|
||||
bisect = { 'bisect.lua' },
|
||||
hangman = { 'hangman.lua' },
|
||||
lhttpd = { 'index.pht', 'lhttpd.lua', 'test.lua' },
|
||||
led = { 'led.lua' },
|
||||
piano = { 'piano.lua' },
|
||||
pwmled = { 'pwmled.lua' },
|
||||
tvbgone = { 'tvbgone.lua', 'codes.bin' },
|
||||
hello = { 'hello.lua' },
|
||||
info = { 'info.lua' },
|
||||
morse = { 'morse.lua' },
|
||||
dualpwm = { 'dualpwm.lua' },
|
||||
adcscope = { 'adcscope.lua' },
|
||||
adcpoll = { 'adcpoll.lua' },
|
||||
life = { 'life.lua' },
|
||||
logo = {'logo.lua', 'logo.bin' },
|
||||
pong = { 'pong.lua' },
|
||||
spaceship = { 'spaceship.lua' },
|
||||
tetrives = { 'tetrives.lua' },
|
||||
snake = { 'snake.lua' },
|
||||
dataflash = { 'dataflash.lua' },
|
||||
pachube = { 'pachube_demo.lua' },
|
||||
inttest = { 'inttest.lua' }
|
||||
}
|
||||
--]]
|
||||
|
||||
local romfs = {}
|
||||
|
||||
-- List of board/romfs data combinations
|
||||
-- The following table will be left here just as an example
|
||||
-- eLua examples were removed from the distro since v0.8
|
||||
--[[
|
||||
local file_list =
|
||||
{
|
||||
[ 'SAM7-EX256' ] = { 'bisect', 'hangman' , 'led', 'piano', 'hello', 'info', 'morse' },
|
||||
[ 'EK-LM3S1968' ] = { 'bisect', 'hangman', 'pong', 'led', 'piano', 'pwmled', 'hello', 'info', 'morse', 'adcscope', 'adcpoll', 'logo', 'spaceship', 'tetrives', 'snake' },
|
||||
[ 'EK-LM3S8962' ] = { 'lhttpd','bisect', 'led', 'pachube' },
|
||||
[ 'EK-LM3S6965' ] = { 'bisect', 'hangman', 'pong', 'led', 'piano', 'pwmled', 'hello', 'info', 'morse', 'adcscope', 'adcpoll', 'logo', 'tetrives' },
|
||||
[ 'EK-LM3S9B92' ] = { 'bisect', 'hangman', 'led', 'pwmled', 'hello', 'info', 'adcscope','adcpoll', 'life' },
|
||||
[ 'STR9-COMSTICK' ] = { 'bisect', 'hangman', 'led', 'hello', 'info' },
|
||||
[ 'STR-E912' ] = { 'bisect', 'hangman', 'led', 'hello', 'info', 'piano', 'adcscope' },
|
||||
[ 'PC' ] = { 'bisect', 'hello', 'info', 'life', 'hangman' },
|
||||
[ 'SIM' ] = { 'bisect', 'hello', 'info', 'life', 'hangman' },
|
||||
[ 'LPC-H2888' ] = { 'bisect', 'hangman', 'led', 'hello', 'info' },
|
||||
[ 'MOD711' ] = { 'bisect', 'hangman', 'led', 'hello', 'info', 'dualpwm' },
|
||||
[ 'STM3210E-EVAL' ] = { 'bisect', 'hello', 'info' },
|
||||
[ 'ATEVK1100' ] = { 'bisect', 'hangman', 'led', 'hello', 'info', 'dataflash' },
|
||||
[ 'ATEVK1101' ] = { 'bisect', 'led', 'hello', 'info', 'dataflash' },
|
||||
[ 'ET-STM32' ] = { 't' },
|
||||
[ 'EAGLE-100' ] = { 'bisect', 'hangman', 'lhttpd', 'led', 'hello', 'info' },
|
||||
[ 'ELUA-PUC' ] = { 'bisect', 'hangman', 'led', 'hello', 'info', 'pwmled', 'adcscope', 'adcpoll', 'inttest' },
|
||||
[ 'MBED' ] = { 'bisect', 'hangman', 'hello', 'info', 'led', 'pwmled', 'dualpwm', 'life', 'adcscope', 'adcpoll' },
|
||||
[ 'MIZAR32' ] = { },
|
||||
[ 'NETDUINO' ] = { },
|
||||
}
|
||||
--]]
|
||||
|
||||
local file_list =
|
||||
{
|
||||
[ 'SAM7-EX256' ] = {},
|
||||
[ 'EK-LM3S1968' ] = {},
|
||||
[ 'EK-LM3S8962' ] = {},
|
||||
[ 'EK-LM3S6965' ] = {},
|
||||
[ 'EK-LM3S9B92' ] = {},
|
||||
[ 'STR9-COMSTICK' ] = {},
|
||||
[ 'STR-E912' ] = {},
|
||||
[ 'PC' ] = {},
|
||||
[ 'SIM' ] = {},
|
||||
[ 'LPC-H2888' ] = {},
|
||||
[ 'MOD711' ] = {},
|
||||
[ 'STM3210E-EVAL' ] = {},
|
||||
[ 'ATEVK1100' ] = {},
|
||||
[ 'ATEVK1101' ] = {},
|
||||
[ 'ET-STM32' ] = {},
|
||||
[ 'EAGLE-100' ] = {},
|
||||
[ 'ELUA-PUC' ] = {},
|
||||
[ 'MBED' ] = {},
|
||||
[ 'MIZAR32' ] = {},
|
||||
[ 'NETDUINO'] = {},
|
||||
}
|
||||
|
||||
builder:add_option( 'target', 'build "regular" float lua or integer-only "lualong"', 'lua', { 'lua', 'lualong' } )
|
||||
builder:add_option( 'target', 'build "regular" float lua, 32 bit integer-only "lualong" or 64-bit integer only lua "lualonglong"', 'lua', { 'lua', 'lualong', 'lualonglong' } )
|
||||
builder:add_option( 'cpu', 'build for the specified CPU (board will be inferred, if possible)', 'auto', { cpu_list, 'auto' } )
|
||||
builder:add_option( 'allocator', 'select memory allocator', 'auto', { 'newlib', 'multiple', 'simple', 'auto' } )
|
||||
builder:add_option( 'board', 'selects board for target (cpu will be inferred)', 'auto', { utils.table_keys( board_list ), 'auto' } )
|
||||
@ -399,6 +310,10 @@ end
|
||||
-- Build the compilation command now
|
||||
local fscompcmd = ''
|
||||
if comp.romfs == 'compile' then
|
||||
if comp.target == 'lualonglong' then
|
||||
print "Cross-compilation is not yet supported for 64-bit integer only Lua (lualonglong)."
|
||||
os.exit( -1 )
|
||||
end
|
||||
local suffix = ''
|
||||
if utils.is_windows() then
|
||||
suffix = '.exe'
|
||||
@ -451,13 +366,14 @@ elseif comp.allocator == 'simple' then
|
||||
addm( "USE_SIMPLE_ALLOCATOR" )
|
||||
end
|
||||
if comp.boot == 'luarpc' then addm( "ELUA_BOOT_RPC" ) end
|
||||
if comp.target == 'lualong' then addm( "LUA_NUMBER_INTEGRAL" ) end
|
||||
if comp.target == 'lualong' or comp.target == 'lualonglong' then addm( "LUA_NUMBER_INTEGRAL" ) end
|
||||
if comp.target == 'lualonglong' then addm( "LUA_INTEGRAL_LONGLONG" ) end
|
||||
|
||||
-- Special macro definitions for the SYM target
|
||||
if platform == 'sim' then addm( { "ELUA_SIMULATOR", "ELUA_SIM_" .. cnorm( comp.cpu ) } ) end
|
||||
|
||||
-- Lua source files and include path
|
||||
exclude_patterns = { "^src/platform", "^src/uip", "^src/serial", "^src/luarpc_desktop_serial.c", "^src/lua/print.c", "^src/lua/luac.c" }
|
||||
exclude_patterns = { "^src/platform", "^src/uip", "^src/serial", "^src/luarpc_desktop_serial.c", "^src/linenoise_posix.c", "^src/lua/print.c", "^src/lua/luac.c" }
|
||||
local source_files = utils.get_files( "src", function( fname )
|
||||
fname = fname:gsub( "\\", "/" )
|
||||
local include = fname:find( ".*%.c$" )
|
||||
@ -487,15 +403,25 @@ source_files = source_files .. uip_files .. specific_files
|
||||
-- Create compiler/linker/assembler command lines and build
|
||||
|
||||
-- ROM file system builder
|
||||
|
||||
romfs_exclude_patterns = { '%.DS_Store', '%.gitignore' }
|
||||
|
||||
function match_pattern_list( item, list )
|
||||
for k, v in pairs( list ) do
|
||||
if item:find(v) then return true end
|
||||
end
|
||||
end
|
||||
|
||||
local function make_romfs()
|
||||
print "Building ROM file system ..."
|
||||
local romdir = "romfs"
|
||||
local flist = {}
|
||||
for _, sample in pairs( file_list[ comp.board:upper() ] ) do
|
||||
table.insert( flist, romfs[ sample ] )
|
||||
end
|
||||
flist = utils.string_to_table( utils.get_files( 'romfs', function( fname ) return not match_pattern_list( fname, romfs_exclude_patterns ) end ) )
|
||||
flist = utils.linearize_array( flist )
|
||||
if not mkfs.mkfs( romdir, "romfiles", flist, comp.romfs, fscompcmd ) then return -1 end
|
||||
for k, v in pairs( flist ) do
|
||||
flist[ k ] = v:gsub( "romfs" .. utils.dir_sep, "" )
|
||||
end
|
||||
|
||||
if not mkfs.mkfs( "romfs", "romfiles", flist, comp.romfs, fscompcmd ) then return -1 end
|
||||
if utils.is_file( "inc/romfiles.h" ) then
|
||||
-- Read both the old and the new file
|
||||
local oldfile = io.open( "inc/romfiles.h", "rb" )
|
||||
@ -546,7 +472,6 @@ builder:set_exe_extension( ".elf" )
|
||||
-- Create the ROM file system
|
||||
make_romfs()
|
||||
-- Creaate executable targets
|
||||
builder:make_depends( source_files )
|
||||
odeps = builder:create_compile_targets( source_files )
|
||||
exetarget = builder:link_target( output, odeps )
|
||||
-- This is also the default target
|
||||
|
@ -72,6 +72,7 @@ local menu =
|
||||
{ "Status", "status.html",
|
||||
{
|
||||
{ { "Supported platforms", "Plataformas Suportadas" }, "status.html" },
|
||||
{ "System timer support", "status.html#systmr" },
|
||||
{ { "Modules per platform table", "Módulos por plataforma" }, "status.html#plat_modules" },
|
||||
{ { "Modules overview status", "Visão geral dos módulos" }, "status.html#gen_modules" },
|
||||
{ { "Roadmap", "Planejamento Futuro" }, "status.html#roadmap" }
|
||||
@ -225,9 +226,10 @@ local menu =
|
||||
-- "Platform modules" (automatically generated)
|
||||
{ { "Platform modules", "Módulos Específicos" }, "refman_dep.html",
|
||||
{
|
||||
{ "lm3s", "modules_lm3s.html", "refman_ps_lm3s" },
|
||||
{ "str9", "modules_str9.html", "refman_ps_str9" },
|
||||
{ "mbed", "modules_mbed.html", "refman_ps_mbed" }
|
||||
{ "lm3s", "modules_lm3s.html", "refman_ps_lm3s" },
|
||||
{ "str9", "modules_str9.html", "refman_ps_str9" },
|
||||
{ "mbed", "modules_mbed.html", "refman_ps_mbed" },
|
||||
{ "mizar32", "modules_mizar32.html", "refman_ps_mizar32" },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ local sf = string.format
|
||||
-- Data structure declarations
|
||||
|
||||
-- List here all the sections for which we're generating the documentation
|
||||
local doc_sections = { "arch_platform", "refman_gen", "refman_ps_lm3s", "refman_ps_str9", "refman_ps_mbed" }
|
||||
local doc_sections = { "arch_platform", "refman_gen", "refman_ps_lm3s", "refman_ps_str9", "refman_ps_mbed", "refman_ps_mizar32" }
|
||||
|
||||
-- List here all the components of each section
|
||||
local components =
|
||||
@ -17,8 +17,9 @@ local components =
|
||||
arch_platform = { "ll", "pio", "spi", "uart", "timers", "pwm", "cpu", "eth", "adc", "i2c", "can" },
|
||||
refman_gen = { "bit", "pd", "cpu", "pack", "adc", "term", "pio", "uart", "spi", "tmr", "pwm", "net", "can", "rpc", "elua", "i2c" },
|
||||
refman_ps_lm3s = { "disp" },
|
||||
refman_ps_str9 = { "pio", "rtc" },
|
||||
refman_ps_mbed = { "pio" }
|
||||
refman_ps_str9 = { "pio" },
|
||||
refman_ps_mbed = { "pio" },
|
||||
refman_ps_mizar32 = { "lcd" },
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
@ -23,32 +23,54 @@ data_en =
|
||||
ret = "1 if the ADC interface exists, 0 otherwise"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on an ADC channel",
|
||||
{ sig = "u32 #platform_adc_get_maxval#( unsigned id );",
|
||||
desc = "Gets the maximum conversion value the channel may supply (based on channel resolution)",
|
||||
args = "$id$ - ADC channel ID",
|
||||
ret = "the maximum possible conversion value"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_set_smoothing#( unsigned id, u32 length );",
|
||||
desc = "Sets the length of the moving average smoothing filter",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
[[$op$ - the operation that must be executed. It can take any value from @#adc_operations@this enum@, as follows:
|
||||
<ul>
|
||||
<li>$PLATFORM_ADC_GET_MAXVAL$: get the maximum conversion value the channel may supply (based on channel resolution)</li>
|
||||
<li>$PLATFORM_ADC_SET_SMOOTHING$: sets the length of the moving average smoothing filter to $data$ </li>
|
||||
<li>$PLATFORM_ADC_SET_BLOCKING$: sets whether or not sample requests should block, waiting for additional samples</li>
|
||||
<li>$PLATFORM_ADC_IS_DONE$: checks whether sampling has completed</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_TIMER$: selects a timer to control sampling frequency</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_CLOCK$: set the frequency of sample acquisition</li>
|
||||
</ul>]],
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_SET_SMOOTHING$, specifies the length of the moving average filter (must be a power of 2). If it is 1, filter is disabled.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_SET_BLOCKING$, specifies whether or not sample requests block. If 1, requests will block until enough samples are available or sampling has ended. If 0, requests will return immediately with up to the number of samples requested.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_OP_SET_TIMER$, specifies the timer to use to control sampling frequency.",
|
||||
"$data$ - when used with $op$ == $PLATFORM_ADC_OP_SET_CLOCK$, specifies the frequency of sample collection in Hz (number of samples per second). If 0, timer is not used and samples are acquired as quickly as possible."
|
||||
"$length$ - the length of the moving average filter (must be a power of 2). If it is 1, the filter is disabled.",
|
||||
},
|
||||
ret =
|
||||
ret = "$PLATFORM_OK$ if the operation succeeded, $PLATFORM_ERR$ otherwise."
|
||||
},
|
||||
|
||||
{ sig = "void #platform_adc_set_blocking#( unsigned id, u32 mode );",
|
||||
desc = "Sets whether or not sample requests should block, waiting for additional samples",
|
||||
args =
|
||||
{
|
||||
"the maximum possible conversion value when $op$ == $PLATFORM_ADC_GET_MAXVAL$",
|
||||
"whether or not sampling has completed (1: yes, 0: no) when $op$ == $PLATFORM_ADC_IS_DONE$. This will return 1 (yes), if no samples have been requested.",
|
||||
"the actual frequency of acquisition that will be used when $op$ == $PLATFORM_ADC_OP_SET_CLOCK$",
|
||||
"irellevant for other operations"
|
||||
}
|
||||
"$id$ - ADC channel ID",
|
||||
"$mode$ - specifies whether or not sample requests block. If 1, requests will block until enough samples are available or sampling has ended. If 0, requests will return immediately with up to the number of samples requested.",
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_is_done#( unsigned id );",
|
||||
desc = "Checks whether sampling has completed",
|
||||
args = "$id$ - ADC channel ID",
|
||||
ret = "1 if sampling has completed, 0 if not",
|
||||
},
|
||||
|
||||
{ sig = "void #platform_adc_set_timer#( unsigned id, u32 timer );",
|
||||
desc = "Selects a timer to control the sampling frequency",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
"$timer$ - the ID of the timer to use to control the sampling frequency.",
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_set_clock#( unsigned id, u32 freq );",
|
||||
desc = "Set the frequency of sample acquisition",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID",
|
||||
"$freq$ - the frequency of sample collection in Hz (number of samples per second). If 0, the timer is not used and samples are acquired as quickly as possible.",
|
||||
},
|
||||
ret = "the actual sampling frequency that will be used, which might be different from the requested frequency, depending on the hardware"
|
||||
},
|
||||
|
||||
{ sig = "int #platform_adc_check_timer_id#( unsigned id, unsigned timer_id );",
|
||||
@ -63,64 +85,4 @@ data_en =
|
||||
}
|
||||
}
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Menu name
|
||||
menu_name = "ADC",
|
||||
|
||||
-- Title
|
||||
title = "eLua API - ADC",
|
||||
|
||||
-- Overview
|
||||
overview = "Interfaceamento com as funcões do ADC da MCU.",
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_adc_exists#( unsigned id );",
|
||||
desc = [[Checa se a plataforma possui hardware para o Conversor AD especificado no argumento. Implementado em %src/common.c%, utiliza a macro $NUM_ADC$ que deve estar definida no arquivo $platform_conf.h$ da plataforma em questão. (veja @arch_overview.html#platforms@here@ para detalhes). Por exemplo:</p>
|
||||
~#define NUM_ADC 1 $// A Plataforma possui uma interface para ADC$~<p> ]],
|
||||
args = "$id$ - ADC ID",
|
||||
ret = "1 se a interface do ADC existir, 0 em caso contrário"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_adc_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on an ADC channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - ID do canal ADC",
|
||||
[[$op$ - A operação que deve ser executada. Valores possíveis em @#adc_operations@this enum@, conforme:
|
||||
<ul>
|
||||
<li>$PLATFORM_ADC_GET_MAXVAL$: Pega o maior valor de conversão que o canal pode fornecer, dependendo de sua resolução.</li>
|
||||
<li>$PLATFORM_ADC_SET_SMOOTHING$: Seta o tamanho do filtro atenuador de média móvel em $data$ </li>
|
||||
<li>$PLATFORM_ADC_SET_BLOCKING$: Seta se a amostragem deve aguardar novos valores (blocking)</li>
|
||||
<li>$PLATFORM_ADC_IS_DONE$: Checa se a amostragem foi completada</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_TIMER$: Seleciona um Timer para o controle da amostragem</li>
|
||||
<li>$PLATFORM_ADC_OP_SET_CLOCK$: Seta a frequência de amostragem</li>
|
||||
</ul>]],
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_SET_SMOOTHING$, especifica o tamanho do filtro de média móvel (deve ser potência de 2). O valor 1 desabilita o filtro.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_SET_BLOCKING$, especifica se a amostragem é blocking ou não. Se 1, os pedidos só retornam quando as amostras tiverem sido obtidas ou a amostragem encerrada. Se 0, os pedidos retornam imediatamente, com o número de amostras já obtidas.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_OP_SET_TIMER$, especifica o Timer a ser usado para o controle da frequência de amostragem.",
|
||||
"$data$ - quando usada com $op$ == $PLATFORM_ADC_OP_SET_CLOCK$, especifica a frequência de amostragem em Hz (número de amostras por segundo). Se 0, nenhum Timer é usado e a amostragem é feita o mais rapidamente possível."
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"O maior valor possível de ser obtido do conversor, quando $op$ == $PLATFORM_ADC_GET_MAXVAL$",
|
||||
"Flag informando se a conversão foi completada (1: sim, 0: não), quando $op$ == $PLATFORM_ADC_IS_DONE$. Também retorna 1 se nenhuma conversão foi solicitada.",
|
||||
"A frequência real de conversão que sera usada, quando $op$ == $PLATFORM_ADC_OP_SET_CLOCK$",
|
||||
"Indefinido para outras operações."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "int #platform_adc_check_timer_id#( unsigned id, unsigned timer_id );",
|
||||
desc = "Checa see um Timer pode ser usado com um ADC específico",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC ID",
|
||||
"$timer_id$ - Timer ID",
|
||||
},
|
||||
ret = "1 se o Timer pode ser usado para trigar um ADC. 0 em caso contrário",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -87,103 +87,11 @@ data_en =
|
||||
ret =
|
||||
{
|
||||
"0 if the uIP loop was called because of Ethernet activity, not because a timer expired",
|
||||
"the Ethernet timer perios in ms (which indicates timer activity)"
|
||||
"the Ethernet timer period in ms (which indicates timer activity)"
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Title
|
||||
title = "eLua platform interface - Ethernet support",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "Ethernet",
|
||||
|
||||
-- Overview
|
||||
overview = [[<span style="color: red;">$NOTE$: TCP/IP support is experimental in eLua. Although functional, it's quite incomplete at the moment.</span></p>
|
||||
<p>This part of the platform interface groups functions related to accessing the Ethernet interface (internal or external) of the CPU. Note that unlike the
|
||||
other parts of the platform interface this one is dedicated for TCP/IP support and thus it does not correspond directly to an eLua module, although
|
||||
the @refman_gen_net.html@net module@ is implemented with functions that rely on this part of the platform interface. Currently only
|
||||
the ^http://www.sics.se/~~adam/uip/index.php/Main_Page^uIP^ TCP/IP stack is supported by eLua.</p>
|
||||
<p>uIP is implemented in eLua using two hardware interrupts (that should be available on your platform): the Ethernet receive interrupt (to handle
|
||||
incoming packets) and a timer interrupt (timers are used internally by uIP). However, the uIP main loop is only called from the Ethernet interrupt handler
|
||||
in eLua, so in order to acknowledge the timer interrupt (as well as to provide some optimizations) a function that "forces" an Ethernet interrupt
|
||||
must also be provided by the platform interface (see @#platform_eth_force_interrupt@here@ for details).</p>
|
||||
<p>To put everything together, part of the Ethernet platform interface for the $lm3s$ platform is given below:</p>
|
||||
~u32 platform_eth_get_elapsed_time()
|
||||
{
|
||||
if( eth_timer_fired )
|
||||
{
|
||||
eth_timer_fired = 0;
|
||||
return SYSTICKMS;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SysTickIntHandler()
|
||||
{
|
||||
// Handle virtual timers
|
||||
cmn_virtual_timer_cb();
|
||||
|
||||
// Indicate that a SysTick interrupt has occurred.
|
||||
eth_timer_fired = 1;
|
||||
|
||||
// Generate a fake Ethernet interrupt. This will perform the actual work
|
||||
// of incrementing the timers and taking the appropriate actions.
|
||||
<b>platform_eth_force_interrupt();</b>
|
||||
}
|
||||
|
||||
void EthernetIntHandler()
|
||||
{
|
||||
u32 temp;
|
||||
|
||||
// Read and Clear the interrupt.
|
||||
temp = EthernetIntStatus( ETH_BASE, false );
|
||||
EthernetIntClear( ETH_BASE, temp );
|
||||
|
||||
// Call the UIP main loop
|
||||
<b>elua_uip_mainloop();</b>
|
||||
}~<p>]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "void #platform_eth_send_packet#( const void* src, u32 size )",
|
||||
desc = "Sends an Ethernet packet to the network",
|
||||
args =
|
||||
{
|
||||
"$src$ - start address of the Ethernet packet",
|
||||
"$size$ - size of the Ethernet packet"
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_eth_get_packet_nb#( void* buf, u32 maxlen );",
|
||||
desc = "Non-blocking read of an Ethernet packet from the network",
|
||||
args =
|
||||
{
|
||||
"$buf$ - start address of the receive buffer",
|
||||
"$maxlen$ - maximum length of the Ethernet packet",
|
||||
},
|
||||
ret = "the size of the read packet or 0 if no packet is available"
|
||||
},
|
||||
|
||||
{ sig = "void #platform_eth_force_interrupt#();",
|
||||
desc = "Force the Ethernet interrupt on the platform (see @#overview@overview@ above for details)",
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_eth_get_elapsed_time#();",
|
||||
desc = [[Get the elapsed time (in ms) since the last invocation of the uIP main loop ($elua_uip_mainloop$, from which this function is called). See @#overview@overview@ for a possible
|
||||
implementation of this function).]],
|
||||
ret =
|
||||
{
|
||||
"0 if the uIP loop was called because of Ethernet activity, not because a timer expired",
|
||||
"the Ethernet timer perios in ms (which indicates timer activity)"
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -32,90 +32,6 @@ enum
|
||||
},
|
||||
},
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_init#();",
|
||||
desc = [[This is the platform-specific initialization code. It is the first function called from %main()% ($src/main.c$) and it should handle
|
||||
all the platform initialization sequence, included (but not limited to) setting up the proper clocks, initializing the interrupt subsystem,
|
||||
setting up various peripherals and so on. Although platform specific, this function has a common part named %cmn_platform_init% (implemented
|
||||
in $src/common.c$) that initializes terminal support over serial connections, as well as the XMODEM and TERM components
|
||||
(see @building.html@here@ for details). If you need any of these, you need to call %cmn_platform_init% at the end of your
|
||||
%platform_init% function, $after$ initializing all the peripherals (in particular the UART used for the serial connection).<br>
|
||||
An implementation skeleton for this function is given below:</p>
|
||||
~int platform_init()
|
||||
{
|
||||
............. // perform all your initializations here
|
||||
cmn_platform_init(); // call the common initialiation code
|
||||
return PLATFORM_OK;
|
||||
}~<p>]],
|
||||
ret =
|
||||
{
|
||||
"$PLATFORM_OK$ for success",
|
||||
[[$PLATFORM_ERR$ if an error occured. If $PLATFORM_ERR$ is returned, %main% will block in an infinite loop right
|
||||
after calling this function, so you should return $PLATFORM_ERR$ only for serious errors]],
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "void* #platform_get_last_free_ram#( unsigned id );",
|
||||
desc = [[Returns the start address of a free RAM area in the system (this is the RAM that will be used by any part of the code that uses malloc(),
|
||||
a good example being the Lua interpreter itself). There can be multiple free RAM areas in the system (for example the internal MCU RAM and external
|
||||
RAM chips). Implemented in $src/common.c$, it uses the the $MEM_START_ADDRESS$ macro that must be defined in the platform's $platform_conf.h$
|
||||
file (see @arch_overview.html#platforms@here@ for details). This macro must be defined as an array that contains all the start addresses of
|
||||
free RAM in the system. For internal RAM, this is generally handled by a linker exported symbol (named $end$ in many eLua ports) which
|
||||
points to the first RAM address after all the constant and non-constant program data. An example is given below:</p>
|
||||
~#define MEM_START_ADDRESS { ( void* )end }~<p>]],
|
||||
args = "$id$ - the identifier of the RAM area",
|
||||
ret = "the start address of the given memory area",
|
||||
},
|
||||
|
||||
{ sig = "void* #platform_get_last_free_ram#( unsigned id );",
|
||||
desc = [[Returns the last address of a free RAM area in the system (this is the RAM that will be used by any part of the code that uses malloc(),
|
||||
a good example being the Lua interpreter itself). There can be multiple free RAM areas in the system (for example the internal MCU RAM and external
|
||||
RAM chips). Implemented in $src/common.c$, it uses the the $MEM_END_ADDRESS$ macro that must be defined in the platform's $platform_conf.h$
|
||||
file (see @arch_overview.html#platforms@here@ for details). This macro must be defined as an array that contains all the end addresses of
|
||||
free RAM in the system. For internal RAM, this is generally set as the last RAM memory address minus the size of the system stack(s). An example is
|
||||
given below:</p>
|
||||
~#define MEM_END_ADDRESS { ( void* )( SRAM_BASE + 0x10000 - STACK_SIZE_TOTAL - 1 ) }~<p>]],
|
||||
args = "$id$ - the identifier of the RAM area",
|
||||
ret = "the end address of the given memory area",
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Title
|
||||
title = "eLua platform interface - low level functions",
|
||||
|
||||
-- Menu title
|
||||
menu_name = "Low-level",
|
||||
|
||||
-- Overview
|
||||
overview = [[
|
||||
This part of the platform interface deals contains a small set of "low level functions" that are used to "couple" the eLua port with the
|
||||
target system. No eLua module exposes these functions, as they are strictly used for porting and do not provide any other functionality.
|
||||
]],
|
||||
|
||||
-- Data structures, constants and types
|
||||
structures =
|
||||
{
|
||||
{ text = [[// Error / status codes
|
||||
enum
|
||||
{
|
||||
PLATFORM_ERR,
|
||||
PLATFORM_OK,
|
||||
PLATFORM_UNDERFLOW = -1
|
||||
};]],
|
||||
name = "Status codes",
|
||||
desc = [[
|
||||
This enum defines the possible return values of the @#platform_init@platform_init@ function (although only $PLATFORM_ERR$ and $PLATFORM_OK$ should be
|
||||
returned from $platform_init$).
|
||||
]]
|
||||
},
|
||||
},
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
@ -147,7 +63,7 @@ enum
|
||||
RAM chips). Implemented in $src/common.c$, it uses the the $MEM_START_ADDRESS$ macro that must be defined in the platform's $platform_conf.h$
|
||||
file (see @arch_overview.html#platforms@here@ for details). This macro must be defined as an array that contains all the start addresses of
|
||||
free RAM in the system. For internal RAM, this is generally handled by a linker exported symbol (named $end$ in many eLua ports) which
|
||||
points to the firs RAM address after all the constant and non-constant program data. An example is given below:</p>
|
||||
points to the first RAM address after all the constant and non-constant program data. An example is given below:</p>
|
||||
~#define MEM_START_ADDRESS { ( void* )end }~<p>]],
|
||||
args = "$id$ - the identifier of the RAM area",
|
||||
ret = "the start address of the given memory area",
|
||||
@ -168,3 +84,4 @@ enum
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -99,115 +99,11 @@ data_en =
|
||||
{
|
||||
"an actual value for $PLATFORM_IO_PIN_GET$ (0 or 1) and $PLATFORM_IO_PORT_GET$ (the value of the port).",
|
||||
[[an error flag for all the other operations: 1 if the operation succeeded, 0 otherwise. For example, a platform that doesn't have pulldowns on its ports will always return a 0
|
||||
when caled with the $PLATFORM_IO_PIN_PULLDOWN$ operation.]]
|
||||
when called with the $PLATFORM_IO_PIN_PULLDOWN$ operation.]]
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Title
|
||||
title = "eLua platform interface - PIO",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "PIO",
|
||||
|
||||
-- OverviewA
|
||||
overview = "This part of the platform interface deals with PIO (Programmable Input Output) operations, thus letting the user access the low level input/output facilities of the host MCU.",
|
||||
|
||||
-- Data structures, constants and types
|
||||
structures =
|
||||
{
|
||||
{ text = [[enum
|
||||
{
|
||||
// Pin operations
|
||||
PLATFORM_IO_PIN_SET, $// Set the pin to 1$
|
||||
PLATFORM_IO_PIN_CLEAR, $// Clear the pin (set it to 0)$
|
||||
PLATFORM_IO_PIN_GET, $// Get the value of the pin$
|
||||
PLATFORM_IO_PIN_DIR_INPUT, $// Make the pin an input$
|
||||
PLATFORM_IO_PIN_DIR_OUTPUT, $// Make the pin an output$
|
||||
PLATFORM_IO_PIN_PULLUP, $// Activate the pullup on the pin$
|
||||
PLATFORM_IO_PIN_PULLDOWN, $// Activate the pulldown on the pin$
|
||||
PLATFORM_IO_PIN_NOPULL, $// Disable all pullups/pulldowns on the pin$
|
||||
// Port operations
|
||||
PLATFORM_IO_PORT_SET_VALUE, $// Set port value$
|
||||
PLATFORM_IO_PORT_GET_VALUE, $// Get port value$
|
||||
PLATFORM_IO_PORT_DIR_INPUT, $// Set port as input$
|
||||
PLATFORM_IO_PORT_DIR_OUTPUT $// Set port as output$
|
||||
}; ]],
|
||||
name = "PIO operations",
|
||||
desc = [[These are the operations that can be executed by the PIO subsystem on both ports and pins. They are given as arguments to the @#platform_pio_op@platform_pio_op@ function
|
||||
shown below.]]
|
||||
},
|
||||
|
||||
{ text = "typedef u32 pio_type;",
|
||||
name = "PIO data type",
|
||||
desc = [[This is the type used for the actual I/O operations. Currently defined as an unsigned 32-bit type, thus no port can have more than 32 pins. If this happens, it is possible to split
|
||||
it in two or more parts and adding the new parts as "virtual ports" (logical ports that don't have a direct hardware equivalent). The "virtual port" technique is used in the AVR32 backend.]]
|
||||
}
|
||||
},
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_pio_has_port#( unsigned port );",
|
||||
desc = [[Checks if the platform has the hardware port specified as argument. Implemented in %src/common.c%, it uses the $NUM_PIO$ macro that must be defined in the
|
||||
platform's $platform_conf.h$ file (see @arch_overview.html#platforms@here@ for details). For example:</p>
|
||||
~#define NUM_PIO 4 $// The platform has 4 hardware PIO ports$~<p> ]],
|
||||
args = "$port$ - the port ID",
|
||||
ret = "1 if the port exists, 0 otherwise",
|
||||
},
|
||||
|
||||
{ sig = "int #platform_pio_has_pin#( unsigned port, unsigned pin );",
|
||||
desc = [[Checks if the platform has the hardware port and pin specified as arguments. Implemented in %src/common.c%, it uses the $NUM_PIO$ macro to check the validity
|
||||
of the port and the $PIO_PINS_PER_PORT$ or $PIO_PIN_ARRAY$ macros to check the validity of the pin. The macros must be defined in the platform's $platform_conf.h$ file
|
||||
(see @arch_overview.html#platforms@here@ for details).</p>
|
||||
<ul>
|
||||
<li>use $PIO_PINS_PER_PORT$ when all the ports of the MCU have the same number of pins. For example:
|
||||
~#define PIO_PINS_PER_PORT 8 $// Each port has 8 pins$~</li>
|
||||
<li>use $PIO_PIN_ARRAY$ when different ports of the MCU have different number of pins. For example:
|
||||
~#define PIO_PIN_ARRAY { 4, 4, 2, 6 } $// Port 0 has 4 pins, port 1 has 4 pins, port 2 has 2 pins, port 3 has 6 pins$~</li>
|
||||
</ul><p>]],
|
||||
args =
|
||||
{
|
||||
"$port$ - the port ID",
|
||||
"$pin$ - the pin number"
|
||||
},
|
||||
ret = "1 if the pin exists, 0 otherwise",
|
||||
},
|
||||
|
||||
{ sig = "const char* #platform_pio_get_prefix#( unsigned port );",
|
||||
desc = [[Get the port prefix. Used to establish if the port notation uses numbers (P0, P1, P2...) or letters (PA, PB, PC...). Implemented in %src/common.c%, it uses the
|
||||
$PIO_PREFIX$ macro that must be defined in the platform's $platform_conf.h$ file (see @arch_overview.html#platforms@here@ for details). The value of this macro can be either '0' (for
|
||||
numeric notation) or 'A' (for letter notation). For example:</p>
|
||||
~#define PIO_PREFIX 'A' $// Use PA, PB, PC ... for port notation$~<p>]],
|
||||
args = "$port$ - the port ID",
|
||||
ret = "the port prefix (either '0' or 'A')",
|
||||
},
|
||||
|
||||
{ sig = "pio_type #platform_pio_op#( unsigned port, pio_type pinmask, int op );",
|
||||
link = "platform_pio_op",
|
||||
desc = "This is the function that does the actual I/O work. It is implemented in the platform's own porting layer (%platform.c%, see @arch_overview.html#ports@here@ for more details).",
|
||||
args =
|
||||
{
|
||||
"$port$ - the port number",
|
||||
[[$pinmask$ - has different meanings:
|
||||
<ul>
|
||||
<li>for $pin operations$ it is the mask of pins in the operation. Each pin on which the function action is executed is encoded with an 1 in the corresponding bit position
|
||||
of the pinmask.</li>
|
||||
<li>for $port operations$ it is only meaningful for $PLATFORM_IO_PORT_SET_VALUE$ and in this case it specifies the new value of the port.</li>
|
||||
</ul>]],
|
||||
"$op$ - specifies the I/O operations, as specified @#pio_operations@here@."
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"an actual value for $PLATFORM_IO_PIN_GET$ (0 or 1) and $PLATFORM_IO_PORT_GET$ (the value of the port).",
|
||||
[[an error flag for all the other operations: 1 if the operation succeeded, 0 otherwise. For example, a platform that doesn't have pulldowns on its ports will always return a 0
|
||||
when caled with the $PLATFORM_IO_PIN_PULLDOWN$ operation.]]
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -49,102 +49,45 @@ enum
|
||||
ret = "The actual frequency set on the PWM channel, which might differ from the $frequency$ parameter, depeding on the hardware",
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on a PWM channel",
|
||||
{ sig = "u32 #platform_pwm_start#( unsigned id );",
|
||||
desc = "Starts PWM generation on the specified channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
[[$op$ - the operation that must be executed. It can take any value from @#pwm_operations@this enum@, as follows:
|
||||
<ul>
|
||||
<li>$PLATFORM_PWM_OP_START$: starts PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_STOP$: stops PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_SET_CLOCK$: sets the $base$ clock of the specified PWM channel (which will be used to generate the frequencies requested by
|
||||
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.</li>
|
||||
<li>$PLATFORM_PWM_OP_GET_CLOCK$: get the $base$ clock of the specified PWM channel.</li>
|
||||
</ul>]],
|
||||
"$data$ - when used with $op$ == $PLATFORM_PWM_OP_SET_CLOCK$ it is used to specify the value of the base clock. Not used with other operations."
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"the actual value of the base clock when $op$ == $PLATFORM_PWM_OP_SET_CLOCK$, which might be different than $data$ depending on the hardware",
|
||||
"the value of the base clock when $op$ == $PLATFORM_PWM_OP_GET_CLOCK$",
|
||||
"irellevant for other operations"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Title
|
||||
title = "eLua platform interface - PWM",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "PWM",
|
||||
|
||||
-- Overview
|
||||
overview = "This part of the platform interface groups functions related to the PWM channel(s) of the MCU.",
|
||||
|
||||
-- Data structures, constants and types
|
||||
structures =
|
||||
{
|
||||
{ text = [[// PWM operations
|
||||
enum
|
||||
{
|
||||
PLATFORM_PWM_OP_START,
|
||||
PLATFORM_PWM_OP_STOP,
|
||||
PLATFORM_PWM_OP_SET_CLOCK,
|
||||
PLATFORM_PWM_OP_GET_CLOCK
|
||||
} ]],
|
||||
name = "PWM operations",
|
||||
desc = "This enum lists all the operations that can be executed on a given PWM channel."
|
||||
},
|
||||
},
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_pwm_exists#( unsigned id );",
|
||||
desc = [[Checks if the platform has the PWM channel specified as argument. Implemented in %src/common.c%, it uses the $NUM_PWM$ macro that must be defined in the
|
||||
platform's $platform_conf.h$ file (see @arch_overview.html#platforms@here@ for details). For example:</p>
|
||||
~#define NUM_PWM 4 $// The platform has 4 PWM channels$~<p> ]],
|
||||
args = "$id$ - PWM channel ID",
|
||||
ret = "1 if the specified PWM channel exists, 0 otherwise"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_setup#( unsigned id, u32 frequency, unsigned duty );",
|
||||
desc = "Sets up a PWM channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
"$frequency$ - PWM channel frequency (in hertz)",
|
||||
"$duty$ - PWM channel duty cycle, specified as percent (from 0 to 100). Note that some platform don't allow the full 0%-100% duty cycle"
|
||||
},
|
||||
ret = "The actual frequency set on the PWM channel, which might differ from the $frequency$ parameter, depeding on the hardware",
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_op#( unsigned id, int op, u32 data );",
|
||||
desc = "Executes an operation on a PWM channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
[[$op$ - the operation that must be executed. It can take any value from @#pwm_operations@this enum@, as follows:
|
||||
<ul>
|
||||
<li>$PLATFORM_PWM_OP_START$: starts PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_STOP$: stops PWM generation on the specified channel.</li>
|
||||
<li>$PLATFORM_PWM_OP_SET_CLOCK$: sets the $base$ clock of the specified PWM channel (which will be used to generate the frequencies requested by
|
||||
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.</li>
|
||||
<li>$PLATFORM_PWM_OP_GET_CLOCK$: get the $base$ clock of the specified PWM channel.</li>
|
||||
</ul>]],
|
||||
"$data$ - when used with $op$ == $PLATFORM_PWM_OP_SET_CLOCK$ it is used to specify the value of the base clock. Not used with other operations."
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"the actual value of the base clock when $op$ == $PLATFORM_PWM_OP_SET_CLOCK$, which might be different than $data$ depending on the hardware",
|
||||
"the value of the base clock when $op$ == $PLATFORM_PWM_OP_GET_CLOCK$",
|
||||
"irellevant for other operations"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_stop#( unsigned id );",
|
||||
desc = "Stops PWM generation on the specified channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_set_clock#( unsigned id, u32 clock );",
|
||||
desc = [[Sets the $base$ clock of the specified PWM channel
|
||||
(which will be used to generate the frequencies requested by
|
||||
@#platform_pwm_setup@platform_pwm_setup@) to $data$ hertz.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
"$clock$ - the desired frequency of the base clock."
|
||||
},
|
||||
ret = [[The actual value of the base clock, which might be different
|
||||
from $data$ depending on the hardware]],
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_pwm_get_clock#( unsigned id );",
|
||||
desc = "Gets the $base$ clock of the specified PWM channel",
|
||||
args =
|
||||
{
|
||||
"$id$ - PWM channel ID",
|
||||
"$clock$ - the desired frequency of the base clock."
|
||||
},
|
||||
ret = "the value of the base clock"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -82,84 +82,4 @@ data_en =
|
||||
}
|
||||
}
|
||||
|
||||
data_pt =
|
||||
{
|
||||
-- Menu name
|
||||
menu_name = "SPI",
|
||||
|
||||
-- Title
|
||||
title = "eLua platform interface - SPI",
|
||||
|
||||
-- Overview
|
||||
overview = "This part of the platform interface groups functions related to the SPI interface(s) of the MCU.",
|
||||
|
||||
-- Data structures, constants and types
|
||||
structures =
|
||||
{
|
||||
{ text = [[// SPI mode
|
||||
#define PLATFORM_SPI_MASTER 1
|
||||
#define PLATFORM_SPI_SLAVE 0 ]],
|
||||
name = "Chip select",
|
||||
desc = "Constants used to select/deselect the SPI SS pin (if applicable)."
|
||||
},
|
||||
|
||||
{ text = [[// SS values
|
||||
#define PLATFORM_SPI_SELECT_ON 1
|
||||
#define PLATFORM_SPI_SELECT_OFF 0]],
|
||||
name = "SPI mode",
|
||||
desc = "Constants used to select/deselect the SPI SS pin (if applicable)."
|
||||
},
|
||||
|
||||
{ text = "typedef u32 spi_data_type;",
|
||||
name = "SPI data type",
|
||||
desc = "This is the type of a SPI data word, thus limiting the maximum size of a SPI data work to 32 bits (which should be enough for all practical purposes)."
|
||||
}
|
||||
},
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "int #platform_spi_exists#( unsigned id );",
|
||||
desc = [[Checks if the platform has the hardware SPI specified as argument. Implemented in %src/common.c%, it uses the $NUM_SPI$ macro that must be defined in the
|
||||
platform's $platform_conf.h$ file (see @arch_overview.html#platforms@here@ for details). For example:</p>
|
||||
~#define NUM_SPI 1 $// The platform has 1 SPI interface$~<p> ]],
|
||||
args = "$id$ - SPI interface ID",
|
||||
ret = "1 if the SPI interface exists, 0 otherwise"
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_spi_setup#( unsigned id, int mode, u32 clock, unsigned cpol, unsigned cpha, unsigned databits );",
|
||||
desc = [[This function is used to initialize the parameters of the SPI interface. <span class="warning">NOTE</span>: currently, only master SPI mode is implemented in eLua.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - SPI interface ID",
|
||||
"$mode$ - SPI port mode ($PLATFORM_SPI_MASTER$ or $PLATFORM_SPI_SLAVE$, see @#spi_mode@here@.",
|
||||
"$clock$ - clock speed for the SPI interface in master mode.",
|
||||
"$cpol$ - SPI clock polarity",
|
||||
"$cpha$ - SPI clock phase",
|
||||
"$databits$ - length of the SPI data word in bits (usually 8, but configurable on some platforms)."
|
||||
},
|
||||
ret = "the actual clock set for the SPI interface. Depending on the hardware, this may have a different value than the $clock$ argument."
|
||||
},
|
||||
|
||||
{ sig = "spi_data_type #platform_spi_send_recv#( unsigned id, spi_data_type data );",
|
||||
desc = "Executes a SPI read/write cycle",
|
||||
args =
|
||||
{
|
||||
"$id$ - SPI interface ID",
|
||||
"$data$ - data to be sent to the SPI interface",
|
||||
},
|
||||
ret = "data read from the SPI interface"
|
||||
},
|
||||
|
||||
{ sig = "void #platform_spi_select#( unsigned id, int is_select );",
|
||||
desc = [[For platforms that have a dedicates SS (Slave Select) pin in master SPI mode that can be controlled manually, this function should enable/disable this pin. If this functionality
|
||||
does not exist in hardware this function does nothing.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - SPI interface ID.",
|
||||
"$is_select$ - $PLATFORM_SPI_SELECT_ON$ to select, $PLATFORM_SPI_SELECT_OFF$ to deselect , see @#chip_select@here@."
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -1,5 +1,13 @@
|
||||
-- eLua platform interface - timers
|
||||
|
||||
--[[
|
||||
// The next 3 functions need to be implemented only if the generic system timer mechanism
|
||||
// (src/common.c:cmn_systimer*) is used by the backend
|
||||
u64 platform_timer_sys_raw_read();
|
||||
void platform_timer_sys_enable_int();
|
||||
void platform_timer_sys_disable_int();
|
||||
--]]
|
||||
|
||||
data_en =
|
||||
{
|
||||
-- Title
|
||||
@ -10,14 +18,15 @@ data_en =
|
||||
|
||||
-- Overview
|
||||
overview = [[This part of the platform interface groups functions related to the timers of the MCU. It also makes provisions for using $virtual timers$ on any platform, see @#virtual@this section@
|
||||
for details. Keep in mind that in the following paragraphs a $timer id$ can reffer to both a hardware timer or a virtual timer.]],
|
||||
for details. Keep in mind that in the following paragraphs a $timer id$ can refer to both a hardware timer or a virtual timer.]],
|
||||
|
||||
-- Data structures, constants and types
|
||||
structures =
|
||||
{
|
||||
{ text = "typedef u32 timer_data_type;",
|
||||
{ text = "typedef u64/u32 timer_data_type;",
|
||||
name = "Timer data type",
|
||||
desc = "This defines the data type used to specify delays and time intervals (which are always specifide in $microseconds$)."
|
||||
desc = [[This defines the data type used to specify delays and time intervals (which are always specified in $microseconds$). The choice between u64 and u32 for the timer data type depends
|
||||
on the build type, check ^#the_system_timer^here^ for mode details.]]
|
||||
},
|
||||
|
||||
{ text = [[// Timer operations
|
||||
@ -28,7 +37,8 @@ enum
|
||||
PLATFORM_TIMER_OP_SET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_MAX_DELAY,
|
||||
PLATFORM_TIMER_OP_GET_MIN_DELAY
|
||||
PLATFORM_TIMER_OP_GET_MIN_DELAY,
|
||||
PLATFORM_TIMER_OP_GET_MAX_CNT
|
||||
};]],
|
||||
name = "Timer operations",
|
||||
desc = "This enum lists all the operations that can be executed on a given timer."
|
||||
@ -46,9 +56,9 @@ enum
|
||||
ret = "1 if the timer exists, 0 otherwise"
|
||||
},
|
||||
|
||||
{ sig = "void #platform_timer_delay#( unsigned id, u32 delay_us );",
|
||||
desc = [[Waits on a timer, then returns. This function is "split" in two parts: a platform-independent part implemented in %src/common.c% (that
|
||||
handles virtual timers) and a platform-dependent part that must be implemented by each platform in a function named @#platform_s_timer_delay@platform_s_timer_delay@. This function handles both
|
||||
{ sig = "void #platform_timer_delay#( unsigned id, timer_data_type delay_us );",
|
||||
desc = [[Waits on a timer, then returns. This function is "split" in two parts: a platform-independent part implemented in %src/common_tmr.c% (that
|
||||
handles virtual timers and the system timer) and a platform-dependent part that must be implemented by each platform in a function named @#platform_s_timer_delay@platform_s_timer_delay@. This function handles both
|
||||
hardware timer IDs and virtual timer IDs.<br>
|
||||
<a name="limitations" /><span class="warning">IMPORTANT NOTE</span>: the real delay after executing this functions depends on a number of variables, most notably the base clock of the timer
|
||||
and the size of the timer counter register (32 bits on some platforms, 16 bits on most platforms, other values are less common). To ensure that the delay you're requesting is achievable, use
|
||||
@ -62,9 +72,9 @@ enum
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "void #platform_s_timer_delay#( unsigned id, u32 delay_us );",
|
||||
desc = [[This function is identical in functionality to @#platform_timer_delay@platform_timer_delay@, but this is the function that must actually be implemented by a platform port,
|
||||
and it must never handle virtual timer IDs, only hardware timer IDs. It has the same @#limitations@limitations@ as @#platform_timer_delay@platform_timer_delay@.]],
|
||||
{ sig = "void #platform_s_timer_delay#( unsigned id, timer_data_type delay_us );",
|
||||
desc = [[This function is identical in functionality to @#platform_timer_delay@platform_timer_delay@, but this is the function that must actually be implemented by a platform port
|
||||
and it must never handle virtual timer IDs or the system timer ID, only hardware timer IDs. It has the same @#limitations@limitations@ as @#platform_timer_delay@platform_timer_delay@.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID",
|
||||
@ -72,8 +82,8 @@ enum
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_timer_op#( unsigned id, int op, u32 data );",
|
||||
desc = [[Executes an operation on a timer. This function is "split" in two parts: a platform-independent part implemented in %src/common.c% (that handles virtual timers) and a
|
||||
{ sig = "timer_data_type #platform_timer_op#( unsigned id, int op, timer_data_type data );",
|
||||
desc = [[Executes an operation on a timer. This function is "split" in two parts: a platform-independent part implemented in %src/common_tmr.c% (that handles virtual timers and the system timer) and a
|
||||
platform-dependent part that must be implemented by each platform in a function named @#platform_s_timer_op@platform_s_timer_op@. This function handles both hardware timer IDs and virtual
|
||||
timer IDs.]],
|
||||
args =
|
||||
@ -87,6 +97,7 @@ enum
|
||||
<li>$PLATFORM_TIMER_GET_CLOCK$: get the clock of the specified timer.</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MAX_DELAY$: get the maximum achievable timeout on the specified timer (in us).</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MIN_DELAY$: get the minimum achievable timeout on the specified timer (in us).</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MAX_CNT$: get the maximum value of the timer's counter register.</li>
|
||||
</ul>]],
|
||||
"$data$ - used to specify the timer clock value when $op = PLATFORM_TIMER_SET_CLOCK$, ignored otherwise",
|
||||
},
|
||||
@ -97,13 +108,14 @@ enum
|
||||
"the actual clock set on the timer, which might be different than the request clock depending on the hardware if $op = PLATFORM_TIMER_SET_CLOCK$",
|
||||
"the timer clock if $op = PLATFORM_TIMER_GET_CLOCK$",
|
||||
"the maximum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MAX_DELAY$",
|
||||
"the minimum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MIN_DELAY$"
|
||||
"the minimum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MIN_DELAY$",
|
||||
"the maximum value of the timer's coutner register if $op == PLATFORM_TIMER_OP_GET_MAX_CNT$",
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_s_timer_op#( unsigned id, int op, u32 data );",
|
||||
desc = [[This function is identical in functionality to @#platform_timer_op@platform_timer_op@, but this is the function that must actually be implemented by a platform port, and it must
|
||||
never handle virtual timer IDs, only hardware timer IDs.]],
|
||||
{ sig = "timer_data_type #platform_s_timer_op#( unsigned id, int op, timer_data_type data );",
|
||||
desc = [[This function is identical in functionality to @#platform_timer_op@platform_timer_op@, but this is the function that must actually be implemented by a platform port and it must
|
||||
never handle virtual timer IDs or the system timer, only hardware timer IDs.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID",
|
||||
@ -115,6 +127,7 @@ enum
|
||||
<li>$PLATFORM_TIMER_GET_CLOCK$: get the clock of the specified timer.</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MAX_DELAY$: get the maximum achievable timeout on the specified timer (in us).</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MIN_DELAY$: get the minimum achievable timeout on the specified timer (in us).</li>
|
||||
<li>$PLATFORM_TIMER_OP_GET_MAX_CNT$: get the maximum value of the timer's counter register.</li>
|
||||
</ul>]],
|
||||
"$data$ - used to specify the timer clock value when $op = PLATFORM_TIMER_SET_CLOCK$, ignored otherwise",
|
||||
},
|
||||
@ -125,23 +138,29 @@ enum
|
||||
"the actual clock set on the timer, which might be different than the request clock depending on the hardware if $op = PLATFORM_TIMER_SET_CLOCK$",
|
||||
"the timer clock if $op = PLATFORM_TIMER_GET_CLOCK$",
|
||||
"the maximum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MAX_DELAY$",
|
||||
"the minimum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MIN_DELAY$"
|
||||
"the minimum achievable delay (in microseconds) if $op = PLATFORM_TIMER_OP_GET_MIN_DELAY$",
|
||||
"the maximum value of the timer's coutner register if $op == PLATFORM_TIMER_OP_GET_MAX_CNT$",
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "u32 #platform_timer_get_diff_us#( unsigned id, timer_data_type end, timer_data_type start );",
|
||||
desc = [[Return the time difference (in us) betweeen two timer values. This function is generic for all platforms, thus it is implemented in %src/common.c%.]],
|
||||
{ sig = "timer_data_type #platform_timer_get_diff_us#( unsigned id, timer_data_type end, timer_data_type start );",
|
||||
desc = [[Return the time difference (in us) between two timer values (as returned by calling @refman_gen_tmr.html#platform_timer_op@platform_timer_op@ with $PLATFORM_TIMER_OP_READ$ or $PLATFORM_TIMER_OP_START$. This function
|
||||
is generic, thus it is implemented in %src/common.c%. <span class="warning">NOTE</span>: the order of $end$ and $start$ is important. $end$ must correspond to a moment in time which came after $start$. The function knows how to deal
|
||||
with $a single$ timer overflow condition ($end$ is less than $start$); if the timer overflowed 2 or more times between $start$ and $end$ the result of this function will be incorrect.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID",
|
||||
"$end$ - the first timer value",
|
||||
"$start$ - the second timer value",
|
||||
"$end$ - the final counter value.",
|
||||
"$start$ - the initial counter value.",
|
||||
},
|
||||
ret = "the time difference (in microseconds)"
|
||||
},
|
||||
|
||||
{ sig = "int #platform_timer_set_match_int#( unsigned id, u32 period_us, int type );",
|
||||
desc = "Setup the timer match interrupt. Only available if interrupt support is enabed, check @inthandlers.html@here@ for details.",
|
||||
{ sig = "int #platform_timer_set_match_int#( unsigned id, timer_data_type period_us, int type );",
|
||||
desc = [[Setup the timer match interrupt. Only available if interrupt support is enabled, check @inthandlers.html@here@ for details.This function is "split" in two parts: a platform-independent part
|
||||
implemented in %src/common_tmr.c% (that handles virtual timers and the system timer) and a platform-dependent part that must be implemented by each platform in a function named
|
||||
@#platform_s_timer_set_math_int@platform_s_timer_set_match_int@. This function handles both hardware timer IDs and virtual timer IDs. <span class="warning">NOTE</span>: the @#the_system_timer@system timer@ can't
|
||||
generate interrupts.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID",
|
||||
@ -153,11 +172,62 @@ $period_us$ microseconds]]
|
||||
{
|
||||
"$PLATFORM_TIMER_INT_OK$ if the operation was successful.",
|
||||
"$PLATFORM_TIMER_INT_TOO_SHORT$ if the specified period is too short.",
|
||||
"$PLATFORM_TIMER_INT_TOO_LONG$ if the specified period is too long.",
|
||||
"$PLATFORM_TIMER_INT_INVALID_ID$ if the specified timer cannot handle this operation."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "int #platform_s_timer_set_match_int#( unsigned id, timer_data_type period_us, int type );",
|
||||
desc = [[This function is identical in functionality to @#platform_timer_set_match_int@platform_timer_set_match_int@, but this is the function that must actually be implemented by a platform port and it must
|
||||
never handle virtual timer IDs or the system timer, only hardware timer IDs.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID",
|
||||
"$period_us$ - the period (in microseconds) of the timer interrupt. Setting this to 0 disables the timer match interrupt.",
|
||||
[[$type$ - $PLATFORM_TIMER_INT_ONESHOT$ for an interrupt that occurs only once after $period_us$ microseconds, or $PLATFORM_TIMER_INT_CYCLIC$ for an interrupt that occurs every
|
||||
$period_us$ microseconds]]
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"$PLATFORM_TIMER_INT_OK$ if the operation was successful.",
|
||||
"$PLATFORM_TIMER_INT_TOO_SHORT$ if the specified period is too short.",
|
||||
"$PLATFORM_TIMER_INT_TOO_LONG$ if the specified period is too long.",
|
||||
"$PLATFORM_TIMER_INT_INVALID_ID$ if the specified timer cannot handle this operation."
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
sig = "timer_data_type #platform_timer_read_sys#();",
|
||||
desc = "Returns the current value of the system timer, see @#the_system_timer@here@ for more details.",
|
||||
ret = "The current value of the system timer."
|
||||
},
|
||||
|
||||
{
|
||||
sig = "int #platform_timer_sys_available#();",
|
||||
desc = [[Used to check the availability of the system timer. This function is platform independent and is implemented in %src/common_tmr.c%. It returns the value of the $PLATFORM_HAS_SYSTIMER$ macro, check
|
||||
@#the_system_timer@here@ for more details.]],
|
||||
ret = "1 if the system timer is implemented, 0 otherwise."
|
||||
},
|
||||
|
||||
{
|
||||
sig = "u64 #platform_timer_sys_raw_read#();",
|
||||
desc = [[Return the counter of the timer used to implement the system timer. Needs to be implemented only if eLua's generic system timer mechanism is used, check @#the_system_timer@here@ for details.]],
|
||||
ret = "The counter of the timer used to implement the system timer."
|
||||
},
|
||||
|
||||
{
|
||||
sig = "void #platform_timer_sys_enable_int#();",
|
||||
desc = [[Enable the overflow/match interrupt of the timer used to implement the system timer. Needs to be implemented only if eLua's generic system timer mechanism is used, check @#the_system_timer@here@ for details.]],
|
||||
},
|
||||
|
||||
{
|
||||
sig = "void #platform_timer_sys_disable_int#();",
|
||||
desc = [[Disable the overflow/match interrupt of the timer used to implement the system timer. Needs to be implemented only if eLua's generic system timer mechanism is used, check @#the_system_timer@here@ for details.]],
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
|
||||
auxdata =
|
||||
{
|
||||
{ title = "Virtual timers",
|
||||
@ -199,8 +269,88 @@ $period_us$ microseconds]]
|
||||
$VTMR_FIRST_ID$) is the ID of the first virtual timer in the system, and $VTMR_FIRST_ID+2$ is the ID of the third virtual timer in the system.</p>
|
||||
<p>Virtual timers are capable of generating timer match interrupts just like regular timers, check @#platform_timer_set_match_int@here@ for details.
|
||||
]]
|
||||
}
|
||||
},
|
||||
{ title = "The system timer",
|
||||
desc =
|
||||
[[The system timer was introduced in eLua 0.9 as a simpler alternative to the traditional eLua timers. Working with regular timers in eLua might be challenging for a number of reasons:</p>
|
||||
<ul>
|
||||
<li>depending on the hardware, the timers might have a limited range. Because of this, they might not be able to timeout in the interval requested by the user.</li>
|
||||
<li>the timers might have different ranges even on the same platform (they might have a different base clock, for example). The problem is further aggravated when switching platforms.</li>
|
||||
<li>the timers might be shared with other hardware resources (for example PWMs or ADC triggers) so using them might have unexpected side effects.</li>
|
||||
<li>manual timer management is error prone. The user needs to keep into account the timers he's using, their base frequencies and wether they are shared or not with the C code.</li>
|
||||
</ul>
|
||||
<p>The ^#virtual_timers^virtual timers^ can fix some of the above problems, but their resolution is fairly low and they still require manual management.</p>
|
||||
<p>The $system timer$ attemps to fix (at least partially) these issues. It is a timer with fixed resolution (1us) %on all platforms% and large counters:</p>
|
||||
<ul>
|
||||
<li>if eLua is compiled in floating point mode (default) the counter is 52 bits wide. It will overflow after more than 142 %years%.</li>
|
||||
<li>if eLua is compiled in 32 bit integer-only mode (lualong) the counter is 32 bits wide. It will overflow after about one hour.</li>
|
||||
<li>if eLua is compiled in 64 bit integer-only mode (lualonglong, new in 0.9) the counter is again 52 bits wide and it will also overflow after more than 142 years.</li>
|
||||
</ul>
|
||||
<p>The eLua API was partially modified to take full advantage of this new timer:</p>
|
||||
<ul>
|
||||
<li>all the functions that can operate with a timeout (for example @refman_gen_uart.html#uart.read@uart.read@ or @refman_gen_net.html#net.accept@net.accept@)
|
||||
will default to the system timer is a timer ID is not specified explicitly.</li>
|
||||
<li>all the function in the @refman_gen_tmr.html@timer module@ will default to the system timer if a timer ID is not specified explicitly.</li>
|
||||
<li>timeouts are specified in a more unified manner across the eLua modules as a $[timeout], [timer_id]$ pair:
|
||||
<table class="table_center" style="margin-top: 10px; margin-bottom: 4px;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>timeout</th>
|
||||
<th>timer_id</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>not specified</td>
|
||||
<td>any value</td>
|
||||
<td>infinite timeout (the function blocks until it completes).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>0</td>
|
||||
<td>any value</td>
|
||||
<td>no timeout (the function returns immediately).<//td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>a positive value</td>
|
||||
<td>not specified</td>
|
||||
<td>the system timer will be used to measure the function's timeout.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>a positive value</td>
|
||||
<td>a timer ID</td>
|
||||
<td>the specified timer will be used to measure the function's timeout.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<p>Using the system timer as much as possible is also encouraged with C code that uses the eLua C api, not only with Lua programs. The C code can use the system timer by specifying
|
||||
$PLATFORM_TIMER_SYS_ID$ as the timer ID.</p>
|
||||
<p>From an implementation stand point, the system timer is built around a hardware timer with a base clock of at least 1MHz that can generate an interrupt when the timer counter overflows
|
||||
or when it reaches a certain value. The interrupt handler updates the upper part of the system timer counter (basically an overflow counter). eLua has a generic mechanism that can be used
|
||||
to implement a system timer on any platform using this method. To take advantage of this mechanism follow the steps below:</p>
|
||||
<ol>
|
||||
<li>define the $PLATFORM_HAS_SYSTIMER$ macro in your %platform_conf.h% file.</li>
|
||||
<li>implement @#platform_timer_sys_raw_read@platform_timer_sys_raw_read@, @#platform_timer_sys_enable_int@platform_timer_sys_enable_int@ and @#platform_timer_sys_disable_int@platform_timer_sys_disable_int@.</li>
|
||||
<li>include the %common.h% header.</li>
|
||||
<li>setup your hardware timer and its associated interrupt. This should happen an initialization time (for example in %platform_init%).</li>
|
||||
<li>call %cmn_systimer_set_base_freq% with the base frequency of your timer in Hz.</li>
|
||||
<li>call %cmn_systimer_set_interrupt_freq% with the frequency of the timer's overflow/match interrupt in Hz. Alternatively you can call %cmn_systimer_set_interrupt_period_us% to set the timer's overflow/match
|
||||
interrupt %period% (in microseconds) instead of its frequency. Use the latter form if the frequency is not an integer.</li>
|
||||
<li>call %cmn_systimer_periodic% from your timer's overflow interrupt handler.</li>
|
||||
<li>use this implementation for @#platform_timer_read_sys@platform_timer_read_sys@:
|
||||
~timer_data_type platform_timer_read_sys()
|
||||
{
|
||||
return cmn_systimer_get();
|
||||
}~</li></ol>
|
||||
<p>Note that the above mechanism is optional. A platform might have a different method to implement the system timer; this is OK as long as the system timer requirements are respected.</p>
|
||||
<p><span class="warning">IMPORTANT NOTE</span>: although system timer support in eLua is optional, implementing the system timer is highly recommended. As already specified, all the timer IDs
|
||||
in various eLua modules default to the system timer. This means that any code that was written under the assumption that a system timer is present (which is a fair assumption) will fail on
|
||||
platforms that don't actually have a system timer. Check @status.html#systmr@here@ for a list of platforms that implement the system timer. If your platform doesn't implement the
|
||||
system timer, you'll get this warning at compile time:</p>
|
||||
~#warning This platform does not have a system timer. Your eLua image might not work as expected.~
|
||||
]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,12 +36,6 @@ enum
|
||||
desc = "Constants used to specify the number of UART stop bits.",
|
||||
},
|
||||
|
||||
{ text = [[// "Infinite timeout" constant for recv
|
||||
#define PLATFORM_UART_INFINITE_TIMEOUT (-1)]],
|
||||
name = "UART timeout",
|
||||
desc = "This constant is used as a special timeout value (infinite timeout) in the UART functions that expect a timeout as argument.",
|
||||
},
|
||||
|
||||
{ text = [[// Virtual UART IDs
|
||||
#define SERMUX_SERVICE_ID_FIRST 0xD0
|
||||
#define SERMUX_SERVICE_ID_LAST 0xD7
|
||||
@ -108,7 +102,7 @@ enum
|
||||
},
|
||||
},
|
||||
|
||||
{ sig = "int #platform_uart_recv#( unsigned id, unsigned timer_id, s32 timeout );",
|
||||
{ sig = "int #platform_uart_recv#( unsigned id, unsigned timer_id, timer_data_type timeout );",
|
||||
link = "platform_uart_recv",
|
||||
desc = [[Receive data from the UART interface (blocking/non blocking with timeout/immediate).<br>
|
||||
This function is "split" in two parts: a platform-independent part that is implemented in %src/common.c% and a platform-dependent part that must be implemented by each
|
||||
@ -121,7 +115,7 @@ enum
|
||||
<ul>
|
||||
<li>$timeout > 0$: the timer with the specified $timer_id$ will be used to timeout the receive operation after $timeout$ microseconds.</li>
|
||||
<li>$timeout = 0$: the function returns immediately regardless of data being available or not. $timer_id$ is ignored.</li>
|
||||
<li>$timeout$ = @#uart_timeout@PLATFORM_UART_INFINITE_TIMEOUT@: the function waits indefinitely for UART data to be available and returns it. In this mode the function doesn't
|
||||
<li>$timeout = PLATFORM_TIMER_INF_TIMEOUT$: the function waits indefinitely for UART data to be available and returns it. In this mode the function doesn't
|
||||
time out, so $timer_id$ is ignored.</li>
|
||||
</ul>]],
|
||||
},
|
||||
@ -129,11 +123,11 @@ enum
|
||||
{
|
||||
"if $timeout > 0$ and data from the UART is available in $timeout$ microseconds of less it is returned, otherwise -1 is returned",
|
||||
"if $timeout = 0$ and data from the UART is available when the function is called it is returned, otherwise -1 is returned",
|
||||
"if $timeout$ = @#uart_timeout@PLATFORM_UART_INIFINITE_TIMEOUT@ it returns the data read from the UART after it becomes available"
|
||||
"if $timeout = PLATFORM_TIMER_INF_TIMEOUT$ it returns the data read from the UART after it becomes available"
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "int #platform_s_uart_recv#( unsigned id, s32 timeout );",
|
||||
{ sig = "int #platform_s_uart_recv#( unsigned id, timer_data_type timeout );",
|
||||
link = "platform_s_uart_recv",
|
||||
desc = [[This is the platform-dependent part of the UART receive function @#platform_uart_recv@platform_uart_recv@ and is in fact a "subset" of the full function
|
||||
(thus being easier to implement by each platform in part). In particular, it never needs to deal with the $timeout > 0$ case, which is handled by @#platform_uart_recv@platform_uart_recv@.]],
|
||||
@ -143,13 +137,13 @@ enum
|
||||
[[$timeout$ - specifies a timeout for the receive operation as follows:
|
||||
<ul>
|
||||
<li>$timeout = 0$: the function returns immediately regardless of data being available or not.</li>
|
||||
<li>$timeout$ = @#uart_timeout@PLATFORM_UART_INFINITE_TIMEOUT@: the function waits indefinitely for UART data to be available and returns it.</li>
|
||||
<li>$timeout = PLATFORM_TIMER_INF_TIMEOUT$: the function waits indefinitely for UART data to be available and returns it.</li>
|
||||
</ul>]],
|
||||
},
|
||||
ret =
|
||||
{
|
||||
"if $timeout = 0$ and data from the UART is available when the function is called it is returned, otherwise -1 is returned",
|
||||
"if $timeout$ = @#uart_timeout@PLATFORM_UART_INIFINITE_TIMEOUT@ it returns the data read from the UART after it becomes available"
|
||||
"if $timeout = PLATFORM_TIMER_INF_TIMEOUT$ it returns the data read from the UART after it becomes available"
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -70,7 +70,7 @@ data_en =
|
||||
"$clock$ - frequency to acquire samples at in Hz (number of samples per second), 0 to acquire as fast as possible.",
|
||||
"$timer_id$ - Timer channel ID to use to control ADC conversion. <strong>Note:</strong> At this time, a timer selection will apply to all channels on a given ADC peripheral."
|
||||
},
|
||||
ret = "$clock$ - actual acquisition frequency to be used"
|
||||
ret = "$clock$ - actual acquisition frequency that was set"
|
||||
},
|
||||
{ sig = "status = #adc.isdone#( id )",
|
||||
desc = "Check whether samples are still being acquired on a channel.",
|
||||
@ -81,7 +81,7 @@ data_en =
|
||||
ret = "$status$ - 1 if no samples are being acquired, 0 if samples are pending acquisition."
|
||||
},
|
||||
{ sig = "#adc.setblocking#( id, mode )",
|
||||
desc = "Set whether or not functions that request converted samples should wait for requested samples or return immediately with what is available.",
|
||||
desc = "Set whether or not functions that request converted samples should wait for requested samples or return immediately with what is available. If this function is not called, each channel starts in blocking mode.",
|
||||
args =
|
||||
{
|
||||
"$id$ - ADC channel ID.",
|
||||
|
@ -31,7 +31,7 @@ $_C$. For example, to get the constants listed above declare your $PLATFORM_CPU_
|
||||
_C( INT_GPIOB ),\
|
||||
.................
|
||||
_C( INT_UDMA )~
|
||||
<p>It's worth to note that adding more constants does not increas RAM usage, only Flash usage, so you can expose as much constants as you need without worrying about RAM consumption.<br />
|
||||
<p>It's worth to note that adding more constants does not increase RAM usage, only Flash usage, so you can expose as many constants as you need without worrying about RAM consumption.<br />
|
||||
This mechanism is also used to expose interrupt IDs to the CPU module, check @inthandlers.html@here@ for an overview of eLua interrupt support.]]
|
||||
},
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ data_en =
|
||||
args =
|
||||
{
|
||||
"$id$ - the ID of the I2C interface.",
|
||||
"$speed$ - the speed of the I2C interface. It can be either $i2c.FAST$ (400KHz) or $i2c.SLOW$ (100KHz).",
|
||||
"$speed$ - the clock frequency of the I2C interface. It can be $i2c.FAST$ (400KHz), $i2c.SLOW$ (100KHz) or a number giving the required I2C bus clock speed in Hz.",
|
||||
},
|
||||
ret = "the actual speed of the I2C interface."
|
||||
},
|
||||
@ -48,22 +48,22 @@ data_en =
|
||||
},
|
||||
|
||||
{ sig = "wrote = #i2c.write#( id, data1, [data2], ..., [datan] )",
|
||||
desc = "Writes data to a slave that already acknowledged an @#i2c.address@i2c.address@ call.",
|
||||
desc = "Writes data to a slave that has already acknowledged an @#i2c.address@i2c.address@ call.",
|
||||
args =
|
||||
{
|
||||
"$id$ - the ID of the I2C interface.",
|
||||
"$data1$ - the data to send. It can be either a number between 0 and 255, a string or a table (array).",
|
||||
"$data1$ - the data to send. It can be either a number between 0 and 255, a string or a table (array) of numbers.",
|
||||
"$data2 (optional)$ - the second data to send.",
|
||||
"$datan (optional)$ - the %n%-th data to send."
|
||||
},
|
||||
ret = "the number of bytes actually wrote."
|
||||
ret = "the number of bytes actually written."
|
||||
},
|
||||
|
||||
{ sig = "data = #i2c.read#( id, numbytes )",
|
||||
desc = "Reads a number of bytes from a slave that already acknowledged an @#i2c.address@i2c.address@ call. It acknowledges all the bytes received, except for the last one.",
|
||||
desc = "Reads a number of bytes from a slave that has already acknowledged an @#i2c.address@i2c.address@ call. It acknowledges all the bytes received except for the last one.",
|
||||
args =
|
||||
{
|
||||
"$id$ - the ID os the SPI interface.",
|
||||
"$id$ - the ID of the I2C interface.",
|
||||
"$numbytes$ - the number of bytes to read."
|
||||
},
|
||||
ret = "a string with all the data read from the I2C interface."
|
||||
|
@ -104,15 +104,15 @@ argument. The IP is given as a string.]],
|
||||
ret = "$err$ - the error code, as defined @#error_codes@here@."
|
||||
},
|
||||
|
||||
{ sig = "socket, remoteip, err = #net.accept#( port, [timer_id, timeout] )",
|
||||
{ sig = "socket, remoteip, err = #net.accept#( port, [timeout], [timer_id] )",
|
||||
desc = "Accept a connection from a remote system with an optional timeout.",
|
||||
args =
|
||||
{
|
||||
"$port$ - the port to wait for connections from the remote system.",
|
||||
[[$timer_id (optional)$ - the timer ID of the timer used to timeout the accept function after a specified time. If this is specified, $timeout$ must also
|
||||
be specified.]],
|
||||
[[$timeout (optional)$ - the timeout after which the accept function returns if no connection was requested. If this is specified, $timer_id$ must also
|
||||
be specified.]]
|
||||
[[$timeout (optional)$ - timeout of the operation, can be either $net.NO_TIMEOUT$ or 0 for non-blocking operation, $net.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $unet.INF_TIMEOUT$.]],
|
||||
[[$timer_id (optional)$ - the ID of the timer used for measuring the timeout. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
|
||||
|
||||
},
|
||||
ret =
|
||||
{
|
||||
@ -136,7 +136,7 @@ be specified.]]
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "res, err = #net.recv#( sock, format, [timer_id, timeout] )",
|
||||
{ sig = "res, err = #net.recv#( sock, format, [timeout], [timer_id] )",
|
||||
desc = "Read data from a socket.",
|
||||
args =
|
||||
{
|
||||
@ -146,10 +146,9 @@ be specified.]]
|
||||
<li>$"*l"$: read a line (until the next '\n' character).</li>
|
||||
<li>$an integer$: read up to that many bytes.</li>
|
||||
</ul>]],
|
||||
[[$timer_id (optional)$ - the timer ID of the timer used to timeout the recv function after a specified time. If this is specified, $timeout$ must also
|
||||
be specified.]],
|
||||
[[$timeout (optional)$ - the timeout after which the recv function returns if no connection was requested. If this is specified, $timer_id$ must also
|
||||
be specified.]]
|
||||
[[$timeout (optional)$ - timeout of the operation, can be either $net.NO_TIMEOUT$ or 0 for non-blocking operation, $net.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $unet.INF_TIMEOUT$.]],
|
||||
[[$timer_id (optional)$ - the ID of the timer used for measuring the timeout. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
|
||||
},
|
||||
ret =
|
||||
{
|
||||
@ -160,4 +159,3 @@ be specified.]]
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
||||
|
@ -14,86 +14,100 @@ data_en =
|
||||
(see @arch_platform_timers.html#virtual_timers@here@ and @building.html@here@ for details), they can be used just like the "regular" (hardware)
|
||||
timers with a single exception: you can't set the clock of a virtual timer (using @#tmr.setclock@tmr.setclock@). To use virtual timers with this
|
||||
module, specify $tmr.VIRTx$ as the timer ID instead of a number. For example, if the eLua image was configured to support 4 virtual timers, they will
|
||||
be available by using $tmr.VIRT0$ to $tmr.VIRT3$ as timer IDs.</p>
|
||||
be available by using $tmr.VIRT0$ to $tmr.VIRT3$ as timer IDs. The @arch_platform_timers.html#the_system_timer@system timer@ can also be used with
|
||||
any of these functions by ommiting the timer ID or specifying it as $tmr.SYS_TIMER$.</p>
|
||||
<p>All "time units" (delays, differences in time) in this module, as well as in other parts of eLua (timeouts) are expressed in microseconds. However,
|
||||
please keep in mind that the actual timer resolution depends on many factors. For example, it's very likely that the @#tmr.delay@tmr.delay@ function won't
|
||||
be able to delay for the exact amount you specify (in us), as the real delay depends ona number of variables, most notably the base clock of the timer
|
||||
be able to delay for the exact amount you specify (in us), as the real delay depends on a number of variables, most notably the base clock of the timer
|
||||
and the size of the timer counter register (32 bits on some platforms, 16 bits on most platforms, other values are less common). To ensure that the delay
|
||||
you're requesting is achievable, use @#tmr.getmindelay@tmr.getmindelay@ and @#tmr.getmaxdelay@tmr.getmaxdelay@ to obtain the maximum and the minimum
|
||||
achievable wait times on your timer, respectively. Even if your delay is within these limits, the $precision$ of this function still varies a lot,
|
||||
mainly as a function of the timer base clock.]],
|
||||
mainly as a function of the timer base clock. Using the @arch_platform_timers.html#the_system_timer@system timer@ is highly encouraged if it is
|
||||
available on the platform as it can eliminate the forementioned problems.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#tmr.delay#( id, period )",
|
||||
{ sig = "#tmr.delay#( period, [id] )",
|
||||
desc = "Waits for the specified period, then returns.",
|
||||
args =
|
||||
{
|
||||
"$period$ - the timer ID.",
|
||||
"$period$ - how long to wait (in us)."
|
||||
"$period$ - how long to wait (in us).",
|
||||
"$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "counter = #tmr.read#( id )",
|
||||
{ sig = "counter = #tmr.read#( [id] )",
|
||||
desc= "Reads the timer counter register.",
|
||||
args = "$id$ - the timer ID.",
|
||||
args = "$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
ret = "The value of the timer counter register."
|
||||
},
|
||||
|
||||
{ sig = "counter = #tmr.start#( id )",
|
||||
{ sig = "counter = #tmr.start#( [id] )",
|
||||
desc = "Starts the specified timer.",
|
||||
args = "$id$ - the timer ID.",
|
||||
args = "$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
ret = "The value of the timer counter register when the timer started.",
|
||||
},
|
||||
|
||||
{ sig = "delta = #tmr.gettimediff#( id, counter1, counter2 )",
|
||||
desc = "Computes the time difference between two timer counter values (you can get counter values by calling @#tmr.read@tmr.read@ or @#tmr.start@tmr.start@).",
|
||||
{ sig = "delta = #tmr.gettimediff#( end, start, [id] )",
|
||||
desc = [[Computes the time difference between two timer counter values (obtained by calling @#tmr.read@tmr.read@ or @#tmr.start@tmr.start@). <span class="warning">NOTE</span>: the order
|
||||
of $end$ and $start$ is important. $end$ must correspond to a moment in time which came after $start$. The function knows how to deal with $a single$ timer overflow condition ($end$ is less than $start$); if the timer overflowed 2 or more times between $start$ and $end$ the result of this function will be incorrect.]],
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID.",
|
||||
"$counter1$ - the first counter value.",
|
||||
"$counter2$ - the second counter value.",
|
||||
"$end$ - the final counter value.",
|
||||
"$start$ - the initial counter value.",
|
||||
"$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
},
|
||||
ret = "The time difference (in us)."
|
||||
},
|
||||
|
||||
{ sig = "mindelay = #tmr.getmindelay#( id )",
|
||||
desc = "Get the minimum achieavable delay on the specified timer.",
|
||||
args = "$id$ - the timer ID.",
|
||||
{ sig = "delta = #tmr.getdiffnow#( start, [id] )",
|
||||
desc = [[Computes the time difference between a counter value from the past (obtained by calling @#tmr.read@tmr.read@ or @#tmr.start@tmr.start@) and the counter value corresponding to the current time.]],
|
||||
args =
|
||||
{
|
||||
"$start$ - the initial counter value.",
|
||||
"$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
},
|
||||
ret = "The time difference (in us)."
|
||||
},
|
||||
|
||||
|
||||
{ sig = "mindelay = #tmr.getmindelay#( [id] )",
|
||||
desc = "Get the minimum achievable delay on the specified timer.",
|
||||
args = "$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
ret = "The minimum achievable delay on the specified timer (in us)."
|
||||
},
|
||||
|
||||
{ sig = "maxdelay = #tmr.getmaxdelay#( id )",
|
||||
desc = "Get the maximum achieavable delay on the specified timer.",
|
||||
args = "$id$ - the timer ID.",
|
||||
{ sig = "maxdelay = #tmr.getmaxdelay#( [id] )",
|
||||
desc = "Get the maximum achievable delay on the specified timer.",
|
||||
args = "$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
ret = "The maximum achievable delay on the specified timer (in us)."
|
||||
},
|
||||
|
||||
{ sig = "clock = #tmr.setclock#( id, clock )",
|
||||
{ sig = "clock = #tmr.setclock#( clock, [id] )",
|
||||
desc = "Set the timer clock (the clock used to increment the timer counter register).",
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID.",
|
||||
"$clock$ - the timer clock (in Hz)."
|
||||
"$clock$ - the timer clock (in Hz). ",
|
||||
"$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
},
|
||||
ret = [[The actual clock set on the timer (in Hz). Depending on the hardware, this might have a different value than the $clock$ argument.
|
||||
$NOTE:$ this function does not work with virtual timers.]]
|
||||
$NOTE:$ this function does not work with virtual timers or with the system timer.]]
|
||||
},
|
||||
|
||||
{ sig = "clock = #tmr.getclock#( id )",
|
||||
{ sig = "clock = #tmr.getclock#( [id] )",
|
||||
desc = "Get the timer clock (the clock used to increment the timer counter register).",
|
||||
args = "$id$ - the timer ID.",
|
||||
args = "$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.",
|
||||
ret = "The timer clock (in Hz)."
|
||||
},
|
||||
|
||||
{ sig = "#tmr.set_match_int#( id, period, type )",
|
||||
{ sig = "#tmr.set_match_int#( period, type, [id] )",
|
||||
desc = "Setup the timer match interrupt. Only available if interrupt support is enabled, check @inthandlers.html@here@ for details.",
|
||||
args =
|
||||
{
|
||||
"$id$ - the timer ID.",
|
||||
"$period$ - the interrupt period in microseconds. Setting this to 0 disabled the timer match interrupt.",
|
||||
"$type$ - $tmr.INT_ONESHOT$ to generate a single interrupt after *period* microseconds, or $tmr.INT_CYCLIC$ to generate interrupts every $period$ microseconds."
|
||||
"$type$ - $tmr.INT_ONESHOT$ to generate a single interrupt after *period* microseconds, or $tmr.INT_CYCLIC$ to generate interrupts every $period$ microseconds.",
|
||||
[[$id (optional)$ - the timer ID. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@ (but note that this happens only for consistency, as the system timer can't generate interrupts).]],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,11 +58,9 @@ to the IDs of the virtual UARTs in the system.]]
|
||||
args =
|
||||
{
|
||||
"$id$ - the ID of the serial port",
|
||||
[[$timeout (optional)$ - timeout of the receive operation, can be either $uart.NO_TIMEOUT$ or 0 for non-blocking operation, $uart.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the timeout in microseconds (in this case, the $timer_id$ parameter is also required). The default
|
||||
value of this argument is $uart.INF_TIMEOUT$]],
|
||||
[[$timer_id (optional)$ - the ID of the timer for the receive operation, needed if the $timeout$ parameter specifies an actual timeout (that is,
|
||||
$timeout$ is neither $uart.NO_TIMEOUT$, nor $uart.INF_TIMEOUT$).]]
|
||||
[[$timeout (optional)$ - timeout of the operation, can be either $uart.NO_TIMEOUT$ or 0 for non-blocking operation, $uart.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $uart.INF_TIMEOUT$.]],
|
||||
[[$timer_id (optional)$ - the ID of the timer used for measuring the timeout. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
|
||||
},
|
||||
ret = "The character read from the serial port as a string, or the empty string it timeout occured while waiting for the character."
|
||||
},
|
||||
@ -79,10 +77,9 @@ $timeout$ is neither $uart.NO_TIMEOUT$, nor $uart.INF_TIMEOUT$).]]
|
||||
<li>$'*s'$ - read until a spacing character (like a space or a TAB) is found (the spacing character is not returned) or a timeout occurs.</li>
|
||||
<li>$a positive number$ - read at most this many characters before returning (reading can stop earlier if a timeout occurs).</li>
|
||||
</ul>]],
|
||||
[[$timeout (optional)$ - timeout of the receive operation, can be either $uart.NO_TIMEOUT$ or 0 for non-blocking operation, $uart.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the inter-char timeout in microseconds (in this case, the $timer_id$ parameter is also required). The default value of this argument is $uart.INF_TIMEOUT$]],
|
||||
[[$timer_id (optional)$ - the ID of the timer for the receive operation, needed if the $timeout$ parameter specifies an actual timeout (that is,
|
||||
$timeout$ is neither $uart.NO_TIMEOUT$, nor $uart.INF_TIMEOUT$).]]
|
||||
[[$timeout (optional)$ - timeout of the operation, can be either $uart.NO_TIMEOUT$ or 0 for non-blocking operation, $uart.INF_TIMEOUT$ for
|
||||
blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $uart.INF_TIMEOUT$.]],
|
||||
[[$timer_id (optional)$ - the ID of the timer used for measuring the timeout. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
|
||||
},
|
||||
ret = [[The data read from the serial port as a string (or as a number if $format$ is $'*n'$). If a timeout occures, only the data read before the timeout is returned. If the function times out while trying to read the first character, the empty string is returned]]
|
||||
},
|
||||
|
88
doc/eluadoc/refman_ps_mizar32_lcd.lua
Normal file
88
doc/eluadoc/refman_ps_mizar32_lcd.lua
Normal file
@ -0,0 +1,88 @@
|
||||
-- eLaa reference manual - platform data
|
||||
|
||||
data_en =
|
||||
{
|
||||
|
||||
-- Title
|
||||
title = "eLua reference manual - Mizar32 LCD module",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "lcd",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions to drive the two-line character LCD panel of the Mizar32 display module.</p>
|
||||
<p>Physically, the display has 16 characters per line but internally it has a 40 characters by two line memory. It displays 16 of those 40 columns at a time, with various ways to determine which of the 40 columns appear in the 16-column display. If you just want to display 16x2 characters, the $reset$, $goto$ and $print$ functions are enough to do this.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#mizar32.lcd.reset#()",
|
||||
desc = "Initialises the display, resetting everything to as initial state: clear screen, no cursor, displaying columns 1-16 of the 40-column memory, ready to print at (1,1), writing text from left to right and moving the cursor one place right after each character. You don't %have% to call $reset$ at the start of your program, but doing so does will ensure that your program still works if the display has been left in a funny state by some previous run."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.setup#( display_shift, right_to_left )",
|
||||
desc = "This can be used to set some of the stranger operating modes of the LCD display. Both parameters are optional and if you omit them, they default to $false$, which sets sensible mode.",
|
||||
args =
|
||||
{
|
||||
[[$display_shift$ - If $true$, then with each character you subsequently print, the cursor will move by one place in the character memory as usual but the display's contents will also move by one position horizontally so that the cursor remains in the same column of the physical display. This can be used to achieve "scrolling text" effects. Note, however, that when the cursor passes from column 40 to column 1 or vice versa, it flips over to the other row.]],
|
||||
"$right_to_left$ - If $true$, text will be printed right-to-left: the cursor will move one position to the left in the character memory and, if display shifting is also enabled, the display will shift so as to keep the cursor in the same column on the screen."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.clear#()",
|
||||
desc = "Clears the display, move the cursor to the top left (position 1,1) and reset the display shift to show columns 1-16."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.home#()",
|
||||
desc = "Moves the cursor to the top left (position 1,1) and reset the display shift."
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.goto#( row, column )",
|
||||
desc = "Move the cursor to the specified row and column.",
|
||||
args =
|
||||
{
|
||||
"$row$ - A number (1 or 2) giving the row you want to move to.",
|
||||
"$column$ - A number (1 to 40) giving the position within that row in the character memory."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.print#( [data1] [, data2] ... [datan] )",
|
||||
desc = "Writes into the LCD character memory starting at the current cursor position. The cursor will advance by one position for each character printed. When it goes past column 40, it moves to column 1 of the other line, (and vice versa when printing right-to-left).",
|
||||
args =
|
||||
{
|
||||
"$data$ - Each item of data can be a string or an integer. Strings are the normal way to display messages of ASCII text. An integer parameter should have a value from 0 to 255 to display a single character, which can be one of the user-defined characters 0-7, the regular ASCII characters 32-125 plus 126 and 127 for right- and left-pointing arrows and the chinese, greek and mathematical symbols with codes 160-255."
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.cursor#( what )",
|
||||
desc = "Sets the type of cursor that is displayed at the cursor position or move the cursor left or right.",
|
||||
args =
|
||||
{
|
||||
[[$what$ - A string to say what should be done:
|
||||
<p>$"none"$, $"line"$ or $"block"$ will display, respectively, no visible cursor, a constant underline or a blinking solid block at the cursor position.
|
||||
<p>$"left"$ or $"right"$ move the cursor one position left or right in the character memory and on the display without changing the underlying characters. The display never shifts in this case and, as usual, the cursor wraps between column 40 of one row and column 1 of the other.]]
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.display#( what )",
|
||||
desc = "Turns the physical display on or off, or shifts the displayed characters left or right.",
|
||||
args =
|
||||
{
|
||||
[[$what$ - A string to say what should be done:
|
||||
<p>$"off"$ and $"on"$ turn the physical display off or back on again. While the display is off it appears blank but the contents of the character memory, the position and type of cursor, user-defined characters and setup mode are all remembered and you can write to the character memory and perform all other operations while the display is off. This allows you to update the display without the viewer seeing too much flickering.
|
||||
<p>$"left"$ or $"right"$ shift the displayed characters one place left or right. For example, if it was displaying the usual columns 1-16 and you say %mizar32.lcd.display("left")%, it will then display columns 2-17: the visible characters move left but the window onto the character memory moves right. ]],
|
||||
}
|
||||
},
|
||||
|
||||
{ sig = "#mizar32.lcd.definechar#( code, glyph )",
|
||||
desc = "Programs one of the eight user-definable characters whose codes are 0 to 7. When it has been defined, a character can be displayed using $mizar32.lcd.print(n)$, where $n$ is a number from 0 to 7. If the character in question is already being displayed, its visible form will change immediately on the display. At power-on, the 8 characters are defined as random garbage.",
|
||||
args =
|
||||
{
|
||||
"$code$ - A number (0 to 7) saying which of the characters you wish to redefine.",
|
||||
"$glyph$ - A table of up to eight numbers giving the bit-patterns for the eight rows of the character, in order from top to bottom. Each of these number is a value from 0 to 31, to define which of the 5 bits in the row should be black. The pixels' values from left to right are 16, 8, 4, 2 and 1. For example, { 1, 3, 7, 15, 31, 15, 7, 3, 1, 0 } would define a left-pointing solid triangle in the top 7 rows. Extra rows are ignored, and missing rows are blanked."
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
@ -10,7 +10,7 @@ data_en =
|
||||
menu_name = "pio",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions for accesing the particular features of the PIO subsystem of the STR9 family of CPUs. This subsystem is very flexible, allowing things like
|
||||
overview = [[This module contains functions for accessing the particular features of the PIO subsystem of the STR9 family of CPUs. This subsystem is very flexible, allowing things like
|
||||
configurable output types (push-pull or open collector), multiple alternate functions for the PIO pins, and others. For a full description of the STR9 PIO module check the STR9 CPU
|
||||
Reference manual, available from ST at @http://www.st.com/mcu/devicedocs-STR912FAW44-101.html@this address@. Note that this module is a supplement of the platform independent
|
||||
@refman_gen_pio.html@pio@ module, not a replacement. Use this module only for setting up the STR9 PIO pins, and the @refman_gen_pio.html@pio@ module for all the other PIO related operations.]],
|
||||
|
@ -1,60 +0,0 @@
|
||||
-- eLua reference manual - str9 platform specific rtc - Real Time Clock - data
|
||||
|
||||
data_en =
|
||||
{
|
||||
|
||||
-- Title
|
||||
title = "eLua reference manual - STR9 rtc module",
|
||||
|
||||
-- Menu name
|
||||
menu_name = "rtc",
|
||||
|
||||
-- Overview
|
||||
overview = [[This module contains functions for accesing the particular features of the RTC - Real Time Clock - subsystem of the STR9 family of CPUs.
|
||||
This internal subsystem offers functions to keep track of a real time clock calendar, as well as some other features like alarms and auxiliar functions.
|
||||
Reference manual, available from ST at @http://www.st.com/mcu/devicedocs-STR912FAW44-101.html@this address@.]],
|
||||
|
||||
-- Functions
|
||||
funcs =
|
||||
{
|
||||
{ sig = "#str9.rtc.settime#( time )",
|
||||
desc = "Sets the Real Time Clock time to a specific time of the day.",
|
||||
args =
|
||||
{
|
||||
"$time$ - a string in the format 'hh:mm:ss' or a Lua table with 'hour', 'min' and 'sec' string fields.",
|
||||
},
|
||||
ret = "nothing.",
|
||||
ex = 'str9.settime("14:25:00") - Sets the RTC time to 14 hour 25 minutes, 2:25 PM',
|
||||
},
|
||||
{ sig = "#str9.rtc.gettime#( format )",
|
||||
desc = "Gets the time kept by the Real Time Clock.",
|
||||
args =
|
||||
{
|
||||
"$format$ - the string '*s' to return the time as a string 'hh:mm:ss' or '*t' to return as a Lua table with string fields 'hour', 'min' and 'sec'.",
|
||||
},
|
||||
ret = "a string or a Lua table, according to the format argument.",
|
||||
ex = 'now = str9.rtc.gettime( "*s" ) - now receives a sting like "14:25:05", now = str9.rtc.gettime( "*t" ) - now receives the Lua table { hour = 14, min = 25, sec = 05 }',
|
||||
},
|
||||
{ sig = "#str9.rtc.setdate#( date )",
|
||||
desc = "Sets the Real Time Clock date to a specific date.",
|
||||
args =
|
||||
{
|
||||
"$date$ - a string in the format 'dd/mm/yyyy' or a Lua table with 'day', 'month' and 'year' string fields.",
|
||||
},
|
||||
ret = "nothing.",
|
||||
ex = 'str9.rtc.setdate( "31/08/1960" ) - set the RTC date to August 31st 1960',
|
||||
},
|
||||
{ sig = "#str9.rtc.getdate#( format )",
|
||||
desc = "Gets the date kept by the Real Time Clock.",
|
||||
args =
|
||||
{
|
||||
"$format$ - the string '*s' to return the date as a string 'dd/mm/yyyy' or '*t' to return as a Lua table with string fields 'day', 'month' and 'year'.",
|
||||
},
|
||||
ret = "a string or a Lua table, according to the format argument.",
|
||||
ex = 'today = str9.rtc.getdate( "*s" ) - today receives a string like "14/12/2010", meaning December 14th of 2010, today = str9.rtc.getdate( "*t" ) - today receives the Lua table { day = 14, month = 12, year = 2010 }',
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
data_pt = data_en
|
@ -15,7 +15,7 @@ typedef void ( *p_std_send_char )( int fd, char c );
|
||||
typedef int ( *p_std_get_char )( s32 to );
|
||||
</code></pre>
|
||||
<p>(the <b>send</b> function gets an additional <b>fd</b> parameter that you can use to differentiate between the standard C stdout and stderr output streams).</p>
|
||||
<p>To set them, use <b>std_set_send_func</b> and <b>std_set_get_func</b>, both are defined in <i>inc/newlib/getstd.h</i>. Usually they are called from <i>src/common.c</i> and configured to work
|
||||
<p>To set them, use <b>std_set_send_func</b> and <b>std_set_get_func</b>, both are defined in <i>inc/newlib/genstd.h</i>. Usually they are called from <i>src/common.c</i> and configured to work
|
||||
over the UART by default:</p>
|
||||
<pre><code>// *****************************************************************************
|
||||
// std functions and platform initialization
|
||||
|
@ -9,7 +9,7 @@ $$HEADER$$
|
||||
0, PORTB will have 1 and so on. Similarly, the second SPI interface (SPI1) of the MCU will probably have an id equal to 1. However, this is not a strict
|
||||
rule. The implementation of the platform interface might choose to expose only some of the peripherals (components) of the MCU, thus this rule might be
|
||||
broken. For example, if a board has 3 UARTs, but for some reason the second UART (UART1) is dedicated and can't be touched by <b>eLua</b>, then UART0 will have the id 0 and UART2 will
|
||||
have the id 1, so UART1 won't ever be accesible to the code. </p>
|
||||
have the id 1, so UART1 won't ever be accessible to the code. </p>
|
||||
<p>With some exceptions (most notably the low-level support functions), the different modules supported by the platform interface are
|
||||
mirrored more or less accurately in separate Lua modules that can be used directly from <b>eLua</b>. Check the reference manual for a
|
||||
complete description of these modules.</p>
|
||||
|
@ -22,7 +22,7 @@ You need to define the following macros for RFS:
|
||||
| RFS_BUFFER_SIZE | Size of the RFS buffer. Needs to be one of the *BUF_SIZE_xxx* constants defined in _inc/buf.h_
|
||||
| RFS_UART_ID | The ID of the UART that will be used by RFS. This is the physical connection over which the PC directory will be shared.
|
||||
| RFS_UART_SPEED | Communication speed of the RFS UART interface.
|
||||
| RFS_TIMER_ID | The ID of a timer that will be used by RFS for internal operations
|
||||
| RFS_TIMER_ID | The ID of a timer that will be used by RFS for internal operations. If not specified it defaults to the link:arch_platform_timers.html#the_system_timer[system timer].
|
||||
| RFS_FLOW_TYPE | Flow control type on the serial RFS interface, see link:arch_platform_uart.html#flow_control_type[here] for details.
|
||||
If not specified it defaults to \'no flow control'.
|
||||
| RFS_TIMEOUT | RFS operations timeout (in microseconds). If during a RFS operation no data is received from the PC side for the
|
||||
|
@ -68,7 +68,7 @@ $$HEADER$$
|
||||
(see <a href="using.html#cross">here</a> for details on cross compilation and its benefits) and the result is written in the <b>eLua</b> binary image. This option
|
||||
might decrease or increase the physical size of the ROMFS image, but its real benefits are increased speed (because <b>eLua</b> doesn't need to compile the Lua
|
||||
code to bytecode first) and decreased RAM consumption (the Lua parser might get quite memory-hungry at times, which in turn might lead to stack overflows and very
|
||||
hard to find bugs). </li>
|
||||
hard to find bugs). <b>NOTE</b>: this option is not available if eLua is compiled in 64-bit integer only mode (lualonglong).</li>
|
||||
</ul>
|
||||
<p>See <a href="building.html#buildoptions">here</a> for instructions on how to specify the ROMFS compilation mode.</p>
|
||||
$$FOOTER$$
|
||||
|
@ -31,7 +31,7 @@ stack. These are the services provided by the TCP/IP stack:</p>
|
||||
be used instead. To use only the static configuration (and make the eLua image
|
||||
size a bit smaller) don't define the BUILD_DHCPC client.</p></li>
|
||||
|
||||
<li><b>#define BUILD_DNSM</b> if you want support for the DNS server.</li>
|
||||
<li><b>#define BUILD_DNS</b> if you want support for the DNS server.</li>
|
||||
<li><b>#define BUILD_CON_TCP</b> if you want support for shell over telnet instead of
|
||||
serial. Note that you must NOT define <b>BUILD_CON_GENERIC</b> in this case (see
|
||||
<a href="arch_con_term.html">here</a> for details).</li>
|
||||
@ -48,8 +48,8 @@ you have a list of parameters that you might want to change:</p>
|
||||
but doing so when you have to transfer large amounts of data will slow the transfer speed. 1k seems to be a good compromise.</li>
|
||||
<li><b>UIP_CONF_UDP</b>: turn off UDP support. While <b>eLua</b> doesn't have support for UDP via its <b>net</b> module at this time, UDP can still
|
||||
be used (for example by DNS/DHCP), so be careful if you disable this.</li>
|
||||
<li><b>ELUA_DHCP_TIMER_ID</b>: the timer ID used for the TCP/IP subsystem. Note that this should be a dedicated timer, not available to the rest
|
||||
of the system (or available in "read-only" mode).</li>
|
||||
<li><b>ELUA_DHCP_TIMER_ID</b>: the timer ID used for the TCP/IP subsystem. If not specified it defaults to the link:arch_platform_timers.html#the_system_timer[system timer].
|
||||
If the system timer is <b>not</b> used, please note that this should be a dedicated timer, not available to the rest of the system (or available in "read-only" mode). </li>
|
||||
</ul>
|
||||
<br />
|
||||
|
||||
|
@ -101,3 +101,5 @@ _mmbedpio=link:refman_ps_mbed_pio.html[mbed.pio]
|
||||
|
||||
# Miscellaneous
|
||||
_br=<br />
|
||||
_systmr=link:arch_platform_timers.html#the_system_timer[system timer]
|
||||
_virttmr=link:arch_platform_timers.html#virtual_timers[virtual timers]
|
||||
|
@ -76,7 +76,7 @@ o|BUILD_MMCFS |Enable the eLua SD/MMC FAT filesystem support. To enable:
|
||||
|
||||
#define BUILD_MMCFS
|
||||
|
||||
xref:static[Static configuration data dependencies]: *MMCFS_TICK_HZ, MMCFS_TICK_MS, MMCFS_CS_PORT, MMCFS_CS_PIN, MMCFS_SPI_NUM*
|
||||
xref:static[Static configuration data dependencies]: *MMCFS_CS_PORT, MMCFS_CS_PIN, MMCFS_SPI_NUM*
|
||||
|
||||
o|BUILD_TERM |Enable ANSI terminal support. It allows eLua to interact with terminals that support ANSI escape sequences
|
||||
(more details link:arch_con_term.html[here]). Currently it works only over RS-232 connections, although this is not a strict requirement.
|
||||
@ -210,7 +210,8 @@ o|CON_UART_ID +
|
||||
CON_UART_SPEED +
|
||||
CON_TIMER_ID +
|
||||
CON_FLOW_TYPE |Used to configure console input/output over UART. The specified UART id will be used for console input/output, at the
|
||||
specified speed. The data format is always 8N1 (8 data bits, no parity, 1 stop bits)t. The specified timer ID will be used for the console subsystem. These
|
||||
specified speed. The data format is always 8N1 (8 data bits, no parity, 1 stop bits)t. The specified timer ID will be used for the console subsystem (if
|
||||
not specified it defaults to the link:arch_platform_timers.html#the_system_timer[system timer]). These
|
||||
variables are also used by the XMODEM and TERM implementations. If CON_FLOW_TYPE is defined the specified flow control is applied to the console UART
|
||||
interface (see link:arch_platform_uart.html#platform_uart_set_flow_control[this link] to find out how to specify the flow control). If not defined it
|
||||
defaults to no flow control.
|
||||
@ -229,10 +230,6 @@ o|VTMR_NUM_TIMERS +
|
||||
VTMR_FREQ_HZ |Specify the virtual timers configuration for the platform (refer to link:refman_gen_tmr.html[the timer module documentation] for details). Define VTMR_NUM_TIMERS to 0
|
||||
if this feature is not used.
|
||||
|
||||
o|MMCFS_TICK_HZ +
|
||||
MMCFS_TICK_MS |Specify the rate at which SD/MMC timer function _disk_timerproc()_ are being called by the platform. On most platforms MMCFS_TICK_HZ will match VTMR_FREQ_HZ.
|
||||
Only needed if MMCFS support is enabled.
|
||||
|
||||
o|MMCFS_CS_PORT +
|
||||
MMCFS_CS_PIN |Specify the port and pin to be used as chip select for MMCFS control of an SD/MMC card over SPI. Only needed if MMCFS support is enabled.
|
||||
|
||||
@ -265,6 +262,7 @@ value that can be returned by the ADC.
|
||||
o|RPC_UART_ID |If the link:refman_gen_rpc.html[rpc module] is enabled and boot mode is set to luarpc, this selects which uart luarpc will listen on for incoming client connections.
|
||||
|
||||
o|RPC_TIMER_ID |If the link:refman_gen_rpc.html[rpc module] is enabled and boot mode is set to luarpc, this selects which timer will be used with the uart selected with RPC_UART_ID.
|
||||
If not specified it defaults to the link:arch_platform_timers.html#the_system_timer[system timer].
|
||||
|
||||
o|EGC_INITIAL_MODE +
|
||||
EGC_INITIAL_MEMLIMIT |**(version 0.7 or above)**Configure the default (compile time) operation mode and memory limit of the emergency garbage collector link:elua_egc.html[here] for details
|
||||
@ -284,7 +282,7 @@ by this macro. Check link:linenoise.html[here] for details. This macro is option
|
||||
o|RFS_BUFFER_SIZE |Size of the RFS buffer. Needs to be one of the *BUF_SIZE_xxx* constants defined in _inc/buf.h_
|
||||
o|RFS_UART_ID |The ID of the UART that will be used by RFS. This is the physical connection over which the PC directory will be shared.
|
||||
o|RFS_UART_SPEED |Communication speed of the RFS UART interface.
|
||||
o|RFS_TIMER_ID |The ID of a timer that will be used by RFS for internal operations
|
||||
o|RFS_TIMER_ID |The ID of a timer that will be used by RFS for internal operations. If not specified it defaults to the link:arch_platform_timers.html#the_system_timer[system timer].
|
||||
o|RFS_FLOW_TYPE |Flow control type on the serial RFS interface, see link:arch_platform_uart.html#flow_control_type[here] for details.
|
||||
If not specified it defaults to \'no flow control'.
|
||||
o|RFS_TIMEOUT |RFS operations timeout (in microseconds). If during a RFS operation no data is received from the PC side for the
|
||||
@ -315,7 +313,7 @@ to modify them, so don't worry about the apparent complexity. The examples at th
|
||||
|
||||
------------------------------------
|
||||
$ scons
|
||||
[target=lua | lualong]
|
||||
[target=lua | lualong | lualonglong]
|
||||
[cpu=<cpuname>]
|
||||
[board=<boardname>]
|
||||
[cpumode=arm | thumb]
|
||||
@ -336,8 +334,9 @@ one CPU. This allows the build system to be very flexible. You can use these two
|
||||
For board/CPU assignment, look at the beginning of the SConstruct file (the _platform_list_), it's self-explanatory. +
|
||||
The other options are as follows:
|
||||
|
||||
* **target=lua | lualong**: specify if you want to build "regular" Lua (with floating point support) or integer only Lua (lualong). The default is "lua". "lualong" runs faster on
|
||||
targets that don't have a floating point co-processor, but it completely lacks support for floating point operations, it can only handle integers.
|
||||
* **target=lua | lualong | lualonglong**: specify if you want to build "regular" Lua (with floating point support). 32 bit integer only Lua (lualong) or 64 bit integer only Lua (lualonglong,
|
||||
starting with version 0.9). The default is "lua". "lualong" and "lualonglong" run faster on targets that don't have a floating point co-processor, but they completely lack support for floating
|
||||
point operations, they can only handle integers. Also, "lualonglong" doesn't support cross-compilation of Lua source files to bytecode (check link:arch_romfs.html#mode[here] for details).
|
||||
|
||||
* **cpumode=arm | thumb**: for ARM targets (not Cortex) this specifies the compilation mode. Its default value is 'thumb' for AT91SAM7X targets and 'arm' for STR9, LPC2888 and LPC2468 targets.
|
||||
|
||||
|
@ -5,7 +5,7 @@ $$HEADER$$
|
||||
<li><b>the ROM file system</b>: a very simple, very low footprint read-only file system that can be included in the <b>eLua</b> binary image. Check <a href="arch_romfs.html">here</a> for details.</li>
|
||||
<li><b>the FAT file system</b>: a read-write FAT file system implementation (platform independent) that can currently be used with SD/MMC memory cards. Check <a href="fatfs.html">here</a> for
|
||||
details. <b>(new in 0.7)</b></li>
|
||||
<li><b>the remote file system (RFS)</b>: a read-write file system that allows eLua to 'share' a directory on a PC, effectively accesing
|
||||
<li><b>the remote file system (RFS)</b>: a read-write file system that allows eLua to 'share' a directory on a PC, effectively accessing
|
||||
its contents as if it was a local file system. Check <a href="arch_rfs.html">here</a> for details. <b>(new in 0.8)</b></li>
|
||||
</ul>
|
||||
$$FOOTER$$
|
||||
|
5
doc/en/modules_mizar32.txt
Normal file
5
doc/en/modules_mizar32.txt
Normal file
@ -0,0 +1,5 @@
|
||||
$$HEADER$$
|
||||
<h3>Reference manual - Mizar32 platform dependent modules</h3>
|
||||
<p>This paragraph presents all the modules specific to the <a href="status.html">Mizar32</a> platform.</p>
|
||||
$$FOOTER$$
|
||||
|
@ -59,7 +59,7 @@ install it, then open the com0com serial port manager to create your virtual
|
||||
serial port pairs. Then give it a little spin to get used to how it works. Supposing
|
||||
that you created COM10 and COM11 as a virtual serial port pair, try this:
|
||||
|
||||
- start your terminal emulator program. My preffered terminal emulator program in
|
||||
- start your terminal emulator program. My preferred terminal emulator program in
|
||||
Windows is http://www.ayera.com/teraterm/[TeraTerm], but you can use any emulator
|
||||
you want. Open COM10 at baud 115200.
|
||||
- start another instance of the terminal emulator, but this time open COM11 at baud 115200.
|
||||
|
@ -43,6 +43,27 @@ The list of CPUs and boards currently supported by eLua is given below:
|
||||
| _I386 | x86 o| i386 | PCs/emulators | _sok
|
||||
|=====================================================================================
|
||||
|
||||
[[systmr]]
|
||||
System timer support
|
||||
--------------------
|
||||
The table below shows the status of _systmr implementation on all eLua platforms.
|
||||
|
||||
[width="70%", cols="<1, ^4", options="header"]
|
||||
|============================================
|
||||
^| Platform ^| System timer support
|
||||
| AT91SAM7x o| yes
|
||||
| AVR32 o| yes
|
||||
| i386 o| no
|
||||
| LM3S o| yes
|
||||
| LPC17xx o| yes
|
||||
| LPC24xx o| yes
|
||||
| LPC288x o| no
|
||||
| SIM o| yes
|
||||
| STM32 o| yes
|
||||
| STR7 o| no
|
||||
| STR9 o| yes
|
||||
|============================================
|
||||
|
||||
[[plat_modules]]
|
||||
eLua modules x MCUs
|
||||
-------------------
|
||||
|
14
inc/common.h
14
inc/common.h
@ -4,9 +4,12 @@
|
||||
#define __COMMON_H__
|
||||
|
||||
#include "elua_int.h"
|
||||
#include "lua.h"
|
||||
#include "platform.h"
|
||||
|
||||
// Virtual timers data
|
||||
#define VTMR_FIRST_ID ( 32 )
|
||||
// VTMR_FIRST_ID must be LARGER than PLATFORM_TIMER_SYS_ID (as declared in platform.h)
|
||||
#define VTMR_FIRST_ID ( 0x200 )
|
||||
#define VTMR_GET_ID( x ) ( ( x ) - VTMR_FIRST_ID )
|
||||
#define TIMER_IS_VIRTUAL( x ) ( ( VTMR_NUM_TIMERS > 0 ) && ( ( x ) >= VTMR_FIRST_ID ) && ( ( x ) < VTMR_NUM_TIMERS + VTMR_FIRST_ID ) )
|
||||
|
||||
@ -18,9 +21,18 @@ void cmn_int_handler( elua_int_id id, elua_int_resnum resnum );
|
||||
int cmn_tmr_int_set_status( elua_int_resnum resnum, int status );
|
||||
int cmn_tmr_int_get_status( elua_int_resnum resnum );
|
||||
int cmn_tmr_int_get_flag( elua_int_resnum resnum, int clear );
|
||||
// System timer generic implemenation
|
||||
void cmn_systimer_set_base_freq( u32 freq_hz );
|
||||
void cmn_systimer_set_interrupt_freq( u32 freq_hz );
|
||||
void cmn_systimer_set_interrupt_period_us( u32 period );
|
||||
void cmn_systimer_periodic();
|
||||
timer_data_type cmn_systimer_get();
|
||||
|
||||
void cmn_uart_setup_sermux();
|
||||
|
||||
unsigned int intlog2( unsigned int v );
|
||||
const char* cmn_str64( u64 x );
|
||||
void cmn_get_timeout_data( lua_State *L, int pidx, timer_data_type *ptimeout, unsigned *pid );
|
||||
|
||||
#endif // #ifndef __COMMON_H__
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
#define BUILD_RPC
|
||||
#define LUARPC_ENABLE_SERIAL
|
||||
|
||||
#define LUA_PLATFORM_LIBS_REG \
|
||||
{LUA_OSLIBNAME, luaopen_os}
|
||||
|
||||
#define LUA_PLATFORM_LIBS_ROM \
|
||||
_ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )\
|
||||
_ROM( AUXLIB_BITARRAY, luaopen_bitarray, bitarray_map )\
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "type.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
|
||||
// eLua network typedefs
|
||||
typedef s16 elua_net_size;
|
||||
@ -40,10 +41,10 @@ typedef union
|
||||
// eLua TCP/IP functions
|
||||
int elua_net_socket( int type );
|
||||
int elua_net_close( int s );
|
||||
elua_net_size elua_net_recvbuf( int s, luaL_Buffer *buf, elua_net_size maxsize, s16 readto, unsigned timer_id, u32 to_us );
|
||||
elua_net_size elua_net_recv( int s, void *buf, elua_net_size maxsize, s16 readto, unsigned timer_id, u32 to_us );
|
||||
elua_net_size elua_net_recvbuf( int s, luaL_Buffer *buf, elua_net_size maxsize, s16 readto, unsigned timer_id, timer_data_type to_us );
|
||||
elua_net_size elua_net_recv( int s, void *buf, elua_net_size maxsize, s16 readto, unsigned timer_id, timer_data_type to_us );
|
||||
elua_net_size elua_net_send( int s, const void* buf, elua_net_size len );
|
||||
int elua_accept( u16 port, unsigned timer_id, u32 to_us, elua_net_ip* pfrom );
|
||||
int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip* pfrom );
|
||||
int elua_net_connect( int s, elua_net_ip addr, u16 port );
|
||||
elua_net_ip elua_net_lookup( const char* hostname );
|
||||
|
||||
|
56
inc/linenoise_posix.h
Normal file
56
inc/linenoise_posix.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* linenoise.h -- guerrilla line editing library against the idea that a
|
||||
* line editing lib needs to be 20,000 lines of C code.
|
||||
*
|
||||
* See linenoise.c for more information.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __LINENOISE_H
|
||||
#define __LINENOISE_H
|
||||
|
||||
typedef struct linenoiseCompletions {
|
||||
size_t len;
|
||||
char **cvec;
|
||||
} linenoiseCompletions;
|
||||
|
||||
typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *);
|
||||
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *);
|
||||
void linenoiseAddCompletion(linenoiseCompletions *, char *);
|
||||
|
||||
char *linenoise(const char *prompt);
|
||||
int linenoiseHistoryAdd(const char *line);
|
||||
int linenoiseHistorySetMaxLen(int len);
|
||||
int linenoiseHistorySave(char *filename);
|
||||
int linenoiseHistoryLoad(char *filename);
|
||||
void linenoiseClearScreen(void);
|
||||
|
||||
#endif /* __LINENOISE_H */
|
@ -67,7 +67,7 @@ enum exception_type { done, nonfatal, fatal };
|
||||
|
||||
struct exception {
|
||||
enum exception_type type;
|
||||
int errnum;
|
||||
int errnum;
|
||||
};
|
||||
|
||||
define_exception_type(struct exception);
|
||||
@ -113,7 +113,7 @@ typedef struct _ServerHandle ServerHandle;
|
||||
struct _ServerHandle {
|
||||
Transport ltpt; // listening transport, always valid if no error
|
||||
Transport atpt; // accepting transport, valid if connection established
|
||||
int link_errs;
|
||||
int link_errs;
|
||||
};
|
||||
|
||||
|
||||
@ -125,12 +125,12 @@ struct _ServerHandle {
|
||||
#endif
|
||||
|
||||
#define TRANSPORT_VERIFY_OPEN \
|
||||
if (tpt->fd == INVALID_TRANSPORT) \
|
||||
{ \
|
||||
e.errnum = ERR_CLOSED; \
|
||||
e.type = fatal; \
|
||||
Throw( e ); \
|
||||
}
|
||||
if (tpt->fd == INVALID_TRANSPORT) \
|
||||
{ \
|
||||
e.errnum = ERR_CLOSED; \
|
||||
e.type = fatal; \
|
||||
Throw( e ); \
|
||||
}
|
||||
|
||||
// Arg & Error Checking Provided to Transport Mechanisms
|
||||
int check_num_args (lua_State *L, int desired_n);
|
||||
@ -156,11 +156,11 @@ void transport_read_buffer (Transport *tpt, u8 *buffer, int length);
|
||||
void transport_write_buffer (Transport *tpt, const u8 *buffer, int length);
|
||||
|
||||
// Check if data is available on connection without reading:
|
||||
// - 1 = data available, 0 = no data available
|
||||
// - 1 = data available, 0 = no data available
|
||||
int transport_readable (Transport *tpt);
|
||||
|
||||
// Check if transport is open:
|
||||
// - 1 = connection open, 0 = connection closed
|
||||
// - 1 = connection open, 0 = connection closed
|
||||
int transport_is_open (Transport *tpt);
|
||||
|
||||
// Shut down connection
|
||||
|
@ -10,12 +10,12 @@
|
||||
// STD device name (for devman)
|
||||
#define STD_DEV_NAME "/std"
|
||||
|
||||
#define STD_INFINITE_TIMEOUT PLATFORM_UART_INFINITE_TIMEOUT
|
||||
#define STD_INFINITE_TIMEOUT PLATFORM_TIMER_INF_TIMEOUT
|
||||
#define STD_INTER_CHAR_TIMEOUT 10000
|
||||
|
||||
// Send/receive function types
|
||||
typedef void ( *p_std_send_char )( int fd, char c );
|
||||
typedef int ( *p_std_get_char )( s32 to );
|
||||
typedef int ( *p_std_get_char )( timer_data_type to );
|
||||
|
||||
// STD functions
|
||||
void std_set_send_func( p_std_send_char pfunc );
|
||||
|
172
inc/platform.h
172
inc/platform.h
@ -68,6 +68,77 @@ const char* platform_pio_get_prefix( unsigned port );
|
||||
int platform_pio_has_pin( unsigned port, unsigned pin );
|
||||
pio_type platform_pio_op( unsigned port, pio_type pinmask, int op );
|
||||
|
||||
// *****************************************************************************
|
||||
// Timer subsection
|
||||
|
||||
// The ID of the system timer
|
||||
#define PLATFORM_TIMER_SYS_ID 0x100
|
||||
|
||||
#if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
|
||||
// Maximum values of the system timer
|
||||
#define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 32 ) - 2 )
|
||||
// Timer data type
|
||||
typedef u32 timer_data_type;
|
||||
#else
|
||||
// Maximum values of the system timer
|
||||
#define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 52 ) - 2 )
|
||||
// Timer data type
|
||||
typedef u64 timer_data_type;
|
||||
#endif // #if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
|
||||
|
||||
// This constant means 'infinite timeout'
|
||||
#define PLATFORM_TIMER_INF_TIMEOUT ( PLATFORM_TIMER_SYS_MAX + 1 )
|
||||
|
||||
// System timer frequency
|
||||
#define PLATFORM_TIMER_SYS_FREQ 1000000
|
||||
|
||||
// Interrupt types
|
||||
#define PLATFORM_TIMER_INT_ONESHOT 1
|
||||
#define PLATFORM_TIMER_INT_CYCLIC 2
|
||||
|
||||
// Match interrupt error codes
|
||||
#define PLATFORM_TIMER_INT_OK 0
|
||||
#define PLATFORM_TIMER_INT_TOO_SHORT 1
|
||||
#define PLATFORM_TIMER_INT_TOO_LONG 2
|
||||
#define PLATFORM_TIMER_INT_INVALID_ID 3
|
||||
|
||||
// Timer operations
|
||||
enum
|
||||
{
|
||||
PLATFORM_TIMER_OP_START,
|
||||
PLATFORM_TIMER_OP_READ,
|
||||
PLATFORM_TIMER_OP_SET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_MAX_DELAY,
|
||||
PLATFORM_TIMER_OP_GET_MIN_DELAY,
|
||||
PLATFORM_TIMER_OP_GET_MAX_CNT
|
||||
};
|
||||
|
||||
// The platform timer functions
|
||||
int platform_timer_exists( unsigned id );
|
||||
void platform_timer_delay( unsigned id, timer_data_type delay_us );
|
||||
void platform_s_timer_delay( unsigned id, timer_data_type delay_us );
|
||||
timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data );
|
||||
timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data );
|
||||
int platform_timer_set_match_int( unsigned id, timer_data_type period_us, int type );
|
||||
int platform_s_timer_set_match_int( unsigned id, timer_data_type period_us, int type );
|
||||
timer_data_type platform_timer_get_diff_us( unsigned id, timer_data_type end, timer_data_type start );
|
||||
// System timer functions
|
||||
timer_data_type platform_timer_read_sys();
|
||||
int platform_timer_sys_available();
|
||||
// The next 3 functions need to be implemented only if the generic system timer mechanism
|
||||
// (src/common.c:cmn_systimer*) is used by the backend
|
||||
u64 platform_timer_sys_raw_read();
|
||||
void platform_timer_sys_enable_int();
|
||||
void platform_timer_sys_disable_int();
|
||||
|
||||
// Convenience macros
|
||||
#define platform_timer_read( id ) platform_timer_op( id, PLATFORM_TIMER_OP_READ, 0 )
|
||||
#define platform_timer_start( id ) platform_timer_op( id, PLATFORM_TIMER_OP_START, 0 )
|
||||
#define platform_timer_get_diff_crt( id, v ) platform_timer_get_diff_us( id, platform_timer_read( id ), v )
|
||||
#define platform_timer_sys_delay( us ) platform_timer_delay( PLATFORM_TIMER_SYS_ID, us )
|
||||
#define platform_timer_get_max_cnt( id ) platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_CNT, 0 )
|
||||
|
||||
// *****************************************************************************
|
||||
// CAN subsection
|
||||
|
||||
@ -133,9 +204,6 @@ enum
|
||||
PLATFORM_UART_STOPBITS_2
|
||||
};
|
||||
|
||||
// "Infinite timeout" constant for recv
|
||||
#define PLATFORM_UART_INFINITE_TIMEOUT (-1)
|
||||
|
||||
// Flow control types (this is a bit mask, one can specify PLATFORM_UART_FLOW_RTS | PLATFORM_UART_FLOW_CTS )
|
||||
#define PLATFORM_UART_FLOW_NONE 0
|
||||
#define PLATFORM_UART_FLOW_RTS 1
|
||||
@ -147,70 +215,24 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
|
||||
int platform_uart_set_buffer( unsigned id, unsigned size );
|
||||
void platform_uart_send( unsigned id, u8 data );
|
||||
void platform_s_uart_send( unsigned id, u8 data );
|
||||
int platform_uart_recv( unsigned id, unsigned timer_id, s32 timeout );
|
||||
int platform_s_uart_recv( unsigned id, s32 timeout );
|
||||
int platform_uart_recv( unsigned id, unsigned timer_id, timer_data_type timeout );
|
||||
int platform_s_uart_recv( unsigned id, timer_data_type timeout );
|
||||
int platform_uart_set_flow_control( unsigned id, int type );
|
||||
int platform_s_uart_set_flow_control( unsigned id, int type );
|
||||
|
||||
// *****************************************************************************
|
||||
// Timer subsection
|
||||
|
||||
// There are 16 "virtual" timers (TMR0...TMR15)
|
||||
#define PLATFORM_TIMER_TOTAL 16
|
||||
|
||||
// Data types
|
||||
typedef u32 timer_data_type;
|
||||
|
||||
// Interrupt types
|
||||
#define PLATFORM_TIMER_INT_ONESHOT 1
|
||||
#define PLATFORM_TIMER_INT_CYCLIC 2
|
||||
|
||||
// Match interrupt error codes
|
||||
#define PLATFORM_TIMER_INT_OK 0
|
||||
#define PLATFORM_TIMER_INT_TOO_SHORT 1
|
||||
#define PLATFORM_TIMER_INT_TOO_LONG 2
|
||||
#define PLATFORM_TIMER_INT_INVALID_ID 3
|
||||
|
||||
// Timer operations
|
||||
enum
|
||||
{
|
||||
PLATFORM_TIMER_OP_START,
|
||||
PLATFORM_TIMER_OP_READ,
|
||||
PLATFORM_TIMER_OP_SET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_CLOCK,
|
||||
PLATFORM_TIMER_OP_GET_MAX_DELAY,
|
||||
PLATFORM_TIMER_OP_GET_MIN_DELAY
|
||||
};
|
||||
|
||||
// The platform timer functions
|
||||
int platform_timer_exists( unsigned id );
|
||||
void platform_timer_delay( unsigned id, u32 delay_us );
|
||||
void platform_s_timer_delay( unsigned id, u32 delay_us );
|
||||
u32 platform_timer_op( unsigned id, int op, u32 data );
|
||||
u32 platform_s_timer_op( unsigned id, int op, u32 data );
|
||||
int platform_timer_set_match_int( unsigned id, u32 period_us, int type );
|
||||
int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type );
|
||||
u32 platform_timer_get_diff_us( unsigned id, timer_data_type end, timer_data_type start );
|
||||
|
||||
// *****************************************************************************
|
||||
// PWM subsection
|
||||
|
||||
// There are 16 "virtual" PWM channels (PWM0...PWM15)
|
||||
#define PLATFORM_PWM_TOTAL 16
|
||||
|
||||
// PWM operations
|
||||
enum
|
||||
{
|
||||
PLATFORM_PWM_OP_START,
|
||||
PLATFORM_PWM_OP_STOP,
|
||||
PLATFORM_PWM_OP_SET_CLOCK,
|
||||
PLATFORM_PWM_OP_GET_CLOCK
|
||||
};
|
||||
|
||||
// The platform PWM functions
|
||||
int platform_pwm_exists( unsigned id );
|
||||
u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty );
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data );
|
||||
void platform_pwm_start( unsigned id );
|
||||
void platform_pwm_stop( unsigned id );
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 data );
|
||||
u32 platform_pwm_get_clock( unsigned id );
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU specific functions
|
||||
@ -235,27 +257,21 @@ u32 platform_cpu_get_frequency();
|
||||
// *****************************************************************************
|
||||
// The platform ADC functions
|
||||
|
||||
enum
|
||||
{
|
||||
PLATFORM_ADC_GET_MAXVAL,
|
||||
PLATFORM_ADC_SET_SMOOTHING,
|
||||
PLATFORM_ADC_SET_BLOCKING,
|
||||
PLATFORM_ADC_SET_FREERUNNING,
|
||||
PLATFORM_ADC_IS_DONE,
|
||||
PLATFORM_ADC_OP_SET_TIMER,
|
||||
PLATFORM_ADC_OP_SET_CLOCK,
|
||||
};
|
||||
|
||||
// Functions requiring platform-specific implementation
|
||||
int platform_adc_update_sequence();
|
||||
int platform_adc_start_sequence();
|
||||
int platform_adc_update_sequence();
|
||||
int platform_adc_start_sequence();
|
||||
void platform_adc_stop( unsigned id );
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency);
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency);
|
||||
int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
|
||||
|
||||
// ADC Common Functions
|
||||
int platform_adc_exists( unsigned id );
|
||||
int platform_adc_check_timer_id( unsigned id, unsigned timer_id );
|
||||
u32 platform_adc_op( unsigned id, int op, u32 data );
|
||||
int platform_adc_exists( unsigned id );
|
||||
u32 platform_adc_get_maxval( unsigned id );
|
||||
u32 platform_adc_set_smoothing( unsigned id, u32 length );
|
||||
void platform_adc_set_blocking( unsigned id, u32 mode );
|
||||
void platform_adc_set_freerunning( unsigned id, u32 mode );
|
||||
u32 platform_adc_is_done( unsigned id );
|
||||
void platform_adc_set_timer( unsigned id, u32 timer );
|
||||
|
||||
// *****************************************************************************
|
||||
// I2C platform interface
|
||||
@ -290,10 +306,22 @@ u32 platform_eth_get_packet_nb( void* buf, u32 maxlen );
|
||||
void platform_eth_force_interrupt();
|
||||
u32 platform_eth_get_elapsed_time();
|
||||
|
||||
// *****************************************************************************
|
||||
// USB platform interface
|
||||
// NOTE: for now this just supports CDC functionality
|
||||
|
||||
#define CDC_UART_ID 0xB0
|
||||
|
||||
void platform_usb_cdc_send( u8 data );
|
||||
int platform_usb_cdc_recv( s32 timeout );
|
||||
|
||||
|
||||
|
||||
// *****************************************************************************
|
||||
// Allocator support
|
||||
|
||||
void* platform_get_first_free_ram( unsigned id );
|
||||
void* platform_get_last_free_ram( unsigned id );
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __CLIENT_H__
|
||||
|
||||
#include "type.h"
|
||||
#include "platform.h"
|
||||
|
||||
// Error codes
|
||||
#define CLIENT_OK 0
|
||||
@ -11,11 +12,11 @@
|
||||
|
||||
// RFS client send/receive functions
|
||||
typedef u32 ( *p_rfsc_send )( const u8 *p, u32 size );
|
||||
typedef u32 ( *p_rfsc_recv )( u8 *p, u32 size, s32 timeout );
|
||||
typedef u32 ( *p_rfsc_recv )( u8 *p, u32 size, timer_data_type timeout );
|
||||
|
||||
// Public interface
|
||||
void rfsc_setup( u8 *pbuf, p_rfsc_send rfsc_send_func, p_rfsc_recv rfsc_recv_func, u32 timeout );
|
||||
void rfsc_set_timeout( u32 timeout );
|
||||
void rfsc_setup( u8 *pbuf, p_rfsc_send rfsc_send_func, p_rfsc_recv rfsc_recv_func, timer_data_type timeout );
|
||||
void rfsc_set_timeout( timer_data_type timeout );
|
||||
int rfsc_open( const char* pathname, int flags, int mode );
|
||||
s32 rfsc_write( int fd, const void *buf, u32 count );
|
||||
s32 rfsc_read( int fd, void *buf, u32 count );
|
||||
|
58
inc/swi.h
58
inc/swi.h
@ -27,42 +27,42 @@
|
||||
|
||||
|
||||
/* Now the SWI numbers and reason codes for RDI (Angel) monitors. */
|
||||
#define AngelSWI_ARM 0x123456
|
||||
#define AngelSWI_ARM 0x123456
|
||||
#ifdef __thumb__
|
||||
#define AngelSWI 0xAB
|
||||
#define AngelSWI 0xAB
|
||||
#else
|
||||
#define AngelSWI AngelSWI_ARM
|
||||
#define AngelSWI AngelSWI_ARM
|
||||
#endif
|
||||
/* For Thumb-2 code use the BKPT instruction instead of SWI. */
|
||||
#ifdef __thumb2__
|
||||
#define AngelSWIInsn "bkpt"
|
||||
#define AngelSWIAsm bkpt
|
||||
#define AngelSWIInsn "bkpt"
|
||||
#define AngelSWIAsm bkpt
|
||||
#else
|
||||
#define AngelSWIInsn "swi"
|
||||
#define AngelSWIAsm swi
|
||||
#define AngelSWIInsn "swi"
|
||||
#define AngelSWIAsm swi
|
||||
#endif
|
||||
|
||||
/* The reason codes: */
|
||||
#define AngelSWI_Reason_Open 0x01
|
||||
#define AngelSWI_Reason_Close 0x02
|
||||
#define AngelSWI_Reason_WriteC 0x03
|
||||
#define AngelSWI_Reason_Write0 0x04
|
||||
#define AngelSWI_Reason_Write 0x05
|
||||
#define AngelSWI_Reason_Read 0x06
|
||||
#define AngelSWI_Reason_ReadC 0x07
|
||||
#define AngelSWI_Reason_IsTTY 0x09
|
||||
#define AngelSWI_Reason_Seek 0x0A
|
||||
#define AngelSWI_Reason_FLen 0x0C
|
||||
#define AngelSWI_Reason_TmpNam 0x0D
|
||||
#define AngelSWI_Reason_Remove 0x0E
|
||||
#define AngelSWI_Reason_Rename 0x0F
|
||||
#define AngelSWI_Reason_Clock 0x10
|
||||
#define AngelSWI_Reason_Time 0x11
|
||||
#define AngelSWI_Reason_System 0x12
|
||||
#define AngelSWI_Reason_Errno 0x13
|
||||
#define AngelSWI_Reason_GetCmdLine 0x15
|
||||
#define AngelSWI_Reason_HeapInfo 0x16
|
||||
#define AngelSWI_Reason_EnterSVC 0x17
|
||||
#define AngelSWI_Reason_Open 0x01
|
||||
#define AngelSWI_Reason_Close 0x02
|
||||
#define AngelSWI_Reason_WriteC 0x03
|
||||
#define AngelSWI_Reason_Write0 0x04
|
||||
#define AngelSWI_Reason_Write 0x05
|
||||
#define AngelSWI_Reason_Read 0x06
|
||||
#define AngelSWI_Reason_ReadC 0x07
|
||||
#define AngelSWI_Reason_IsTTY 0x09
|
||||
#define AngelSWI_Reason_Seek 0x0A
|
||||
#define AngelSWI_Reason_FLen 0x0C
|
||||
#define AngelSWI_Reason_TmpNam 0x0D
|
||||
#define AngelSWI_Reason_Remove 0x0E
|
||||
#define AngelSWI_Reason_Rename 0x0F
|
||||
#define AngelSWI_Reason_Clock 0x10
|
||||
#define AngelSWI_Reason_Time 0x11
|
||||
#define AngelSWI_Reason_System 0x12
|
||||
#define AngelSWI_Reason_Errno 0x13
|
||||
#define AngelSWI_Reason_GetCmdLine 0x15
|
||||
#define AngelSWI_Reason_HeapInfo 0x16
|
||||
#define AngelSWI_Reason_EnterSVC 0x17
|
||||
#define AngelSWI_Reason_ReportException 0x18
|
||||
#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
|
||||
#define ADP_Stopped_RunTimeError ((2 << 16) + 35)
|
||||
#define ADP_Stopped_ApplicationExit ((2 << 16) + 38)
|
||||
#define ADP_Stopped_RunTimeError ((2 << 16) + 35)
|
||||
|
@ -74,6 +74,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined( BUILD_MMCFS ) && !defined( PLATFORM_HAS_SYSTIMER )
|
||||
#error "BUILD_MMCFS needs system timer support. Ensure your platform has this implemented and PLATFORM_HAS_SYSTIMER is defined"
|
||||
#endif
|
||||
|
||||
// CON_BUF_SIZE needs BUF_ENABLE_UART and CON_UART_ID
|
||||
#if defined( CON_BUF_SIZE )
|
||||
#if !defined( BUF_ENABLE_UART )
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define __XMODEM_H__
|
||||
|
||||
#include "type.h"
|
||||
#include "platform.h"
|
||||
|
||||
// XMODEM constants
|
||||
#define XMODEM_INITIAL_BUFFER_SIZE 1024
|
||||
@ -20,7 +21,7 @@
|
||||
#define XMODEM_ERROR_OUTOFMEM (-4)
|
||||
|
||||
typedef void ( *p_xm_send_func )( u8 );
|
||||
typedef int ( *p_xm_recv_func )( u32 );
|
||||
typedef int ( *p_xm_recv_func )( timer_data_type );
|
||||
long xmodem_receive( char** dest );
|
||||
void xmodem_init( p_xm_send_func send_func, p_xm_recv_func recv_func );
|
||||
|
||||
|
3
romfs/.gitignore
vendored
Normal file
3
romfs/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*
|
||||
!.gitignore
|
||||
|
25
rpc-lua.py
25
rpc-lua.py
@ -1,7 +1,7 @@
|
||||
import os, sys, platform
|
||||
|
||||
output = 'luarpc'
|
||||
cdefs = ['-DLUA_CROSS_COMPILER','-DLUA_RPC']
|
||||
cdefs = "-DLUA_CROSS_COMPILER -DLUA_RPC"
|
||||
|
||||
# Lua source files and include path
|
||||
lua_files = """lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c
|
||||
@ -10,24 +10,25 @@ lua_files = """lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c
|
||||
lua_full_files = " " + " ".join( [ "src/lua/%s" % name for name in lua_files.split() ] )
|
||||
lua_full_files += " src/modules/luarpc.c src/modules/lpack.c src/modules/bitarray.c src/modules/bit.c src/luarpc_desktop_serial.c "
|
||||
|
||||
external_libs = ['m']
|
||||
external_libs = '-lm'
|
||||
|
||||
if platform.system() == "Windows":
|
||||
lua_full_files += " src/serial/serial_win32.c"
|
||||
cdefs.append("-DWIN32_BUILD")
|
||||
cdefs += " -DWIN32_BUILD"
|
||||
else:
|
||||
lua_full_files += " src/serial/serial_posix.c"
|
||||
external_libs += ['readline']
|
||||
cdefs.append("-DLUA_USE_READLINE")
|
||||
lua_full_files += " src/serial/serial_posix.c src/linenoise_posix.c"
|
||||
cdefs += " -DLUA_USE_LINENOISE "
|
||||
|
||||
local_include = ['src/lua', 'inc', 'src/modules', 'inc/desktop'];
|
||||
local_include = "-Isrc/lua -Iinc -Isrc/modules -Iinc/desktop"
|
||||
|
||||
# Compiler/linker options
|
||||
cccom = "gcc -O2 -g %s -Wall %s -c $SOURCE -o $TARGET" % ( local_include, cdefs )
|
||||
linkcom = "gcc -o $TARGET $SOURCES %s" % external_libs
|
||||
|
||||
# Env for building the program
|
||||
comp = Environment( CPPPATH = local_include,
|
||||
CCFLAGS = cdefs,
|
||||
comp = Environment( CCCOM = cccom,
|
||||
LINKCOM = linkcom,
|
||||
ENV = os.environ )
|
||||
# Debug
|
||||
comp.PrependUnique(CCFLAGS=['-g'])
|
||||
|
||||
Decider( 'MD5-timestamp' )
|
||||
Default( comp.Program( output, Split( lua_full_files ), LIBS=external_libs ) )
|
||||
Default( comp.Program( output, Split( lua_full_files ) ) )
|
||||
|
@ -4,7 +4,7 @@
|
||||
stty -echo raw -igncr
|
||||
|
||||
# Run simulator
|
||||
./elua_lua_linux.elf
|
||||
./elua_lua$1_linux.elf
|
||||
|
||||
# Restore terminal to default settings
|
||||
stty echo cooked
|
||||
|
132
src/common.c
132
src/common.c
@ -8,6 +8,7 @@
|
||||
#include "buf.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "math.h"
|
||||
#include "elua_adc.h"
|
||||
@ -15,6 +16,9 @@
|
||||
#include "xmodem.h"
|
||||
#include "elua_int.h"
|
||||
#include "sermux.h"
|
||||
#include "lua.h"
|
||||
#include "lapi.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
// [TODO] the new builder should automatically do this
|
||||
#if defined( BUILD_LUA_INT_HANDLERS ) || defined( BUILD_C_INT_HANDLERS )
|
||||
@ -45,7 +49,12 @@ extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ];
|
||||
|
||||
// [TODO] the new builder should automatically do this
|
||||
#ifndef CON_FLOW_TYPE
|
||||
#define CON_FLOW_TYPE PLATFORM_UART_FLOW_NONE
|
||||
#define CON_FLOW_TYPE PLATFORM_UART_FLOW_NONE
|
||||
#endif
|
||||
|
||||
// [TODO] the new builder should automatically do this
|
||||
#ifndef CON_TIMER_ID
|
||||
#define CON_TIMER_ID PLATFORM_TIMER_SYS_ID
|
||||
#endif
|
||||
|
||||
// ****************************************************************************
|
||||
@ -58,7 +67,7 @@ static void xmodem_send( u8 data )
|
||||
platform_uart_send( CON_UART_ID, data );
|
||||
}
|
||||
|
||||
static int xmodem_recv( u32 timeout )
|
||||
static int xmodem_recv( timer_data_type timeout )
|
||||
{
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, timeout );
|
||||
}
|
||||
@ -82,7 +91,7 @@ static int term_in( int mode )
|
||||
if( mode == TERM_INPUT_DONT_WAIT )
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, 0 );
|
||||
else
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_UART_INFINITE_TIMEOUT );
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, PLATFORM_TIMER_INF_TIMEOUT );
|
||||
}
|
||||
|
||||
static int term_translate( int data )
|
||||
@ -176,7 +185,7 @@ static void uart_send( int fd, char c )
|
||||
platform_uart_send( CON_UART_ID, c );
|
||||
}
|
||||
|
||||
static int uart_recv( s32 to )
|
||||
static int uart_recv( timer_data_type to )
|
||||
{
|
||||
return platform_uart_recv( CON_UART_ID, CON_TIMER_ID, to );
|
||||
}
|
||||
@ -201,7 +210,7 @@ void cmn_platform_init()
|
||||
platform_uart_set_buffer( i + SERMUX_SERVICE_ID_FIRST, bufsizes[ i ] );
|
||||
#endif // #ifdef BUILD_SERMUX
|
||||
|
||||
#if defined( CON_UART_ID ) && CON_UART_ID < SERMUX_SERVICE_ID_FIRST
|
||||
#if defined( CON_UART_ID ) && CON_UART_ID < SERMUX_SERVICE_ID_FIRST && ( CON_UART_ID != CDC_UART_ID )
|
||||
// Setup console UART
|
||||
platform_uart_setup( CON_UART_ID, CON_UART_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
platform_uart_set_flow_control( CON_UART_ID, CON_FLOW_TYPE );
|
||||
@ -294,47 +303,41 @@ int platform_adc_exists( unsigned id )
|
||||
|
||||
#ifdef BUILD_ADC
|
||||
|
||||
u32 platform_adc_op( unsigned id, int op, u32 data )
|
||||
u32 platform_adc_get_maxval( unsigned id )
|
||||
{
|
||||
elua_adc_ch_state *s = adc_get_ch_state( id );
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
u32 res = 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_ADC_GET_MAXVAL:
|
||||
res = pow( 2, ADC_BIT_RESOLUTION ) - 1;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_SMOOTHING:
|
||||
res = adc_update_smoothing( id, ( u8 )intlog2( ( unsigned ) data ) );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_BLOCKING:
|
||||
s->blocking = data;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_IS_DONE:
|
||||
res = ( s->op_pending == 0 );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_OP_SET_TIMER:
|
||||
if ( d->timer_id != data )
|
||||
d->running = 0;
|
||||
platform_adc_stop( id );
|
||||
d->timer_id = data;
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_OP_SET_CLOCK:
|
||||
res = platform_adc_setclock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_ADC_SET_FREERUNNING:
|
||||
s->freerunning = data;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
return pow( 2, ADC_BIT_RESOLUTION ) - 1;
|
||||
}
|
||||
|
||||
u32 platform_adc_set_smoothing( unsigned id, u32 length )
|
||||
{
|
||||
return adc_update_smoothing( id, ( u8 )intlog2( ( unsigned ) length ) );
|
||||
}
|
||||
|
||||
void platform_adc_set_blocking( unsigned id, u32 mode )
|
||||
{
|
||||
adc_get_ch_state( id )->blocking = mode;
|
||||
}
|
||||
|
||||
void platform_adc_set_freerunning( unsigned id, u32 mode )
|
||||
{
|
||||
adc_get_ch_state( id )->freerunning = mode;
|
||||
}
|
||||
|
||||
u32 platform_adc_is_done( unsigned id )
|
||||
{
|
||||
return adc_get_ch_state( id )->op_pending == 0;
|
||||
}
|
||||
|
||||
void platform_adc_set_timer( unsigned id, u32 timer )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
|
||||
if ( d->timer_id != timer )
|
||||
d->running = 0;
|
||||
platform_adc_stop( id );
|
||||
d->timer_id = timer;
|
||||
}
|
||||
|
||||
#endif // #ifdef BUILD_ADC
|
||||
|
||||
// ****************************************************************************
|
||||
@ -451,3 +454,44 @@ unsigned int intlog2( unsigned int v )
|
||||
return r;
|
||||
}
|
||||
|
||||
// 64-bits integer printf support seems to be broken in some versions of Newlib...
|
||||
const char* cmn_str64( u64 x )
|
||||
{
|
||||
static char nr[ 32 ];
|
||||
u64 q, r;
|
||||
unsigned l = 30;
|
||||
|
||||
memset( nr, 0, 32 );
|
||||
do
|
||||
{
|
||||
q = x / 10;
|
||||
r = x % 10;
|
||||
nr[ l -- ] = r + '0';
|
||||
x = q;
|
||||
} while( x != 0 );
|
||||
return nr + l + 1;
|
||||
}
|
||||
|
||||
// Read a timeout spec from the user and return it
|
||||
// The timeout spec has the format [timeout], [timer_id]. Both arguments are optional.
|
||||
// If none is specified -> defaults to infinite timeout
|
||||
// If timeout is PLATFORM_TIMER_INF_TIMEOUT -> also infinite timeout (see above)
|
||||
// If a timeout is specified -> timer_id might also be specified. If not, it defaults to
|
||||
// PLATFORM_TIMER_SYS_ID
|
||||
void cmn_get_timeout_data( lua_State *L, int pidx, timer_data_type *ptimeout, unsigned *pid )
|
||||
{
|
||||
lua_Number tempn;
|
||||
|
||||
*ptimeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
*pid = ( unsigned )luaL_optinteger( L, pidx + 1, PLATFORM_TIMER_SYS_ID );
|
||||
if( lua_type( L, pidx ) == LUA_TNUMBER )
|
||||
{
|
||||
tempn = lua_tonumber( L, pidx );
|
||||
if( tempn < 0 || tempn > PLATFORM_TIMER_INF_TIMEOUT )
|
||||
luaL_error( L, "invalid timeout value" );
|
||||
*ptimeout = ( timer_data_type )tempn;
|
||||
}
|
||||
if( *pid == PLATFORM_TIMER_SYS_ID && !platform_timer_sys_available() )
|
||||
luaL_error( L, "the system timer is not implemented on this platform" );
|
||||
}
|
||||
|
||||
|
188
src/common_tmr.c
188
src/common_tmr.c
@ -6,6 +6,7 @@
|
||||
#include "type.h"
|
||||
#include "common.h"
|
||||
#include "elua_int.h"
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// [TODO] when the new build system is ready, automatically add the
|
||||
@ -25,11 +26,20 @@ extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ];
|
||||
#define VTMR_NUM_TIMERS 0
|
||||
#endif // #ifndef VTMR_NUM_TIMERS
|
||||
|
||||
#ifndef PLATFORM_HAS_SYSTIMER
|
||||
#warning This platform does not have a system timer. Your eLua image might not work as expected.
|
||||
#define SYSTIMER_SUPPORT 0
|
||||
#else // #ifndef PLATFORM_HAS_SYSTIMER
|
||||
#define SYSTIMER_SUPPORT 1
|
||||
#endif // #ifndef PLATFORM_HAS_SYSTIMER
|
||||
|
||||
// ****************************************************************************
|
||||
// Timers (and vtimers) functions
|
||||
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
|
||||
#define VTMR_MAX_PERIOD ( ( 1LL << 32 ) - 1 )
|
||||
|
||||
// ============================================================================
|
||||
// VTMR functions
|
||||
|
||||
@ -87,23 +97,28 @@ static void vtmr_reset_timer( unsigned vid )
|
||||
while( vtmr_reset_idx != -1 );
|
||||
}
|
||||
|
||||
static void vtmr_delay( unsigned vid, u32 delay_us )
|
||||
static void vtmr_delay( unsigned vid, timer_data_type delay_us )
|
||||
{
|
||||
timer_data_type final;
|
||||
unsigned id = VTMR_GET_ID( vid );
|
||||
|
||||
if( delay_us > VTMR_MAX_PERIOD )
|
||||
return;
|
||||
final = ( ( u64 )delay_us * VTMR_FREQ_HZ ) / 1000000;
|
||||
vtmr_reset_timer( vid );
|
||||
while( vtmr_counters[ id ] < final );
|
||||
}
|
||||
|
||||
#ifdef CMN_TIMER_INT_SUPPORT
|
||||
static int vtmr_set_match_int( unsigned vid, u32 period_us, int type )
|
||||
|
||||
static int vtmr_set_match_int( unsigned vid, timer_data_type period_us, int type )
|
||||
{
|
||||
timer_data_type final;
|
||||
unsigned id = VTMR_GET_ID( vid );
|
||||
u8 msk = 1 << ( id & 0x07 );
|
||||
|
||||
if( period_us > VTMR_MAX_PERIOD )
|
||||
return PLATFORM_TIMER_INT_TOO_LONG;
|
||||
if( period_us == 0 )
|
||||
{
|
||||
vtmr_int_enabled[ id >> 3 ] &= ( u8 )~msk;
|
||||
@ -166,6 +181,18 @@ void cmn_virtual_timer_cb()
|
||||
// ============================================================================
|
||||
// Actual timer functions
|
||||
|
||||
int platform_timer_sys_available()
|
||||
{
|
||||
return SYSTIMER_SUPPORT;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_HAS_SYSTIMER
|
||||
timer_data_type platform_timer_read_sys()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int platform_timer_exists( unsigned id )
|
||||
{
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
@ -173,25 +200,81 @@ int platform_timer_exists( unsigned id )
|
||||
return TIMER_IS_VIRTUAL( id );
|
||||
else
|
||||
#endif
|
||||
return id < NUM_TIMER;
|
||||
return id < NUM_TIMER || ( id == PLATFORM_TIMER_SYS_ID && SYSTIMER_SUPPORT );
|
||||
}
|
||||
|
||||
void platform_timer_delay( unsigned id, u32 delay_us )
|
||||
void platform_timer_delay( unsigned id, timer_data_type delay_us )
|
||||
{
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
if( TIMER_IS_VIRTUAL( id ) )
|
||||
vtmr_delay( id, delay_us );
|
||||
else
|
||||
#endif
|
||||
if( id == PLATFORM_TIMER_SYS_ID )
|
||||
{
|
||||
if( !SYSTIMER_SUPPORT )
|
||||
return;
|
||||
if( delay_us > 0 )
|
||||
{
|
||||
u64 tstart = platform_timer_read_sys(), tend;
|
||||
while( 1 )
|
||||
{
|
||||
if( ( tend = platform_timer_read_sys() ) < tstart ) // overflow
|
||||
tend += ( u64 )PLATFORM_TIMER_SYS_MAX + 1;
|
||||
if( tend - tstart >= delay_us )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
platform_s_timer_delay( id, delay_us );
|
||||
}
|
||||
|
||||
u32 platform_timer_op( unsigned id, int op, u32 data )
|
||||
timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data )
|
||||
{
|
||||
u32 res = 0;
|
||||
timer_data_type res = 0;
|
||||
|
||||
if( id == PLATFORM_TIMER_SYS_ID ) // the system timer gets special treatment
|
||||
{
|
||||
if( !SYSTIMER_SUPPORT )
|
||||
return 0;
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_TIMER_OP_START:
|
||||
case PLATFORM_TIMER_OP_READ:
|
||||
res = platform_timer_read_sys();
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = PLATFORM_TIMER_SYS_FREQ;
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
|
||||
res = PLATFORM_TIMER_SYS_MAX + 1;
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_CNT:
|
||||
res = PLATFORM_TIMER_SYS_MAX;
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
|
||||
res = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
if( ( VTMR_NUM_TIMERS == 0 ) || ( !TIMER_IS_VIRTUAL( id ) ) )
|
||||
return platform_s_timer_op( id, op, data );
|
||||
{
|
||||
// 'get min delay' and 'get max delay' are very common cases, handle them here
|
||||
if( op == PLATFORM_TIMER_OP_GET_MAX_DELAY )
|
||||
return platform_timer_get_diff_us( id, platform_timer_get_max_cnt( id ), 0 );
|
||||
else if( op == PLATFORM_TIMER_OP_GET_MIN_DELAY )
|
||||
return platform_timer_get_diff_us( id, 1, 0 );
|
||||
else
|
||||
return platform_s_timer_op( id, op, data );
|
||||
}
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
switch( op )
|
||||
{
|
||||
@ -205,11 +288,15 @@ u32 platform_timer_op( unsigned id, int op, u32 data )
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 0xFFFFFFFF );
|
||||
res = platform_timer_get_diff_us( id, 0xFFFFFFFF, 0 );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 1 );
|
||||
res = platform_timer_get_diff_us( id, 1, 0 );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_CNT:
|
||||
res = VTMR_MAX_PERIOD;
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
@ -221,39 +308,41 @@ u32 platform_timer_op( unsigned id, int op, u32 data )
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 platform_timer_get_diff_us( unsigned id, timer_data_type end, timer_data_type start )
|
||||
timer_data_type platform_timer_get_diff_us( unsigned id, timer_data_type end, timer_data_type start )
|
||||
{
|
||||
timer_data_type temp;
|
||||
u32 freq;
|
||||
u64 tstart = ( u64 )start, tend = ( u64 )end;
|
||||
|
||||
freq = platform_timer_op( id, PLATFORM_TIMER_OP_GET_CLOCK, 0 );
|
||||
if( start < end )
|
||||
{
|
||||
temp = end;
|
||||
end = start;
|
||||
start = temp;
|
||||
}
|
||||
return ( ( u64 )( start - end ) * 1000000 ) / freq;
|
||||
if( tstart > tend )
|
||||
tend += platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_CNT, 0 ) + 1;
|
||||
tstart = ( ( tend - tstart ) * 1000000 ) / freq;
|
||||
return UMIN( tstart, PLATFORM_TIMER_SYS_MAX );
|
||||
}
|
||||
|
||||
#ifdef BUILD_INT_HANDLERS
|
||||
int platform_timer_set_match_int( unsigned id, u32 period_us, int type )
|
||||
int platform_timer_set_match_int( unsigned id, timer_data_type period_us, int type )
|
||||
{
|
||||
#if VTMR_NUM_TIMERS > 0 && defined( CMN_TIMER_INT_SUPPORT )
|
||||
if( TIMER_IS_VIRTUAL( id ) )
|
||||
return vtmr_set_match_int( id, period_us, type );
|
||||
else
|
||||
#endif
|
||||
if( id == PLATFORM_TIMER_SYS_ID )
|
||||
return PLATFORM_TIMER_INT_INVALID_ID;
|
||||
else
|
||||
return platform_s_timer_set_match_int( id, period_us, type );
|
||||
}
|
||||
|
||||
int cmn_tmr_int_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
elua_int_p_set_status ps;
|
||||
#if VTMR_NUM_TIMERS > 00 && defined( CMN_TIMER_INT_SUPPORT )
|
||||
if( TIMER_IS_VIRTUAL( resnum ) )
|
||||
return vtmr_int_set_status( resnum, status );
|
||||
#endif
|
||||
elua_int_p_set_status ps;
|
||||
if( resnum == PLATFORM_TIMER_SYS_ID )
|
||||
return PLATFORM_INT_BAD_RESNUM;
|
||||
if( ( ps = elua_int_table[ INT_TMR_MATCH - ELUA_INT_FIRST_ID ].int_set_status ) == NULL )
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
return ps( resnum, status );
|
||||
@ -261,11 +350,13 @@ int cmn_tmr_int_set_status( elua_int_resnum resnum, int status )
|
||||
|
||||
int cmn_tmr_int_get_status( elua_int_resnum resnum )
|
||||
{
|
||||
elua_int_p_get_status pg;
|
||||
#if VTMR_NUM_TIMERS > 00 && defined( CMN_TIMER_INT_SUPPORT )
|
||||
if( TIMER_IS_VIRTUAL( resnum ) )
|
||||
return vtmr_int_get_status( resnum );
|
||||
#endif
|
||||
elua_int_p_get_status pg;
|
||||
if( resnum == PLATFORM_TIMER_SYS_ID )
|
||||
return PLATFORM_INT_BAD_RESNUM;
|
||||
if( ( pg = elua_int_table[ INT_TMR_MATCH - ELUA_INT_FIRST_ID ].int_get_status ) == NULL )
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
return pg( resnum );
|
||||
@ -273,11 +364,13 @@ int cmn_tmr_int_get_status( elua_int_resnum resnum )
|
||||
|
||||
int cmn_tmr_int_get_flag( elua_int_resnum resnum, int clear )
|
||||
{
|
||||
elua_int_p_get_flag pf;
|
||||
#if VTMR_NUM_TIMERS > 00 && defined( CMN_TIMER_INT_SUPPORT )
|
||||
if( TIMER_IS_VIRTUAL( resnum ) )
|
||||
return vtmr_int_get_flag( resnum, clear );
|
||||
#endif
|
||||
elua_int_p_get_flag pf;
|
||||
if( resnum == PLATFORM_TIMER_SYS_ID )
|
||||
return PLATFORM_INT_BAD_RESNUM;
|
||||
if( ( pf = elua_int_table[ INT_TMR_MATCH - ELUA_INT_FIRST_ID ].int_get_flag ) == NULL )
|
||||
return PLATFORM_INT_NOT_HANDLED;
|
||||
return pf( resnum, clear );
|
||||
@ -285,7 +378,7 @@ int cmn_tmr_int_get_flag( elua_int_resnum resnum, int clear )
|
||||
|
||||
#else // #ifdef BUILD_INT_HANDLERS
|
||||
|
||||
int platform_timer_set_match_int( unsigned id, u32 period_us, int type )
|
||||
int platform_timer_set_match_int( unsigned id, timer_data_type period_us, int type )
|
||||
{
|
||||
fprintf( stderr, "Timer match interrupt not available when eLua interrupt support is not enabled.\n" );
|
||||
return 0;
|
||||
@ -293,3 +386,52 @@ int platform_timer_set_match_int( unsigned id, u32 period_us, int type )
|
||||
|
||||
#endif // #ifdef BUILD_INT_HANDLERS
|
||||
|
||||
// ****************************************************************************
|
||||
// Generic system timer support
|
||||
|
||||
static u32 cmn_systimer_ticks_for_us;
|
||||
static volatile u64 cmn_systimer_counter;
|
||||
static u32 cmn_systimer_us_per_interrupt;
|
||||
|
||||
void cmn_systimer_set_base_freq( u32 freq_hz )
|
||||
{
|
||||
cmn_systimer_ticks_for_us = freq_hz / 1000000;
|
||||
}
|
||||
|
||||
void cmn_systimer_set_interrupt_freq( u32 freq_hz )
|
||||
{
|
||||
cmn_systimer_us_per_interrupt = 1000000 / freq_hz;
|
||||
}
|
||||
|
||||
void cmn_systimer_set_interrupt_period_us( u32 period )
|
||||
{
|
||||
cmn_systimer_us_per_interrupt = period;
|
||||
}
|
||||
|
||||
void cmn_systimer_periodic()
|
||||
{
|
||||
cmn_systimer_counter += cmn_systimer_us_per_interrupt;
|
||||
}
|
||||
|
||||
timer_data_type cmn_systimer_get()
|
||||
{
|
||||
u64 tempsys, tempcnt, crtsys;
|
||||
|
||||
tempcnt = platform_timer_sys_raw_read();
|
||||
tempsys = cmn_systimer_counter;
|
||||
while( ( crtsys = cmn_systimer_counter ) != tempsys )
|
||||
{
|
||||
tempcnt = platform_timer_sys_raw_read();
|
||||
tempsys = crtsys;
|
||||
}
|
||||
crtsys += tempcnt / cmn_systimer_ticks_for_us;
|
||||
if( crtsys > PLATFORM_TIMER_SYS_MAX ) // timer overflow
|
||||
{
|
||||
crtsys %= PLATFORM_TIMER_SYS_MAX;
|
||||
platform_timer_sys_disable_int();
|
||||
cmn_systimer_counter = 0;
|
||||
platform_timer_sys_enable_int();
|
||||
}
|
||||
return ( timer_data_type )crtsys;
|
||||
}
|
||||
|
||||
|
@ -24,18 +24,34 @@ int uart_last_sent = -1;
|
||||
int platform_uart_exists( unsigned id )
|
||||
{
|
||||
#ifdef BUILD_SERMUX
|
||||
return id < NUM_UART || ( id >= SERMUX_SERVICE_ID_FIRST && id < SERMUX_SERVICE_ID_FIRST + SERMUX_NUM_VUART );
|
||||
#else // #ifdef BUILD_SERMUX
|
||||
return id < NUM_UART;
|
||||
#endif // #ifdef BUILD_SERMUX
|
||||
if( id >= SERMUX_SERVICE_ID_FIRST && id < SERMUX_SERVICE_ID_FIRST + SERMUX_NUM_VUART )
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if( id < NUM_UART )
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Helper function for buffers
|
||||
static int cmn_recv_helper( unsigned id, s32 timeout )
|
||||
static int cmn_recv_helper( unsigned id, timer_data_type timeout )
|
||||
{
|
||||
#ifdef BUF_ENABLE_UART
|
||||
t_buf_data data;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
return platform_usb_cdc_recv( timeout );
|
||||
#endif
|
||||
|
||||
#ifdef BUF_ENABLE_UART
|
||||
if( buf_is_enabled( BUF_ID_UART, id ) )
|
||||
{
|
||||
if( timeout == 0 )
|
||||
@ -51,28 +67,30 @@ static int cmn_recv_helper( unsigned id, s32 timeout )
|
||||
}
|
||||
else
|
||||
#endif // #ifdef BUF_ENABLE_UART
|
||||
return platform_s_uart_recv( id, timeout );
|
||||
if( id < NUM_UART )
|
||||
return platform_s_uart_recv( id, timeout );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int platform_uart_recv( unsigned id, unsigned timer_id, s32 timeout )
|
||||
int platform_uart_recv( unsigned id, unsigned timer_id, timer_data_type timeout )
|
||||
{
|
||||
timer_data_type tmr_start, tmr_crt;
|
||||
timer_data_type tmr_start;
|
||||
int res;
|
||||
|
||||
if( timeout == 0 )
|
||||
return cmn_recv_helper( id, timeout );
|
||||
else if( timeout == PLATFORM_UART_INFINITE_TIMEOUT )
|
||||
else if( timeout == PLATFORM_TIMER_INF_TIMEOUT )
|
||||
return cmn_recv_helper( id, timeout );
|
||||
else
|
||||
{
|
||||
// Receive char with the specified timeout
|
||||
tmr_start = platform_timer_op( timer_id, PLATFORM_TIMER_OP_START, 0 );
|
||||
tmr_start = platform_timer_start( timer_id );
|
||||
while( 1 )
|
||||
{
|
||||
if( ( res = cmn_recv_helper( id, 0 ) ) >= 0 )
|
||||
break;
|
||||
tmr_crt = platform_timer_op( timer_id, PLATFORM_TIMER_OP_READ, 0 );
|
||||
if( platform_timer_get_diff_us( timer_id, tmr_crt, tmr_start ) >= timeout )
|
||||
if( platform_timer_get_diff_crt( timer_id, tmr_start ) >= timeout )
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
@ -122,6 +140,10 @@ static void cmn_rx_handler( int usart_id, u8 data )
|
||||
// Send: version with and without mux
|
||||
void platform_uart_send( unsigned id, u8 data )
|
||||
{
|
||||
#ifdef BUILD_USB_CDC
|
||||
if( id == CDC_UART_ID )
|
||||
platform_usb_cdc_send( data );
|
||||
#endif
|
||||
#ifdef BUILD_SERMUX
|
||||
if( id >= SERMUX_SERVICE_ID_FIRST && id < SERMUX_SERVICE_ID_FIRST + SERMUX_NUM_VUART )
|
||||
{
|
||||
@ -138,9 +160,9 @@ void platform_uart_send( unsigned id, u8 data )
|
||||
platform_s_uart_send( SERMUX_PHYS_ID, data );
|
||||
uart_service_id_out = id;
|
||||
}
|
||||
else
|
||||
#endif // #ifdef BUILD_SERMUX
|
||||
platform_s_uart_send( id, data );
|
||||
if( id < NUM_UART )
|
||||
platform_s_uart_send( id, data );
|
||||
}
|
||||
|
||||
#ifdef BUF_ENABLE_UART
|
||||
@ -148,8 +170,13 @@ static elua_int_c_handler prev_uart_rx_handler;
|
||||
|
||||
static void cmn_uart_rx_inthandler( elua_int_resnum resnum )
|
||||
{
|
||||
int data;
|
||||
|
||||
if( buf_is_enabled( BUF_ID_UART, resnum ) || resnum == SERMUX_PHYS_ID )
|
||||
cmn_rx_handler( resnum, platform_s_uart_recv( resnum, 0 ) );
|
||||
{
|
||||
while( -1 != ( data = platform_s_uart_recv( resnum, 0 ) ) )
|
||||
cmn_rx_handler( resnum, ( u8 )data );
|
||||
}
|
||||
|
||||
// Chain to previous handler
|
||||
if( prev_uart_rx_handler != NULL )
|
||||
|
@ -24,7 +24,7 @@ elua_adc_dev_state *adc_get_dev_state( unsigned dev_id )
|
||||
return &adc_dev_state;
|
||||
}
|
||||
|
||||
// Rewrite revice sequence
|
||||
// Rewrite device sequence
|
||||
void adc_update_dev_sequence( unsigned dev_id )
|
||||
{
|
||||
elua_adc_dev_state *d = adc_get_dev_state( dev_id );
|
||||
@ -126,7 +126,7 @@ void adc_init_ch_state( unsigned id )
|
||||
#endif
|
||||
|
||||
// Set to run as fast as possible
|
||||
platform_adc_setclock( id, 0 );
|
||||
platform_adc_set_clock( id, 0 );
|
||||
}
|
||||
|
||||
void adc_init_dev_state( unsigned dev_id )
|
||||
|
@ -55,8 +55,8 @@ void DESELECT (void)
|
||||
static volatile
|
||||
DSTATUS Stat = STA_NOINIT; /* Disk status */
|
||||
|
||||
static volatile UINT Timer1 = 0;
|
||||
static volatile UINT Timer2 = 0; /* decrement timer */
|
||||
static volatile timer_data_type Timer1 = 0;
|
||||
static volatile timer_data_type Timer2 = 0;
|
||||
|
||||
static
|
||||
BYTE TriesLeft = 2;
|
||||
@ -67,6 +67,7 @@ BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
|
||||
static
|
||||
BYTE PowerFlag = 0; /* indicates if "power" is on */
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Transmit a byte to MMC via SPI (Platform dependent) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -109,11 +110,11 @@ BYTE wait_ready (void)
|
||||
{
|
||||
BYTE res;
|
||||
|
||||
Timer2 = 500/MMCFS_TICK_MS; /* Wait for ready in timeout of 500ms */
|
||||
Timer2 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||
rcvr_spi();
|
||||
do
|
||||
res = rcvr_spi();
|
||||
while ((res != 0xFF) && Timer2);
|
||||
res = rcvr_spi(); /* Wait for ready in timeout of 500ms. */
|
||||
while ( ( res != 0xFF ) && ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer2 ) < 500000 ) );
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -205,11 +206,11 @@ BOOL rcvr_datablock (
|
||||
{
|
||||
BYTE token;
|
||||
|
||||
|
||||
Timer1 = 100/MMCFS_TICK_MS ? 100/MMCFS_TICK_MS : 1;
|
||||
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||
do { /* Wait for data packet in timeout of 100ms */
|
||||
token = rcvr_spi();
|
||||
} while ((token == 0xFF) && Timer1);
|
||||
} while ( ( token == 0xFF ) &&
|
||||
platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 100000 );
|
||||
if(token != 0xFE) return FALSE; /* If not valid data token, retutn with error */
|
||||
|
||||
do { /* Receive the data block into buffer */
|
||||
@ -326,29 +327,31 @@ DSTATUS disk_initialize (
|
||||
SELECT(); /* CS = L */
|
||||
ty = 0;
|
||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
||||
Timer1 = 1000/MMCFS_TICK_MS; /* Initialization timeout of 1000 msec */
|
||||
Timer1 = platform_timer_read( PLATFORM_TIMER_SYS_ID );
|
||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDC Ver2+ */
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
||||
do {
|
||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
|
||||
} while (Timer1);
|
||||
if (Timer1 && send_cmd(CMD58, 0) == 0) { /* Check CCS bit */
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
||||
ty = (ocr[0] & 0x40) ? 6 : 2;
|
||||
}
|
||||
}
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
||||
do {
|
||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 1UL << 30) == 0) break; /* ACMD41 with HCS bit */
|
||||
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
||||
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 )
|
||||
&& send_cmd(CMD58, 0) == 0) { /* Check CCS bit (it seems pointless to check the timer here*/
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
||||
ty = (ocr[0] & 0x40) ? 6 : 2;
|
||||
}
|
||||
}
|
||||
} else { /* SDC Ver1 or MMC */
|
||||
ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
|
||||
do {
|
||||
if (ty == 2) {
|
||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
|
||||
} else {
|
||||
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
|
||||
}
|
||||
} while (Timer1);
|
||||
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
|
||||
ty = 0;
|
||||
ty = (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) <= 1) ? 2 : 1; /* SDC : MMC */
|
||||
do {
|
||||
if (ty == 2) {
|
||||
if (send_cmd(CMD55, 0) <= 1 && send_cmd(CMD41, 0) == 0) break; /* ACMD41 */
|
||||
} else {
|
||||
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
|
||||
}
|
||||
} while ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 1000000 );
|
||||
if ( ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) >= 1000000 )
|
||||
|| send_cmd(CMD16, 512) != 0 ) /* Select R/W block length */
|
||||
ty = 0;
|
||||
}
|
||||
}
|
||||
CardType = ty;
|
||||
@ -356,13 +359,13 @@ DSTATUS disk_initialize (
|
||||
rcvr_spi(); /* Idle (Release DO) */
|
||||
|
||||
if (TriesLeft)
|
||||
TriesLeft--;
|
||||
TriesLeft--;
|
||||
|
||||
if (ty) { /* Initialization succeded */
|
||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
||||
set_max_speed();
|
||||
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
|
||||
set_max_speed();
|
||||
} else { /* Initialization failed */
|
||||
power_off();
|
||||
power_off();
|
||||
}
|
||||
|
||||
} while( TriesLeft > 0 && ty == 0 );
|
||||
@ -580,22 +583,6 @@ DRESULT disk_ioctl (
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Device Timer Interrupt Procedure (Platform dependent) */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* This function must be called in period of 10ms */
|
||||
|
||||
void disk_timerproc( void )
|
||||
{
|
||||
UINT n;
|
||||
|
||||
n = Timer1;
|
||||
if (n) Timer1 = --n;
|
||||
n = Timer2;
|
||||
if (n) Timer2 = --n;
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
/* User Provided Timer Function for FatFs module */
|
||||
/*---------------------------------------------------------*/
|
||||
|
@ -545,10 +545,10 @@ elua_net_size elua_net_send( int s, const void* buf, elua_net_size len )
|
||||
}
|
||||
|
||||
// Internal "read" function
|
||||
static elua_net_size elua_net_recv_internal( int s, void* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, u32 to_us, int with_buffer )
|
||||
static elua_net_size elua_net_recv_internal( int s, void* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, timer_data_type to_us, int with_buffer )
|
||||
{
|
||||
volatile struct elua_uip_state *pstate = ( volatile struct elua_uip_state* )&( uip_conns[ s ].appstate );
|
||||
u32 tmrstart = 0;
|
||||
timer_data_type tmrstart = 0;
|
||||
int old_status;
|
||||
|
||||
if( !ELUA_UIP_IS_SOCK_OK( s ) || !uip_conn_active( s ) )
|
||||
@ -557,12 +557,12 @@ static elua_net_size elua_net_recv_internal( int s, void* buf, elua_net_size max
|
||||
return 0;
|
||||
elua_prep_socket_state( pstate, buf, maxsize, readto, with_buffer, ELUA_UIP_STATE_RECV );
|
||||
if( to_us > 0 )
|
||||
tmrstart = platform_timer_op( timer_id, PLATFORM_TIMER_OP_START, 0 );
|
||||
tmrstart = platform_timer_start( timer_id );
|
||||
while( 1 )
|
||||
{
|
||||
if( pstate->state == ELUA_UIP_STATE_IDLE )
|
||||
break;
|
||||
if( to_us > 0 && platform_timer_get_diff_us( timer_id, tmrstart, platform_timer_op( timer_id, PLATFORM_TIMER_OP_READ, 0 ) ) >= to_us )
|
||||
if( to_us > 0 && platform_timer_get_diff_crt( timer_id, tmrstart ) >= to_us )
|
||||
{
|
||||
old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE );
|
||||
if( pstate->state != ELUA_UIP_STATE_IDLE )
|
||||
@ -578,13 +578,13 @@ static elua_net_size elua_net_recv_internal( int s, void* buf, elua_net_size max
|
||||
}
|
||||
|
||||
// Receive data in buf, upto "maxsize" bytes, or upto the 'readto' character if it's not -1
|
||||
elua_net_size elua_net_recv( int s, void* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, u32 to_us )
|
||||
elua_net_size elua_net_recv( int s, void* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, timer_data_type to_us )
|
||||
{
|
||||
return elua_net_recv_internal( s, buf, maxsize, readto, timer_id, to_us, 0 );
|
||||
}
|
||||
|
||||
// Same thing, but with a Lua buffer as argument
|
||||
elua_net_size elua_net_recvbuf( int s, luaL_Buffer* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, u32 to_us )
|
||||
elua_net_size elua_net_recvbuf( int s, luaL_Buffer* buf, elua_net_size maxsize, s16 readto, unsigned timer_id, timer_data_type to_us )
|
||||
{
|
||||
return elua_net_recv_internal( s, buf, maxsize, readto, timer_id, to_us, 1 );
|
||||
}
|
||||
@ -627,9 +627,9 @@ int elua_net_get_last_err( int s )
|
||||
}
|
||||
|
||||
// Accept a connection on the given port, return its socket id (and the IP of the remote host by side effect)
|
||||
int elua_accept( u16 port, unsigned timer_id, u32 to_us, elua_net_ip* pfrom )
|
||||
int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip* pfrom )
|
||||
{
|
||||
u32 tmrstart = 0;
|
||||
timer_data_type tmrstart = 0;
|
||||
int old_status;
|
||||
|
||||
if( !elua_uip_configured )
|
||||
@ -645,12 +645,12 @@ int elua_accept( u16 port, unsigned timer_id, u32 to_us, elua_net_ip* pfrom )
|
||||
elua_uip_accept_sock = -1;
|
||||
elua_uip_accept_request = 1;
|
||||
if( to_us > 0 )
|
||||
tmrstart = platform_timer_op( timer_id, PLATFORM_TIMER_OP_START, 0 );
|
||||
tmrstart = platform_timer_start( timer_id );
|
||||
while( 1 )
|
||||
{
|
||||
if( elua_uip_accept_request == 0 )
|
||||
break;
|
||||
if( to_us > 0 && platform_timer_get_diff_us( timer_id, tmrstart, platform_timer_op( timer_id, PLATFORM_TIMER_OP_READ, 0 ) ) >= to_us )
|
||||
if( to_us > 0 && platform_timer_get_diff_crt( timer_id, tmrstart ) >= to_us )
|
||||
{
|
||||
elua_uip_accept_request = 0;
|
||||
break;
|
||||
|
@ -34,7 +34,6 @@ DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
|
||||
DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
|
||||
#endif
|
||||
DRESULT disk_ioctl (BYTE, BYTE, void*);
|
||||
void disk_timerproc (void);
|
||||
|
||||
|
||||
|
||||
|
@ -414,9 +414,9 @@ int linenoise_savehistory( int id, const char *filename )
|
||||
int linenoise_getline( int id, char* buffer, int maxinput, const char* prompt )
|
||||
{
|
||||
( void )id;
|
||||
fputs( prompt, stdout );
|
||||
fputs( prompt, stdout );
|
||||
fflush( stdout );
|
||||
return fgets( buffer, maxinput, stdin ) == NULL ? -1 : 0;
|
||||
return fgets( buffer, maxinput, stdin ) == NULL ? -1 : 0;
|
||||
}
|
||||
|
||||
int linenoise_addhistory( int id, const char *line )
|
||||
|
612
src/linenoise_posix.c
Normal file
612
src/linenoise_posix.c
Normal file
@ -0,0 +1,612 @@
|
||||
/* linenoise.c -- guerrilla line editing library against the idea that a
|
||||
* line editing lib needs to be 20,000 lines of C code.
|
||||
*
|
||||
* You can find the latest source code at:
|
||||
*
|
||||
* http://github.com/antirez/linenoise
|
||||
*
|
||||
* Does a number of crazy assumptions that happen to be true in 99.9999% of
|
||||
* the 2010 UNIX computers around.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2010, Salvatore Sanfilippo <antirez at gmail dot com>
|
||||
* Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* References:
|
||||
* - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
* - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
|
||||
*
|
||||
* Todo list:
|
||||
* - Switch to gets() if $TERM is something we can't support.
|
||||
* - Filter bogus Ctrl+<char> combinations.
|
||||
* - Win32 support
|
||||
*
|
||||
* Bloat:
|
||||
* - Completion?
|
||||
* - History search like Ctrl+r in readline?
|
||||
*
|
||||
* List of escape sequences used by this program, we do everything just
|
||||
* with three sequences. In order to be so cheap we may have some
|
||||
* flickering effect with some slow terminal, but the lesser sequences
|
||||
* the more compatible.
|
||||
*
|
||||
* CHA (Cursor Horizontal Absolute)
|
||||
* Sequence: ESC [ n G
|
||||
* Effect: moves cursor to column n
|
||||
*
|
||||
* EL (Erase Line)
|
||||
* Sequence: ESC [ n K
|
||||
* Effect: if n is 0 or missing, clear from cursor to end of line
|
||||
* Effect: if n is 1, clear from beginning of line to cursor
|
||||
* Effect: if n is 2, clear entire line
|
||||
*
|
||||
* CUF (CUrsor Forward)
|
||||
* Sequence: ESC [ n C
|
||||
* Effect: moves cursor forward of n chars
|
||||
*
|
||||
* The following are used to clear the screen: ESC [ H ESC [ 2 J
|
||||
* This is actually composed of two sequences:
|
||||
*
|
||||
* cursorhome
|
||||
* Sequence: ESC [ H
|
||||
* Effect: moves the cursor to upper left corner
|
||||
*
|
||||
* ED2 (Clear entire screen)
|
||||
* Sequence: ESC [ 2 J
|
||||
* Effect: clear the whole screen
|
||||
*
|
||||
*/
|
||||
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include "linenoise_posix.h"
|
||||
|
||||
#define LINENOISE_DEFAULT_HISTORY_MAX_LEN 100
|
||||
#define LINENOISE_MAX_LINE 4096
|
||||
static char *unsupported_term[] = {"dumb","cons25",NULL};
|
||||
static linenoiseCompletionCallback *completionCallback = NULL;
|
||||
|
||||
static struct termios orig_termios; /* in order to restore at exit */
|
||||
static int rawmode = 0; /* for atexit() function to check if restore is needed*/
|
||||
static int atexit_registered = 0; /* register atexit just 1 time */
|
||||
static int history_max_len = LINENOISE_DEFAULT_HISTORY_MAX_LEN;
|
||||
static int history_len = 0;
|
||||
char **history = NULL;
|
||||
|
||||
static void linenoiseAtExit(void);
|
||||
int linenoiseHistoryAdd(const char *line);
|
||||
|
||||
static int isUnsupportedTerm(void) {
|
||||
char *term = getenv("TERM");
|
||||
int j;
|
||||
|
||||
if (term == NULL) return 0;
|
||||
for (j = 0; unsupported_term[j]; j++)
|
||||
if (!strcasecmp(term,unsupported_term[j])) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void freeHistory(void) {
|
||||
if (history) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < history_len; j++)
|
||||
free(history[j]);
|
||||
free(history);
|
||||
}
|
||||
}
|
||||
|
||||
static int enableRawMode(int fd) {
|
||||
struct termios raw;
|
||||
|
||||
if (!isatty(STDIN_FILENO)) goto fatal;
|
||||
if (!atexit_registered) {
|
||||
atexit(linenoiseAtExit);
|
||||
atexit_registered = 1;
|
||||
}
|
||||
if (tcgetattr(fd,&orig_termios) == -1) goto fatal;
|
||||
|
||||
raw = orig_termios; /* modify the original mode */
|
||||
/* input modes: no break, no CR to NL, no parity check, no strip char,
|
||||
* no start/stop output control. */
|
||||
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
|
||||
/* output modes - disable post processing */
|
||||
raw.c_oflag &= ~(OPOST);
|
||||
/* control modes - set 8 bit chars */
|
||||
raw.c_cflag |= (CS8);
|
||||
/* local modes - choing off, canonical off, no extended functions,
|
||||
* no signal chars (^Z,^C) */
|
||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
|
||||
/* control chars - set return condition: min number of bytes and timer.
|
||||
* We want read to return every single byte, without timeout. */
|
||||
raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; /* 1 byte, no timer */
|
||||
|
||||
/* put terminal in raw mode after flushing */
|
||||
if (tcsetattr(fd,TCSAFLUSH,&raw) < 0) goto fatal;
|
||||
rawmode = 1;
|
||||
return 0;
|
||||
|
||||
fatal:
|
||||
errno = ENOTTY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void disableRawMode(int fd) {
|
||||
/* Don't even check the return value as it's too late. */
|
||||
if (rawmode && tcsetattr(fd,TCSAFLUSH,&orig_termios) != -1)
|
||||
rawmode = 0;
|
||||
}
|
||||
|
||||
/* At exit we'll try to fix the terminal to the initial conditions. */
|
||||
static void linenoiseAtExit(void) {
|
||||
disableRawMode(STDIN_FILENO);
|
||||
freeHistory();
|
||||
}
|
||||
|
||||
static int getColumns(void) {
|
||||
struct winsize ws;
|
||||
|
||||
if (ioctl(1, TIOCGWINSZ, &ws) == -1) return 80;
|
||||
return ws.ws_col;
|
||||
}
|
||||
|
||||
static void refreshLine(int fd, const char *prompt, char *buf, size_t len, size_t pos, size_t cols) {
|
||||
char seq[64];
|
||||
size_t plen = strlen(prompt);
|
||||
|
||||
while((plen+pos) >= cols) {
|
||||
buf++;
|
||||
len--;
|
||||
pos--;
|
||||
}
|
||||
while (plen+len > cols) {
|
||||
len--;
|
||||
}
|
||||
|
||||
/* Cursor to left edge */
|
||||
snprintf(seq,64,"\x1b[0G");
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
/* Write the prompt and the current buffer content */
|
||||
if (write(fd,prompt,strlen(prompt)) == -1) return;
|
||||
if (write(fd,buf,len) == -1) return;
|
||||
/* Erase to right */
|
||||
snprintf(seq,64,"\x1b[0K");
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
/* Move cursor to original position. */
|
||||
snprintf(seq,64,"\x1b[0G\x1b[%dC", (int)(pos+plen));
|
||||
if (write(fd,seq,strlen(seq)) == -1) return;
|
||||
}
|
||||
|
||||
static void beep() {
|
||||
fprintf(stderr, "\x7");
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
static void freeCompletions(linenoiseCompletions *lc) {
|
||||
size_t i;
|
||||
for (i = 0; i < lc->len; i++)
|
||||
free(lc->cvec[i]);
|
||||
if (lc->cvec != NULL)
|
||||
free(lc->cvec);
|
||||
}
|
||||
|
||||
static int completeLine(int fd, const char *prompt, char *buf, size_t buflen, size_t *len, size_t *pos, size_t cols) {
|
||||
linenoiseCompletions lc = { 0, NULL };
|
||||
int nread, nwritten;
|
||||
char c = 0;
|
||||
|
||||
completionCallback(buf,&lc);
|
||||
if (lc.len == 0) {
|
||||
beep();
|
||||
} else {
|
||||
size_t stop = 0, i = 0;
|
||||
size_t clen;
|
||||
|
||||
while(!stop) {
|
||||
/* Show completion or original buffer */
|
||||
if (i < lc.len) {
|
||||
clen = strlen(lc.cvec[i]);
|
||||
refreshLine(fd,prompt,lc.cvec[i],clen,clen,cols);
|
||||
} else {
|
||||
refreshLine(fd,prompt,buf,*len,*pos,cols);
|
||||
}
|
||||
|
||||
nread = read(fd,&c,1);
|
||||
if (nread <= 0) {
|
||||
freeCompletions(&lc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
case 9: /* tab */
|
||||
i = (i+1) % (lc.len+1);
|
||||
if (i == lc.len) beep();
|
||||
break;
|
||||
case 27: /* escape */
|
||||
/* Re-show original buffer */
|
||||
if (i < lc.len) {
|
||||
refreshLine(fd,prompt,buf,*len,*pos,cols);
|
||||
}
|
||||
stop = 1;
|
||||
break;
|
||||
default:
|
||||
/* Update buffer and return */
|
||||
if (i < lc.len) {
|
||||
nwritten = snprintf(buf,buflen,"%s",lc.cvec[i]);
|
||||
*len = *pos = nwritten;
|
||||
}
|
||||
stop = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
freeCompletions(&lc);
|
||||
return c; /* Return last read character */
|
||||
}
|
||||
|
||||
void linenoiseClearScreen(void) {
|
||||
if (write(STDIN_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
|
||||
/* nothing to do, just to avoid warning. */
|
||||
}
|
||||
}
|
||||
|
||||
static int linenoisePrompt(int fd, char *buf, size_t buflen, const char *prompt) {
|
||||
size_t plen = strlen(prompt);
|
||||
size_t pos = 0;
|
||||
size_t len = 0;
|
||||
size_t cols = getColumns();
|
||||
int history_index = 0;
|
||||
|
||||
buf[0] = '\0';
|
||||
buflen--; /* Make sure there is always space for the nulterm */
|
||||
|
||||
/* The latest history entry is always our current buffer, that
|
||||
* initially is just an empty string. */
|
||||
linenoiseHistoryAdd("");
|
||||
|
||||
if (write(fd,prompt,plen) == -1) return -1;
|
||||
while(1) {
|
||||
char c;
|
||||
int nread;
|
||||
char seq[2], seq2[2];
|
||||
|
||||
nread = read(fd,&c,1);
|
||||
if (nread <= 0) return len;
|
||||
|
||||
/* Only autocomplete when the callback is set. It returns < 0 when
|
||||
* there was an error reading from fd. Otherwise it will return the
|
||||
* character that should be handled next. */
|
||||
if (c == 9 && completionCallback != NULL) {
|
||||
c = completeLine(fd,prompt,buf,buflen,&len,&pos,cols);
|
||||
/* Return on errors */
|
||||
if (c < 0) return len;
|
||||
/* Read next character when 0 */
|
||||
if (c == 0) continue;
|
||||
}
|
||||
|
||||
switch(c) {
|
||||
case 13: /* enter */
|
||||
history_len--;
|
||||
free(history[history_len]);
|
||||
return (int)len;
|
||||
case 3: /* ctrl-c */
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
case 127: /* backspace */
|
||||
case 8: /* ctrl-h */
|
||||
if (pos > 0 && len > 0) {
|
||||
memmove(buf+pos-1,buf+pos,len-pos);
|
||||
pos--;
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
break;
|
||||
case 4: /* ctrl-d, remove char at right of cursor */
|
||||
if (len > 1 && pos < (len-1)) {
|
||||
memmove(buf+pos,buf+pos+1,len-pos);
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
} else if (len == 0) {
|
||||
history_len--;
|
||||
free(history[history_len]);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 20: /* ctrl-t */
|
||||
if (pos > 0 && pos < len) {
|
||||
int aux = buf[pos-1];
|
||||
buf[pos-1] = buf[pos];
|
||||
buf[pos] = aux;
|
||||
if (pos != len-1) pos++;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
break;
|
||||
case 2: /* ctrl-b */
|
||||
goto left_arrow;
|
||||
case 6: /* ctrl-f */
|
||||
goto right_arrow;
|
||||
case 16: /* ctrl-p */
|
||||
seq[1] = 65;
|
||||
goto up_down_arrow;
|
||||
case 14: /* ctrl-n */
|
||||
seq[1] = 66;
|
||||
goto up_down_arrow;
|
||||
break;
|
||||
case 27: /* escape sequence */
|
||||
if (read(fd,seq,2) == -1) break;
|
||||
if (seq[0] == 91 && seq[1] == 68) {
|
||||
left_arrow:
|
||||
/* left arrow */
|
||||
if (pos > 0) {
|
||||
pos--;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else if (seq[0] == 91 && seq[1] == 67) {
|
||||
right_arrow:
|
||||
/* right arrow */
|
||||
if (pos != len) {
|
||||
pos++;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else if (seq[0] == 91 && (seq[1] == 65 || seq[1] == 66)) {
|
||||
up_down_arrow:
|
||||
/* up and down arrow: history */
|
||||
if (history_len > 1) {
|
||||
/* Update the current history entry before to
|
||||
* overwrite it with tne next one. */
|
||||
free(history[history_len-1-history_index]);
|
||||
history[history_len-1-history_index] = strdup(buf);
|
||||
/* Show the new entry */
|
||||
history_index += (seq[1] == 65) ? 1 : -1;
|
||||
if (history_index < 0) {
|
||||
history_index = 0;
|
||||
break;
|
||||
} else if (history_index >= history_len) {
|
||||
history_index = history_len-1;
|
||||
break;
|
||||
}
|
||||
strncpy(buf,history[history_len-1-history_index],buflen);
|
||||
buf[buflen] = '\0';
|
||||
len = pos = strlen(buf);
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else if (seq[0] == 91 && seq[1] > 48 && seq[1] < 55) {
|
||||
/* extended escape */
|
||||
if (read(fd,seq2,2) == -1) break;
|
||||
if (seq[1] == 51 && seq2[0] == 126) {
|
||||
/* delete */
|
||||
if (len > 0 && pos < len) {
|
||||
memmove(buf+pos,buf+pos+1,len-pos-1);
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (len < buflen) {
|
||||
if (len == pos) {
|
||||
buf[pos] = c;
|
||||
pos++;
|
||||
len++;
|
||||
buf[len] = '\0';
|
||||
if (plen+len < cols) {
|
||||
/* Avoid a full update of the line in the
|
||||
* trivial case. */
|
||||
if (write(fd,&c,1) == -1) return -1;
|
||||
} else {
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
} else {
|
||||
memmove(buf+pos+1,buf+pos,len-pos);
|
||||
buf[pos] = c;
|
||||
len++;
|
||||
pos++;
|
||||
buf[len] = '\0';
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 21: /* Ctrl+u, delete the whole line. */
|
||||
buf[0] = '\0';
|
||||
pos = len = 0;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 11: /* Ctrl+k, delete from current to end of line. */
|
||||
buf[pos] = '\0';
|
||||
len = pos;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 1: /* Ctrl+a, go to the start of the line */
|
||||
pos = 0;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 5: /* ctrl+e, go to the end of the line */
|
||||
pos = len;
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
break;
|
||||
case 12: /* ctrl+l, clear screen */
|
||||
linenoiseClearScreen();
|
||||
refreshLine(fd,prompt,buf,len,pos,cols);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
|
||||
int fd = STDIN_FILENO;
|
||||
int count;
|
||||
|
||||
if (buflen == 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (!isatty(STDIN_FILENO)) {
|
||||
if (fgets(buf, buflen, stdin) == NULL) return -1;
|
||||
count = strlen(buf);
|
||||
if (count && buf[count-1] == '\n') {
|
||||
count--;
|
||||
buf[count] = '\0';
|
||||
}
|
||||
} else {
|
||||
if (enableRawMode(fd) == -1) return -1;
|
||||
count = linenoisePrompt(fd, buf, buflen, prompt);
|
||||
disableRawMode(fd);
|
||||
printf("\n");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
char *linenoise(const char *prompt) {
|
||||
char buf[LINENOISE_MAX_LINE];
|
||||
int count;
|
||||
|
||||
if (isUnsupportedTerm()) {
|
||||
size_t len;
|
||||
|
||||
printf("%s",prompt);
|
||||
fflush(stdout);
|
||||
if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL;
|
||||
len = strlen(buf);
|
||||
while(len && (buf[len-1] == '\n' || buf[len-1] == '\r')) {
|
||||
len--;
|
||||
buf[len] = '\0';
|
||||
}
|
||||
return strdup(buf);
|
||||
} else {
|
||||
count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt);
|
||||
if (count == -1) return NULL;
|
||||
return strdup(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register a callback function to be called for tab-completion. */
|
||||
void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) {
|
||||
completionCallback = fn;
|
||||
}
|
||||
|
||||
void linenoiseAddCompletion(linenoiseCompletions *lc, char *str) {
|
||||
size_t len = strlen(str);
|
||||
char *copy = malloc(len+1);
|
||||
memcpy(copy,str,len+1);
|
||||
lc->cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1));
|
||||
lc->cvec[lc->len++] = copy;
|
||||
}
|
||||
|
||||
/* Using a circular buffer is smarter, but a bit more complex to handle. */
|
||||
int linenoiseHistoryAdd(const char *line) {
|
||||
char *linecopy;
|
||||
|
||||
if (history_max_len == 0) return 0;
|
||||
if (history == NULL) {
|
||||
history = malloc(sizeof(char*)*history_max_len);
|
||||
if (history == NULL) return 0;
|
||||
memset(history,0,(sizeof(char*)*history_max_len));
|
||||
}
|
||||
linecopy = strdup(line);
|
||||
if (!linecopy) return 0;
|
||||
if (history_len == history_max_len) {
|
||||
free(history[0]);
|
||||
memmove(history,history+1,sizeof(char*)*(history_max_len-1));
|
||||
history_len--;
|
||||
}
|
||||
history[history_len] = linecopy;
|
||||
history_len++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int linenoiseHistorySetMaxLen(int len) {
|
||||
char **new;
|
||||
|
||||
if (len < 1) return 0;
|
||||
if (history) {
|
||||
int tocopy = history_len;
|
||||
|
||||
new = malloc(sizeof(char*)*len);
|
||||
if (new == NULL) return 0;
|
||||
if (len < tocopy) tocopy = len;
|
||||
memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy);
|
||||
free(history);
|
||||
history = new;
|
||||
}
|
||||
history_max_len = len;
|
||||
if (history_len > history_max_len)
|
||||
history_len = history_max_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Save the history in the specified file. On success 0 is returned
|
||||
* otherwise -1 is returned. */
|
||||
int linenoiseHistorySave(char *filename) {
|
||||
FILE *fp = fopen(filename,"w");
|
||||
int j;
|
||||
|
||||
if (fp == NULL) return -1;
|
||||
for (j = 0; j < history_len; j++)
|
||||
fprintf(fp,"%s\n",history[j]);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load the history from the specified file. If the file does not exist
|
||||
* zero is returned and no operation is performed.
|
||||
*
|
||||
* If the file exists and the operation succeeded 0 is returned, otherwise
|
||||
* on error -1 is returned. */
|
||||
int linenoiseHistoryLoad(char *filename) {
|
||||
FILE *fp = fopen(filename,"r");
|
||||
char buf[LINENOISE_MAX_LINE];
|
||||
|
||||
if (fp == NULL) return -1;
|
||||
|
||||
while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) {
|
||||
char *p;
|
||||
|
||||
p = strchr(buf,'\r');
|
||||
if (!p) p = strchr(buf,'\n');
|
||||
if (p) *p = '\0';
|
||||
linenoiseHistoryAdd(buf);
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
@ -51,7 +51,7 @@ static void MaybeByteSwap(char *number, size_t numbersize, DumpState *D)
|
||||
int platform_little_endian = *(char*)&x;
|
||||
if (platform_little_endian != D->target.little_endian)
|
||||
{
|
||||
int i;
|
||||
unsigned long i;
|
||||
for (i=0; i<numbersize/2; i++)
|
||||
{
|
||||
char temp = number[i];
|
||||
@ -91,7 +91,7 @@ static void DumpInt(int x, DumpState* D)
|
||||
DumpIntWithSize(x,D->target.sizeof_int,D);
|
||||
}
|
||||
|
||||
static void DumpSize(int32_t x, DumpState* D)
|
||||
static void DumpSize(uint32_t x, DumpState* D)
|
||||
{
|
||||
/* dump unsigned integer */
|
||||
switch(D->target.sizeof_strsize_t) {
|
||||
@ -179,7 +179,7 @@ static void DumpString(const TString* s, DumpState* D)
|
||||
}
|
||||
else
|
||||
{
|
||||
strsize_t size=s->tsv.len+1; /* include trailing '\0' */
|
||||
strsize_t size=( strsize_t )s->tsv.len+1; /* include trailing '\0' */
|
||||
DumpSize(size,D);
|
||||
DumpBlock(getstr(s),size,D);
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ static int math_abs (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_sin (lua_State *L) {
|
||||
lua_pushnumber(L, sin(luaL_checknumber(L, 1)));
|
||||
return 1;
|
||||
@ -107,6 +109,20 @@ static int math_modf (lua_State *L) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
#else // #ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
// In integer math, floor() and ceil() give the same value;
|
||||
// having them in the integer library allows you to write code that
|
||||
// works in both integer and floating point versions of Lua.
|
||||
// This identity function is used for them.
|
||||
|
||||
static int math_identity (lua_State *L) {
|
||||
lua_pushnumber(L, luaL_checknumber(L, 1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // #ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
// Integer square root for integer version
|
||||
static lua_Number isqrt(lua_Number x)
|
||||
@ -142,6 +158,8 @@ static int math_sqrt (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_pow (lua_State *L) {
|
||||
lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));
|
||||
return 1;
|
||||
@ -184,7 +202,7 @@ static int math_ldexp (lua_State *L) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif // #ifdef LUA_NUMBER_INTEGRAL
|
||||
|
||||
static int math_min (lua_State *L) {
|
||||
int n = lua_gettop(L); /* number of arguments */
|
||||
@ -284,6 +302,8 @@ static int math_randomseed (lua_State *L) {
|
||||
const LUA_REG_TYPE math_map[] = {
|
||||
#ifdef LUA_NUMBER_INTEGRAL
|
||||
{LSTRKEY("abs"), LFUNCVAL(math_abs)},
|
||||
{LSTRKEY("ceil"), LFUNCVAL(math_identity)},
|
||||
{LSTRKEY("floor"), LFUNCVAL(math_identity)},
|
||||
{LSTRKEY("max"), LFUNCVAL(math_max)},
|
||||
{LSTRKEY("min"), LFUNCVAL(math_min)},
|
||||
{LSTRKEY("random"), LFUNCVAL(math_random)},
|
||||
|
@ -160,8 +160,12 @@
|
||||
#if !defined LUA_NUMBER_INTEGRAL
|
||||
#define LUA_INTEGER ptrdiff_t
|
||||
#else
|
||||
#define LUA_INTEGER long
|
||||
#endif
|
||||
#if !defined LUA_INTEGRAL_LONGLONG
|
||||
#define LUA_INTEGER long
|
||||
#else
|
||||
#define LUA_INTEGER long long
|
||||
#endif // #if !defined LUA_INTEGRAL_LONGLONG
|
||||
#endif // #if !defined LUA_NUMBER_INTEGRAL
|
||||
|
||||
/*
|
||||
@@ LUA_API is a mark for all core API functions.
|
||||
@ -300,6 +304,13 @@
|
||||
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
|
||||
add_history(lua_tostring(L, idx)); /* add it to history */
|
||||
#define lua_freeline(L,b) ((void)L, free(b))
|
||||
#elif defined(LUA_USE_LINENOISE) // #if defined(LUA_USE_READLINE)
|
||||
#include "linenoise_posix.h"
|
||||
#define lua_readline(L,b,p) ((void)L, ((b)=linenoise(p)) != NULL)
|
||||
#define lua_saveline(L,idx) \
|
||||
if (lua_strlen(L,idx) > 0) /* non-empty line? */ \
|
||||
linenoiseHistoryAdd(lua_tostring(L, idx)); /* add it to history */
|
||||
#define lua_freeline(L,b) ((void)L, free(b))
|
||||
#else // #if defined(LUA_USE_READLINE)
|
||||
#define lua_readline(L,b,p) \
|
||||
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
|
||||
@ -511,7 +522,7 @@
|
||||
@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
|
||||
@* (must be smaller than 250).
|
||||
*/
|
||||
#define LUAI_MAXUPVALUES 10
|
||||
#define LUAI_MAXUPVALUES 60
|
||||
|
||||
|
||||
/*
|
||||
@ -546,7 +557,7 @@
|
||||
%G. */
|
||||
|
||||
#if defined LUA_NUMBER_INTEGRAL
|
||||
#define LUA_NUMBER long
|
||||
#define LUA_NUMBER LUA_INTEGER
|
||||
#else
|
||||
#define LUA_NUMBER_DOUBLE
|
||||
#define LUA_NUMBER double
|
||||
@ -567,20 +578,28 @@
|
||||
@@ lua_str2number converts a string to a number.
|
||||
*/
|
||||
#if defined LUA_NUMBER_INTEGRAL
|
||||
#define LUA_NUMBER_SCAN "%ld"
|
||||
#define LUA_NUMBER_FMT "%ld"
|
||||
#if !defined LUA_INTEGRAL_LONGLONG
|
||||
#define LUA_NUMBER_SCAN "%ld"
|
||||
#define LUA_NUMBER_FMT "%ld"
|
||||
#else
|
||||
#define LUA_NUMBER_SCAN "%lld"
|
||||
#define LUA_NUMBER_FMT "%lld"
|
||||
#endif // #if !defined LUA_INTEGRAL_LONGLONG
|
||||
#else
|
||||
#define LUA_NUMBER_SCAN "%lf"
|
||||
#define LUA_NUMBER_FMT "%.14g"
|
||||
#endif
|
||||
#endif // #if defined LUA_NUMBER_INTEGRAL
|
||||
#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))
|
||||
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
|
||||
#if defined LUA_NUMBER_INTEGRAL
|
||||
#define lua_str2number(s,p) strtol((s), (p), 10)
|
||||
#if !defined LUA_INTEGRAL_LONGLONG
|
||||
#define lua_str2number(s,p) strtol((s), (p), 10)
|
||||
#else
|
||||
#define lua_str2number(s,p) strtoll((s), (p), 10)
|
||||
#endif // #if !defined LUA_INTEGRAL_LONGLONG
|
||||
#else
|
||||
#define lua_str2number(s,p) strtod((s), (p))
|
||||
#endif
|
||||
|
||||
#endif // #if defined LUA_NUMBER_INTEGRAL
|
||||
|
||||
/*
|
||||
@@ The luai_num* macros define the primitive operations over numbers.
|
||||
@ -820,7 +839,7 @@ union luai_Cast { double l_d; long l_l; };
|
||||
** CHANGE them if your system supports long long or does not support long.
|
||||
*/
|
||||
|
||||
#if defined(LUA_USELONGLONG)
|
||||
#if defined(LUA_USELONGLONG) || defined(LUA_INTEGRAL_LONGLONG)
|
||||
|
||||
#define LUA_INTFRMLEN "ll"
|
||||
#define LUA_INTFRM_T long long
|
||||
|
@ -82,7 +82,7 @@ void transport_accept (Transport *tpt, Transport *atpt)
|
||||
// Read & Write to Transport
|
||||
void transport_read_buffer (Transport *tpt, u8 *buffer, int length)
|
||||
{
|
||||
u32 n;
|
||||
int n;
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
|
||||
|
@ -7,18 +7,32 @@
|
||||
|
||||
#if defined( BUILD_RPC )
|
||||
|
||||
// Setup Transport
|
||||
void transport_init (Transport *tpt)
|
||||
// Buffer for async dispatch
|
||||
int adispatch_buff = -1;
|
||||
|
||||
void set_adispatch_buff( int i )
|
||||
{
|
||||
tpt->fd = INVALID_TRANSPORT;
|
||||
adispatch_buff = i;
|
||||
}
|
||||
|
||||
// Setup Transport
|
||||
void transport_init( Transport *tpt )
|
||||
{
|
||||
tpt->fd = INVALID_TRANSPORT;
|
||||
tpt->tmr_id = 0;
|
||||
}
|
||||
|
||||
// Open Listener / Server
|
||||
void transport_open_listener(lua_State *L, ServerHandle *handle)
|
||||
// Read a char from serial buffer
|
||||
int transport_get_char(Transport *t)
|
||||
{
|
||||
// Get args & Set up connection
|
||||
unsigned uart_id, tmr_id;
|
||||
return platform_uart_recv( t->fd, t->tmr_id, 0 );
|
||||
}
|
||||
|
||||
// Open Listener / Server
|
||||
void transport_open_listener( lua_State *L, ServerHandle *handle )
|
||||
{
|
||||
// Get args & Set up connection
|
||||
unsigned uart_id, tmr_id;
|
||||
|
||||
check_num_args( L,3 ); // 1st arg is uart num, 2nd arg is tmr_id, 3nd is handle
|
||||
if ( !lua_isnumber( L, 1 ) )
|
||||
@ -36,15 +50,18 @@ void transport_open_listener(lua_State *L, ServerHandle *handle)
|
||||
if( !platform_timer_exists( tmr_id ) )
|
||||
luaL_error( L, "invalid timer id" );
|
||||
|
||||
handle->ltpt.fd = ( int )uart_id;
|
||||
handle->ltpt.tmr_id = tmr_id;
|
||||
handle->ltpt.fd = ( int )uart_id;
|
||||
handle->ltpt.tmr_id = tmr_id;
|
||||
|
||||
// Setup uart
|
||||
platform_uart_setup( (unsigned int) uart_id, 115200, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
}
|
||||
|
||||
// Open Connection / Client
|
||||
int transport_open_connection(lua_State *L, Handle *handle)
|
||||
{
|
||||
// Get args & Set up connection
|
||||
unsigned uart_id, tmr_id;
|
||||
// Get args & Set up connection
|
||||
unsigned uart_id, tmr_id;
|
||||
|
||||
check_num_args( L,3 ); // 1st arg is uart num, 2nd arg is tmr_id, 3nd is handle
|
||||
if ( !lua_isnumber( L, 1 ) )
|
||||
@ -59,80 +76,104 @@ int transport_open_connection(lua_State *L, Handle *handle)
|
||||
tmr_id = lua_tonumber( L, 1 );
|
||||
MOD_CHECK_ID( timer, tmr_id );
|
||||
|
||||
handle->tpt.fd = ( int )uart_id;
|
||||
handle->tpt.tmr_id = tmr_id;
|
||||
return 1;
|
||||
adispatch_buff = -1;
|
||||
|
||||
handle->tpt.fd = ( int )uart_id;
|
||||
handle->tpt.tmr_id = tmr_id;
|
||||
|
||||
// Setup uart
|
||||
platform_uart_setup( (unsigned int) uart_id, 115200, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Accept Connection
|
||||
void transport_accept (Transport *tpt, Transport *atpt)
|
||||
void transport_accept( Transport *tpt, Transport *atpt )
|
||||
{
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
atpt->fd = tpt->fd;
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
atpt->fd = tpt->fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void transport_read_buffer (Transport *tpt, u8 *buffer, int length)
|
||||
void transport_read_buffer( Transport *tpt, u8 *buffer, int length )
|
||||
{
|
||||
int n = 0;
|
||||
int c;
|
||||
struct exception e;
|
||||
int uart_timeout = PLATFORM_UART_INFINITE_TIMEOUT; // not sure whether we should always follow this
|
||||
int n = 0;
|
||||
int c;
|
||||
struct exception e;
|
||||
timer_data_type uart_timeout = PLATFORM_TIMER_INF_TIMEOUT; // not sure whether we should always follow this
|
||||
// int uart_timeout = 100000;
|
||||
|
||||
while( n < length )
|
||||
{
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
c = platform_uart_recv( tpt->fd, tpt->tmr_id, uart_timeout );
|
||||
while( n < length )
|
||||
{
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
|
||||
if ( adispatch_buff < 0 )
|
||||
c = platform_uart_recv( tpt->fd, tpt->tmr_id, uart_timeout );
|
||||
else
|
||||
{
|
||||
c = adispatch_buff;
|
||||
adispatch_buff = -1;
|
||||
}
|
||||
|
||||
if( c < 0 )
|
||||
{
|
||||
// uart_timeout = 1000000; // Reset and use timeout of 1s
|
||||
e.errnum = ERR_NODATA;
|
||||
e.type = nonfatal;
|
||||
Throw( e );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[ n ] = ( u8 )c;
|
||||
n++;
|
||||
}
|
||||
// After getting one char of a read remainder
|
||||
// should follow within a timeout of 0.1 sec
|
||||
uart_timeout = 100000;
|
||||
{
|
||||
// uart_timeout = 1000000; // Reset and use timeout of 1s
|
||||
e.errnum = ERR_NODATA;
|
||||
e.type = nonfatal;
|
||||
Throw( e );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[ n ] = ( u8 )c;
|
||||
n++;
|
||||
}
|
||||
// After getting one char of a read remainder
|
||||
// should follow within a timeout of 0.1 sec
|
||||
uart_timeout = 100000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void transport_write_buffer( Transport *tpt, const u8 *buffer, int length )
|
||||
{
|
||||
int i;
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
int i;
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
|
||||
for( i = 0; i < length; i ++ )
|
||||
platform_uart_send( CON_UART_ID, buffer[ i ] );
|
||||
for( i = 0; i < length; i ++ )
|
||||
platform_uart_send( tpt->fd, buffer[ i ] );
|
||||
}
|
||||
|
||||
// Check if data is available on connection without reading:
|
||||
// - 1 = data available, 0 = no data available
|
||||
int transport_readable (Transport *tpt)
|
||||
// - 1 = data available, 0 = no data available
|
||||
int transport_readable( Transport *tpt )
|
||||
{
|
||||
return 1; // no really easy way to check this unless platform support is added
|
||||
int c;
|
||||
|
||||
if ( adispatch_buff >= 0 ) // if we have a char already
|
||||
return 1;
|
||||
else // check if a char is ready to be read
|
||||
{
|
||||
c = transport_get_char( tpt );
|
||||
if( c > 0)
|
||||
{
|
||||
adispatch_buff = c;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if transport is open:
|
||||
// - 1 = connection open, 0 = connection closed
|
||||
int transport_is_open (Transport *tpt)
|
||||
// - 1 = connection open, 0 = connection closed
|
||||
int transport_is_open( Transport *tpt )
|
||||
{
|
||||
return ( tpt->fd != INVALID_TRANSPORT );
|
||||
return ( tpt->fd != INVALID_TRANSPORT );
|
||||
}
|
||||
|
||||
// Shut down connection
|
||||
void transport_close (Transport *tpt)
|
||||
void transport_close( Transport *tpt )
|
||||
{
|
||||
tpt->fd = INVALID_TRANSPORT;
|
||||
tpt->fd = INVALID_TRANSPORT;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -48,7 +48,7 @@ extern char etext[];
|
||||
#endif
|
||||
|
||||
#ifndef RPC_TIMER_ID
|
||||
#define RPC_TIMER_ID CON_TIMER_ID
|
||||
#define RPC_TIMER_ID PLATFORM_TIMER_SYS_ID
|
||||
#endif
|
||||
|
||||
#ifndef RPC_UART_SPEED
|
||||
|
@ -20,30 +20,30 @@ static int adc_maxval( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
res = platform_adc_op( id, PLATFORM_ADC_GET_MAXVAL, 0 );
|
||||
res = platform_adc_get_maxval( id );
|
||||
lua_pushinteger( L, res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: realclock = setclock( id, clock, [timer_id] )
|
||||
// Lua: realclock = setclock( id, freq, [timer_id] )
|
||||
static int adc_setclock( lua_State* L )
|
||||
{
|
||||
u32 clock;
|
||||
u32 freq;
|
||||
unsigned id, timer_id = 0;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
clock = luaL_checkinteger( L, 2 );
|
||||
if ( clock > 0 )
|
||||
freq = luaL_checkinteger( L, 2 );
|
||||
if ( freq > 0 )
|
||||
{
|
||||
timer_id = luaL_checkinteger( L, 3 );
|
||||
MOD_CHECK_ID( timer, timer_id );
|
||||
MOD_CHECK_RES_ID( adc, id, timer, timer_id );
|
||||
}
|
||||
|
||||
platform_adc_op( id, PLATFORM_ADC_OP_SET_TIMER, timer_id );
|
||||
clock = platform_adc_op( id, PLATFORM_ADC_OP_SET_CLOCK, clock );
|
||||
lua_pushinteger( L, clock );
|
||||
platform_adc_set_timer( id, timer_id );
|
||||
freq = platform_adc_set_clock( id, freq );
|
||||
lua_pushinteger( L, freq );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -54,7 +54,7 @@ static int adc_isdone( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
lua_pushinteger( L, platform_adc_op( id, PLATFORM_ADC_IS_DONE, 0 ) );
|
||||
lua_pushinteger( L, platform_adc_is_done( id ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ static int adc_setblocking( lua_State* L )
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( adc, id );
|
||||
mode = luaL_checkinteger( L, 2 );
|
||||
platform_adc_op( id, PLATFORM_ADC_SET_BLOCKING, mode );
|
||||
platform_adc_set_blocking( id, mode );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ static int adc_setsmoothing( lua_State* L )
|
||||
length = luaL_checkinteger( L, 2 );
|
||||
if ( !( length & ( length - 1 ) ) )
|
||||
{
|
||||
res = platform_adc_op( id, PLATFORM_ADC_SET_SMOOTHING, length );
|
||||
res = platform_adc_set_smoothing( id, length );
|
||||
if ( res == PLATFORM_ERR )
|
||||
return luaL_error( L, "Buffer allocation failed." );
|
||||
else
|
||||
@ -185,7 +185,7 @@ static int adc_getsamples( lua_State* L )
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
lua_rawseti( L, -2, i );
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -201,21 +201,21 @@ static int adc_insertsamples( lua_State* L )
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
|
||||
startidx = luaL_checkinteger( L, 3 );
|
||||
if ( startidx <= 0 )
|
||||
if ( startidx <= 0 )
|
||||
return luaL_error( L, "idx must be > 0" );
|
||||
|
||||
count = luaL_checkinteger(L, 4 );
|
||||
if ( count == 0 )
|
||||
if ( count == 0 )
|
||||
return luaL_error( L, "count must be > 0" );
|
||||
|
||||
bcnt = adc_wait_samples( id, count );
|
||||
|
||||
for( i = startidx; i < ( count + startidx ); i ++ )
|
||||
{
|
||||
if ( i < bcnt + startidx )
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
else
|
||||
lua_pushnil( L ); // nil-out values where we don't have enough samples
|
||||
if ( i < bcnt + startidx )
|
||||
lua_pushinteger( L, adc_get_processed_sample( id ) );
|
||||
else
|
||||
lua_pushnil( L ); // nil-out values where we don't have enough samples
|
||||
|
||||
lua_rawseti( L, 2, i );
|
||||
}
|
||||
|
@ -62,6 +62,12 @@ LUALIB_API int ( luaopen_i2c )( lua_State *L );
|
||||
if( !platform_ ## mod ## _exists( id ) )\
|
||||
return luaL_error( L, #mod" %d does not exist", ( unsigned )id )
|
||||
|
||||
#define MOD_CHECK_TIMER( id )\
|
||||
if( id == PLATFORM_TIMER_SYS_ID && !platform_timer_sys_available() )\
|
||||
return luaL_error( L, "the system timer is not available on this platform" );\
|
||||
if( !platform_timer_exists( id ) )\
|
||||
return luaL_error( L, "timer %d does not exist", ( unsigned )id )\
|
||||
|
||||
#define MOD_CHECK_RES_ID( mod, id, resmod, resid )\
|
||||
if( !platform_ ## mod ## _check_ ## resmod ## _id( id, resid ) )\
|
||||
return luaL_error( L, #resmod" %d not valid with " #mod " %d", ( unsigned )resid, ( unsigned )id )
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
// Modified by BogdanM for eLua
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "auxmods.h"
|
||||
#include "type.h"
|
||||
#include "lrotable.h"
|
||||
|
@ -45,7 +45,7 @@ static int bitarray_new( lua_State *L )
|
||||
if( lua_isnumber( L, 1 ) )
|
||||
{
|
||||
// capacity, [element_size_bits], [fill]
|
||||
capacity = luaL_checkinteger( L, 1 );
|
||||
capacity = ( u32 )luaL_checkinteger( L, 1 );
|
||||
if( lua_isnumber( L, 2 ) )
|
||||
elsize = luaL_checkinteger( L, 2 );
|
||||
else
|
||||
@ -69,7 +69,7 @@ static int bitarray_new( lua_State *L )
|
||||
elsize = 8;
|
||||
if( ( temp << 3 ) % elsize )
|
||||
return luaL_error( L, "length is not a multiple of element size." );
|
||||
capacity = ( temp << 3 ) / elsize;
|
||||
capacity = ( u32 )( temp << 3 ) / elsize;
|
||||
}
|
||||
else
|
||||
return luaL_error( L, "invalid arguments." );
|
||||
@ -141,7 +141,7 @@ static int bitarray_get( lua_State *L )
|
||||
u32 idx;
|
||||
|
||||
pa = bitarray_check( L );
|
||||
idx = luaL_checkinteger( L, 2 );
|
||||
idx = ( u32 )luaL_checkinteger( L, 2 );
|
||||
if( ( idx <= 0 ) || ( idx > pa->capacity ) )
|
||||
return luaL_error( L, "invalid index." );
|
||||
lua_pushinteger( L, bitarray_getval( pa, idx ) );
|
||||
@ -156,8 +156,8 @@ static int bitarray_set( lua_State *L )
|
||||
u8 rest, mask;
|
||||
|
||||
pa = bitarray_check( L );
|
||||
idx = luaL_checkinteger( L, 2 );
|
||||
newval = luaL_checkinteger( L, 3 );
|
||||
idx = ( u32 )luaL_checkinteger( L, 2 );
|
||||
newval = ( u32 )luaL_checkinteger( L, 3 );
|
||||
if( ( idx <= 0 ) || ( idx > pa->capacity ) )
|
||||
return luaL_error( L, "invalid index." );
|
||||
idx --;
|
||||
@ -206,7 +206,7 @@ static int bitarray_iter( lua_State *L )
|
||||
u32 idx;
|
||||
|
||||
pa = bitarray_check( L );
|
||||
idx = luaL_checkinteger( L, 2 ) + 1;
|
||||
idx = ( u32 )luaL_checkinteger( L, 2 ) + 1;
|
||||
if( idx <= pa->capacity )
|
||||
{
|
||||
lua_pushinteger( L, idx );
|
||||
|
@ -13,10 +13,12 @@
|
||||
static int i2c_setup( lua_State *L )
|
||||
{
|
||||
unsigned id = luaL_checkinteger( L, 1 );
|
||||
u32 speed = ( u32 )luaL_checkinteger( L, 2 );
|
||||
s32 speed = ( s32 )luaL_checkinteger( L, 2 );
|
||||
|
||||
MOD_CHECK_ID( i2c, id );
|
||||
lua_pushinteger( L, platform_i2c_setup( id, speed ) );
|
||||
if (speed <= 0)
|
||||
return luaL_error( L, "frequency must be > 0" );
|
||||
lua_pushinteger( L, platform_i2c_setup( id, (u32)speed ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -44,11 +46,13 @@ static int i2c_stop( lua_State *L )
|
||||
static int i2c_address( lua_State *L )
|
||||
{
|
||||
unsigned id = luaL_checkinteger( L, 1 );
|
||||
u16 address = ( u16 )luaL_checkinteger( L, 2 );
|
||||
int address = luaL_checkinteger( L, 2 );
|
||||
int direction = luaL_checkinteger( L, 3 );
|
||||
|
||||
MOD_CHECK_ID( i2c, id );
|
||||
lua_pushboolean( L, platform_i2c_send_address( id, address, direction ) );
|
||||
if ( address < 0 || address > 127 )
|
||||
return luaL_error( L, "slave address must be from 0 to 127" );
|
||||
lua_pushboolean( L, platform_i2c_send_address( id, (u16)address, direction ) );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -68,11 +72,13 @@ static int i2c_write( lua_State *L )
|
||||
return luaL_error( L, "invalid number of arguments" );
|
||||
for( argn = 2; argn <= lua_gettop( L ); argn ++ )
|
||||
{
|
||||
if( lua_isnumber( L, argn ) )
|
||||
// lua_isnumber() would silently convert a string of digits to an integer
|
||||
// whereas here strings are handled separately.
|
||||
if( lua_type( L, argn ) == LUA_TNUMBER )
|
||||
{
|
||||
numdata = ( int )luaL_checkinteger( L, argn );
|
||||
if( numdata < 0 || numdata > 255 )
|
||||
return luaL_error( L, "numeric data can be between 0 and 255" );
|
||||
return luaL_error( L, "numeric data must be from 0 to 255" );
|
||||
if( platform_i2c_send_byte( id, numdata ) != 1 )
|
||||
break;
|
||||
wrote ++;
|
||||
@ -83,10 +89,10 @@ static int i2c_write( lua_State *L )
|
||||
for( i = 0; i < datalen; i ++ )
|
||||
{
|
||||
lua_rawgeti( L, argn, i + 1 );
|
||||
numdata = luaL_checkinteger( L, -1 );
|
||||
numdata = ( int )luaL_checkinteger( L, -1 );
|
||||
lua_pop( L, 1 );
|
||||
if( numdata < 0 || numdata > 255 )
|
||||
return luaL_error( L, "numeric data can be between 0 and 255" );
|
||||
return luaL_error( L, "numeric data must be from 0 to 255" );
|
||||
if( platform_i2c_send_byte( id, numdata ) == 0 )
|
||||
break;
|
||||
}
|
||||
|
@ -10,25 +10,25 @@
|
||||
* Modified by BogdanM for eLua
|
||||
*/
|
||||
|
||||
#define OP_ZSTRING 'z' /* zero-terminated string */
|
||||
#define OP_BSTRING 'p' /* string preceded by length byte */
|
||||
#define OP_WSTRING 'P' /* string preceded by length word */
|
||||
#define OP_SSTRING 'a' /* string preceded by length size_t */
|
||||
#define OP_STRING 'A' /* string */
|
||||
#define OP_FLOAT 'f' /* float */
|
||||
#define OP_DOUBLE 'd' /* double */
|
||||
#define OP_NUMBER 'n' /* Lua number */
|
||||
#define OP_CHAR 'c' /* char */
|
||||
#define OP_BYTE 'b' /* byte = unsigned char */
|
||||
#define OP_SHORT 'h' /* short */
|
||||
#define OP_USHORT 'H' /* unsigned short */
|
||||
#define OP_INT 'i' /* int */
|
||||
#define OP_UINT 'I' /* unsigned int */
|
||||
#define OP_LONG 'l' /* long */
|
||||
#define OP_ULONG 'L' /* unsigned long */
|
||||
#define OP_LITTLEENDIAN '<' /* little endian */
|
||||
#define OP_BIGENDIAN '>' /* big endian */
|
||||
#define OP_NATIVE '=' /* native endian */
|
||||
#define OP_ZSTRING 'z' /* zero-terminated string */
|
||||
#define OP_BSTRING 'p' /* string preceded by length byte */
|
||||
#define OP_WSTRING 'P' /* string preceded by length word */
|
||||
#define OP_SSTRING 'a' /* string preceded by length size_t */
|
||||
#define OP_STRING 'A' /* string */
|
||||
#define OP_FLOAT 'f' /* float */
|
||||
#define OP_DOUBLE 'd' /* double */
|
||||
#define OP_NUMBER 'n' /* Lua number */
|
||||
#define OP_CHAR 'c' /* char */
|
||||
#define OP_BYTE 'b' /* byte = unsigned char */
|
||||
#define OP_SHORT 'h' /* short */
|
||||
#define OP_USHORT 'H' /* unsigned short */
|
||||
#define OP_INT 'i' /* int */
|
||||
#define OP_UINT 'I' /* unsigned int */
|
||||
#define OP_LONG 'l' /* long */
|
||||
#define OP_ULONG 'L' /* unsigned long */
|
||||
#define OP_LITTLEENDIAN '<' /* little endian */
|
||||
#define OP_BIGENDIAN '>' /* big endian */
|
||||
#define OP_NATIVE '=' /* native endian */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
@ -62,44 +62,44 @@ static void doswap(int swap, void *p, size_t n)
|
||||
{
|
||||
char *a=p;
|
||||
int i,j;
|
||||
for (i=0, j=n-1, n=n/2; n--; i++, j--)
|
||||
for (i=0, j=( int )n-1, n=n/2; n--; i++, j--)
|
||||
{
|
||||
char t=a[i]; a[i]=a[j]; a[j]=t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define UNPACKNUMBER(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T a; \
|
||||
int m=sizeof(a); \
|
||||
if (i+m>len) goto done; \
|
||||
memcpy(&a,s+i,m); \
|
||||
i+=m; \
|
||||
doswap(swap,&a,m); \
|
||||
lua_pushnumber(L,(lua_Number)a); \
|
||||
++n; \
|
||||
break; \
|
||||
#define UNPACKNUMBER(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T a; \
|
||||
int m=sizeof(a); \
|
||||
if (((unsigned long)i+m)>len) goto done; \
|
||||
memcpy(&a,s+i,m); \
|
||||
i+=m; \
|
||||
doswap(swap,&a,m); \
|
||||
lua_pushnumber(L,(lua_Number)a); \
|
||||
++n; \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define UNPACKSTRING(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T l; \
|
||||
int m=sizeof(l); \
|
||||
if (i+m>len) goto done; \
|
||||
memcpy(&l,s+i,m); \
|
||||
doswap(swap,&l,m); \
|
||||
if (i+m+l>len) goto done; \
|
||||
i+=m; \
|
||||
lua_pushlstring(L,s+i,l); \
|
||||
i+=l; \
|
||||
++n; \
|
||||
break; \
|
||||
#define UNPACKSTRING(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T l; \
|
||||
int m=sizeof(l); \
|
||||
if (((unsigned long)i+m)>len) goto done; \
|
||||
memcpy(&l,s+i,m); \
|
||||
doswap(swap,&l,m); \
|
||||
if (((unsigned long)i+m+l)>len) goto done; \
|
||||
i+=m; \
|
||||
lua_pushlstring(L,s+i,l); \
|
||||
i+=l; \
|
||||
++n; \
|
||||
break; \
|
||||
}
|
||||
|
||||
static int l_unpack(lua_State *L) /** unpack(s,f,[init]) */
|
||||
static int l_unpack(lua_State *L) /** unpack(s,f,[init]) */
|
||||
{
|
||||
size_t len;
|
||||
const char *s=luaL_checklstring(L,1,&len);
|
||||
@ -131,7 +131,7 @@ static int l_unpack(lua_State *L) /** unpack(s,f,[init]) */
|
||||
case OP_STRING:
|
||||
{
|
||||
++N;
|
||||
if (i+N>len) goto done;
|
||||
if (((unsigned long)i+N)>len) goto done;
|
||||
lua_pushlstring(L,s+i,N);
|
||||
i+=N;
|
||||
++n;
|
||||
@ -141,7 +141,7 @@ static int l_unpack(lua_State *L) /** unpack(s,f,[init]) */
|
||||
case OP_ZSTRING:
|
||||
{
|
||||
size_t l;
|
||||
if (i>=len) goto done;
|
||||
if (((unsigned long)i)>=len) goto done;
|
||||
l=strlen(s+i);
|
||||
lua_pushlstring(L,s+i,l);
|
||||
i+=l+1;
|
||||
@ -177,28 +177,28 @@ done:
|
||||
return n+1;
|
||||
}
|
||||
|
||||
#define PACKNUMBER(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T a=(T)luaL_checknumber(L,i++); \
|
||||
doswap(swap,&a,sizeof(a)); \
|
||||
luaL_addlstring(&b,(void*)&a,sizeof(a)); \
|
||||
break; \
|
||||
#define PACKNUMBER(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
T a=(T)luaL_checknumber(L,i++); \
|
||||
doswap(swap,&a,sizeof(a)); \
|
||||
luaL_addlstring(&b,(void*)&a,sizeof(a)); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define PACKSTRING(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
size_t l; \
|
||||
const char *a=luaL_checklstring(L,i++,&l); \
|
||||
T ll=(T)l; \
|
||||
doswap(swap,&ll,sizeof(ll)); \
|
||||
luaL_addlstring(&b,(void*)&ll,sizeof(ll)); \
|
||||
luaL_addlstring(&b,a,l); \
|
||||
break; \
|
||||
#define PACKSTRING(OP,T) \
|
||||
case OP: \
|
||||
{ \
|
||||
size_t l; \
|
||||
const char *a=luaL_checklstring(L,i++,&l); \
|
||||
T ll=(T)l; \
|
||||
doswap(swap,&ll,sizeof(ll)); \
|
||||
luaL_addlstring(&b,(void*)&ll,sizeof(ll)); \
|
||||
luaL_addlstring(&b,a,l); \
|
||||
break; \
|
||||
}
|
||||
|
||||
static int l_pack(lua_State *L) /** pack(f,...) */
|
||||
static int l_pack(lua_State *L) /** pack(f,...) */
|
||||
{
|
||||
int i=2;
|
||||
const char *f=luaL_checkstring(L,1);
|
||||
@ -263,9 +263,9 @@ static int l_pack(lua_State *L) /** pack(f,...) */
|
||||
#include "lrodefs.h"
|
||||
const LUA_REG_TYPE pack_map[] =
|
||||
{
|
||||
{ LSTRKEY( "pack" ), LFUNCVAL( l_pack ) },
|
||||
{ LSTRKEY( "unpack" ), LFUNCVAL( l_unpack ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
{ LSTRKEY( "pack" ), LFUNCVAL( l_pack ) },
|
||||
{ LSTRKEY( "unpack" ), LFUNCVAL( l_unpack ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
int luaopen_pack( lua_State *L )
|
||||
|
@ -52,7 +52,8 @@ void *alloca(size_t);
|
||||
// Prototypes for Local Functions
|
||||
LUALIB_API int luaopen_rpc( lua_State *L );
|
||||
Handle *handle_create( lua_State *L );
|
||||
|
||||
static void rpc_dispatch_helper( lua_State *L, ServerHandle *handle );
|
||||
static int rpc_adispatch_helper( lua_State *L, ServerHandle * handle );
|
||||
|
||||
struct exception_context the_exception_context[ 1 ];
|
||||
|
||||
@ -175,7 +176,7 @@ static void transport_write_u8( Transport *tpt, u8 x )
|
||||
|
||||
static void swap_bytes( uint8_t *number, size_t numbersize )
|
||||
{
|
||||
int i;
|
||||
u32 i;
|
||||
for ( i = 0 ; i < numbersize / 2 ; i ++ )
|
||||
{
|
||||
uint8_t temp = number[ i ];
|
||||
@ -217,7 +218,7 @@ static void transport_write_u32( Transport *tpt, u32 x )
|
||||
// read a lua number from the transport
|
||||
static lua_Number transport_read_number( Transport *tpt )
|
||||
{
|
||||
lua_Number x;
|
||||
lua_Number x = 0;
|
||||
u8 b[ tpt->lnum_bytes ];
|
||||
struct exception e;
|
||||
TRANSPORT_VERIFY_OPEN;
|
||||
@ -448,7 +449,7 @@ static void write_variable( Transport *tpt, lua_State *L, int var_index )
|
||||
u32 len;
|
||||
transport_write_u8( tpt, RPC_STRING );
|
||||
s = lua_tostring( L, var_index );
|
||||
len = lua_strlen( L, var_index );
|
||||
len = ( u32 )lua_strlen( L, var_index );
|
||||
transport_write_u32( tpt, len );
|
||||
transport_write_string( tpt, s, len );
|
||||
break;
|
||||
@ -492,7 +493,7 @@ static void write_variable( Transport *tpt, lua_State *L, int var_index )
|
||||
luaL_error( L, "light userdata transmission unsupported" );
|
||||
break;
|
||||
}
|
||||
MYASSERT( lua_gettop( L ) == stack_at_start );
|
||||
lua_assert( lua_gettop( L ) == stack_at_start );
|
||||
}
|
||||
|
||||
|
||||
@ -632,7 +633,7 @@ static void client_negotiate( Transport *tpt )
|
||||
header[1] = 'R';
|
||||
header[2] = 'P';
|
||||
header[3] = 'C';
|
||||
header[4] = RPC_PROTOCOL_VERSION;
|
||||
header[4] = ( char )RPC_PROTOCOL_VERSION;
|
||||
header[5] = tpt->loc_little;
|
||||
header[6] = tpt->lnum_bytes;
|
||||
header[7] = tpt->loc_intnum;
|
||||
@ -779,7 +780,7 @@ static int handle_index (lua_State *L)
|
||||
const char *s;
|
||||
|
||||
check_num_args( L, 2 );
|
||||
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
|
||||
lua_assert( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
|
||||
|
||||
if( lua_type( L, 2 ) != LUA_TSTRING )
|
||||
return luaL_error( L, "can't index a handle with a non-string" );
|
||||
@ -801,7 +802,7 @@ static int handle_newindex( lua_State *L )
|
||||
const char *s;
|
||||
|
||||
check_num_args( L, 3 );
|
||||
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
|
||||
lua_assert( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.handle" ) );
|
||||
|
||||
if( lua_type( L, 2 ) != LUA_TSTRING )
|
||||
return luaL_error( L, "can't index handle with a non-string" );
|
||||
@ -820,12 +821,13 @@ static int handle_newindex( lua_State *L )
|
||||
// replays series of indexes to remote side as a string
|
||||
static void helper_remote_index( Helper *helper )
|
||||
{
|
||||
int i, len;
|
||||
int i;
|
||||
u32 len;
|
||||
Helper **hstack;
|
||||
Transport *tpt = &helper->handle->tpt;
|
||||
|
||||
// get length of name & make stack of helpers
|
||||
len = strlen( helper->funcname );
|
||||
len = ( u32 )strlen( helper->funcname );
|
||||
if( helper->nparents > 0 ) // If helper has parents, build string to remote index
|
||||
{
|
||||
hstack = ( Helper ** )alloca( sizeof( Helper * ) * helper->nparents );
|
||||
@ -838,19 +840,19 @@ static void helper_remote_index( Helper *helper )
|
||||
len += strlen( hstack[ i ]->funcname ) + 1;
|
||||
}
|
||||
|
||||
transport_write_u32( tpt, len );
|
||||
transport_write_u32( tpt, len );
|
||||
|
||||
// replay helper key names
|
||||
for( i = 0 ; i < helper->nparents ; i ++ )
|
||||
{
|
||||
transport_write_string( tpt, hstack[ i ]->funcname, strlen( hstack[ i ]->funcname ) );
|
||||
transport_write_string( tpt, hstack[ i ]->funcname, ( int )strlen( hstack[ i ]->funcname ) );
|
||||
transport_write_string( tpt, ".", 1 );
|
||||
}
|
||||
}
|
||||
else // If helper has no parents, just use length of global
|
||||
transport_write_u32( tpt, len );
|
||||
transport_write_u32( tpt, len );
|
||||
|
||||
transport_write_string( tpt, helper->funcname, strlen( helper->funcname ) );
|
||||
transport_write_string( tpt, helper->funcname, ( int )strlen( helper->funcname ) );
|
||||
}
|
||||
|
||||
static void helper_wait_ready( Transport *tpt, u8 cmd )
|
||||
@ -1072,7 +1074,7 @@ static int helper_index( lua_State *L )
|
||||
const char *s;
|
||||
|
||||
check_num_args( L, 2 );
|
||||
MYASSERT( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.helper" ) );
|
||||
lua_assert( lua_isuserdata( L, 1 ) && ismetatable_type( L, 1, "rpc.helper" ) );
|
||||
|
||||
if( lua_type( L, 2 ) != LUA_TSTRING )
|
||||
return luaL_error( L, "can't index handle with non-string" );
|
||||
@ -1257,13 +1259,13 @@ static void read_cmd_call( Transport *tpt, lua_State *L )
|
||||
// handle errors
|
||||
if ( error_code )
|
||||
{
|
||||
size_t len;
|
||||
size_t elen;
|
||||
const char *errmsg;
|
||||
errmsg = lua_tolstring (L, -1, &len);
|
||||
errmsg = lua_tolstring( L, -1, &elen );
|
||||
transport_write_u8( tpt, 1 );
|
||||
transport_write_u32( tpt, error_code );
|
||||
transport_write_u32( tpt, len );
|
||||
transport_write_string( tpt, errmsg, len );
|
||||
transport_write_u32( tpt, ( u32 )elen );
|
||||
transport_write_string( tpt, errmsg, ( int )elen );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1279,11 +1281,11 @@ static void read_cmd_call( Transport *tpt, lua_State *L )
|
||||
{
|
||||
// bad function
|
||||
const char *msg = "undefined function: ";
|
||||
int errlen = strlen( msg ) + len;
|
||||
int errlen = ( int )strlen( msg ) + len;
|
||||
transport_write_u8( tpt, 1 );
|
||||
transport_write_u32( tpt, LUA_ERRRUN );
|
||||
transport_write_u32( tpt, errlen );
|
||||
transport_write_string( tpt, msg, strlen( msg ) );
|
||||
transport_write_string( tpt, msg, ( int )strlen( msg ) );
|
||||
transport_write_string( tpt, funcname, len );
|
||||
}
|
||||
// empty the stack
|
||||
@ -1567,6 +1569,29 @@ static int rpc_dispatch( lua_State *L )
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpc_adispatch_helper( lua_State *L, ServerHandle * handle )
|
||||
{
|
||||
// Check if we have waiting data that we can dispatch on,
|
||||
// don't block if we don't have any data
|
||||
if( transport_readable( &handle->atpt ) || transport_readable( &handle->ltpt ) )
|
||||
rpc_dispatch_helper( L, handle );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rpc_adispatch( lua_State *L )
|
||||
{
|
||||
|
||||
ServerHandle *handle = 0;
|
||||
|
||||
handle = ( ServerHandle * )luaL_checkudata(L, 1, "rpc.server_handle");
|
||||
luaL_argcheck(L, handle, 1, "server handle expected");
|
||||
|
||||
handle = ( ServerHandle * )lua_touserdata( L, 1 );
|
||||
rpc_adispatch_helper( L, handle );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// rpc_server( transport_identifier )
|
||||
static int rpc_server( lua_State *L )
|
||||
@ -1658,6 +1683,7 @@ const LUA_REG_TYPE rpc_map[] =
|
||||
{ LSTRKEY( "listen" ), LFUNCVAL( rpc_listen ) },
|
||||
{ LSTRKEY( "peek" ), LFUNCVAL( rpc_peek ) },
|
||||
{ LSTRKEY( "dispatch" ), LFUNCVAL( rpc_dispatch ) },
|
||||
{ LSTRKEY( "adispatch" ), LFUNCVAL( rpc_adispatch ) },
|
||||
// { LSTRKEY( "rpc_async" ), LFUNCVAL( rpc_async ) },
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
// { LSTRKEY("mode"), LSTRVAL( LUARPC_MODE ) },
|
||||
@ -1720,6 +1746,7 @@ static const luaL_reg rpc_map[] =
|
||||
{ "listen", rpc_listen },
|
||||
{ "peek", rpc_peek },
|
||||
{ "dispatch", rpc_dispatch },
|
||||
{ "adispatch", rpc_adispatch },
|
||||
// { "rpc_async", rpc_async },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "platform.h"
|
||||
#include "auxmods.h"
|
||||
#include "elua_net.h"
|
||||
#include "common.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
@ -14,20 +15,16 @@
|
||||
#include "platform_conf.h"
|
||||
#ifdef BUILD_UIP
|
||||
|
||||
// Lua: sock, remoteip, err = accept( port, [ timer_id, timeout ] )
|
||||
// Lua: sock, remoteip, err = accept( port, [timeout], [timer_id] )
|
||||
static int net_accept( lua_State *L )
|
||||
{
|
||||
u16 port = ( u16 )luaL_checkinteger( L, 1 );
|
||||
unsigned timer_id = 0;
|
||||
u32 timeout = 0;
|
||||
unsigned timer_id = PLATFORM_TIMER_SYS_ID;
|
||||
timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
elua_net_ip remip;
|
||||
int sock;
|
||||
|
||||
if( lua_gettop( L ) >= 2 ) // check for timeout arguments
|
||||
{
|
||||
timer_id = ( unsigned )luaL_checkinteger( L, 2 );
|
||||
timeout = ( u32 )luaL_checkinteger( L, 3 );
|
||||
}
|
||||
cmn_get_timeout_data( L, 2, &timeout, &timer_id );
|
||||
lua_pushinteger( L, sock = elua_accept( port, timer_id, timeout, &remip ) );
|
||||
lua_pushinteger( L, remip.ipaddr );
|
||||
lua_pushinteger( L, elua_net_get_last_err( sock ) );
|
||||
@ -140,15 +137,15 @@ static int net_unpackip( lua_State *L )
|
||||
return luaL_error( L, "invalid format" );
|
||||
}
|
||||
|
||||
// Lua: res, err = recv( sock, maxsize, [ timer_id, timeout ] ) or
|
||||
// res, err = recv( sock, "*l", [ timer_id, timeout ] )
|
||||
// Lua: res, err = recv( sock, maxsize, [timeout], [timer_id] ) or
|
||||
// res, err = recv( sock, "*l", [timeout], [timer_id] )
|
||||
static int net_recv( lua_State *L )
|
||||
{
|
||||
int sock = ( int )luaL_checkinteger( L, 1 );
|
||||
elua_net_size maxsize;
|
||||
s16 lastchar = ELUA_NET_NO_LASTCHAR;
|
||||
unsigned timer_id = 0;
|
||||
u32 timeout = 0;
|
||||
unsigned timer_id = PLATFORM_TIMER_SYS_ID;
|
||||
timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
luaL_Buffer net_recv_buff;
|
||||
|
||||
if( lua_isnumber( L, 2 ) ) // invocation with maxsize
|
||||
@ -160,11 +157,7 @@ static int net_recv( lua_State *L )
|
||||
lastchar = '\n';
|
||||
maxsize = BUFSIZ;
|
||||
}
|
||||
if( lua_gettop( L ) >= 3 ) // check for timeout arguments
|
||||
{
|
||||
timer_id = ( unsigned )luaL_checkinteger( L, 3 );
|
||||
timeout = ( u32 )luaL_checkinteger( L, 4 );
|
||||
}
|
||||
cmn_get_timeout_data( L, 3, &timeout, &timer_id );
|
||||
// Initialize buffer
|
||||
luaL_buffinit( L, &net_recv_buff );
|
||||
elua_net_recvbuf( sock, &net_recv_buff, maxsize, lastchar, timer_id, timeout );
|
||||
@ -206,6 +199,9 @@ const LUA_REG_TYPE net_map[] =
|
||||
{ LSTRKEY( "ERR_CLOSED" ), LNUMVAL( ELUA_NET_ERR_CLOSED ) },
|
||||
{ LSTRKEY( "ERR_ABORTED" ), LNUMVAL( ELUA_NET_ERR_ABORTED ) },
|
||||
{ LSTRKEY( "ERR_OVERFLOW" ), LNUMVAL( ELUA_NET_ERR_OVERFLOW ) },
|
||||
{ LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) },
|
||||
{ LSTRKEY( "NO_TIMEOUT" ), LNUMVAL( 0 ) },
|
||||
{ LSTRKEY( "INF_TIMEOUT" ), LNUMVAL( PLATFORM_TIMER_INF_TIMEOUT ) },
|
||||
#endif
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
@ -225,6 +221,9 @@ LUALIB_API int luaopen_net( lua_State *L )
|
||||
MOD_REG_NUMBER( L, "ERR_CLOSED", ELUA_NET_ERR_CLOSED );
|
||||
MOD_REG_NUMBER( L, "ERR_ABORTED", ELUA_NET_ERR_ABORTED );
|
||||
MOD_REG_NUMBER( L, "ERR_OVERFLOW", ELUA_NET_ERR_OVERFLOW );
|
||||
MOD_REG_NUMBER( L, "SYS_TIMER", PLATFORM_TIMER_SYS_ID );
|
||||
MOD_REG_NUMBER( L, "NO_TIMEOUT", 0 );
|
||||
MOD_REG_NUMBER( L, "INF_TIMEOUT", PLATFORM_TIMER_INF_TIMEOUT );
|
||||
|
||||
return 1;
|
||||
#endif // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
|
@ -274,10 +274,10 @@ static int pio_mt_index( lua_State* L )
|
||||
#ifdef ELUA_PLATFORM_AVR32
|
||||
/* AVR32UC3A0 has a bizarre "port" called "PX" with 40 pins which map to
|
||||
* random areas of hardware ports 2 and 3:
|
||||
* PX00-PX10 = GPIO100-GPIO90 //Port 3 pins 04-00; port 2 pins 31-26
|
||||
* PX11-PX14 = GPIO109-GPIO106 //Port 3 pins 13-10
|
||||
* PX15-PX34 = GPIO89-GPIO70 //Port 2 pins 25-06
|
||||
* PX35-PX39 = GPIO105-GPIO101 //Port 3 pins 09-05
|
||||
* PX00-PX10 = GPIO100-GPIO90 //Port 3 pins 04-00; port 2 pins 31-26
|
||||
* PX11-PX14 = GPIO109-GPIO106 //Port 3 pins 13-10
|
||||
* PX15-PX34 = GPIO89-GPIO70 //Port 2 pins 25-06
|
||||
* PX35-PX39 = GPIO105-GPIO101 //Port 3 pins 09-05
|
||||
* Then port = trunc(GPIO/32) and pin = GPIO % 32
|
||||
*
|
||||
* This "Port X" exists in EVK1100 and MIZAR32 but not on EVK1101, which
|
||||
@ -287,32 +287,32 @@ static int pio_mt_index( lua_State* L )
|
||||
|
||||
// Disallow "PC_06-PC_31" as aliases for PX pins
|
||||
if (key[1] == 'C' && pin > 5)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
// Disallow "PD_nn" as aliases for PX pins
|
||||
if (key[1] == 'D')
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
// Map PX pins 00-39 to their ports/pins in the hardware register layout.
|
||||
if (key[1] == 'X')
|
||||
{
|
||||
unsigned gpio;
|
||||
unsigned gpio;
|
||||
|
||||
// You cannot perform port operations on port X because it
|
||||
// doesn't exist in hardware.
|
||||
if (pin == 0xFFFF)
|
||||
return 0;
|
||||
// You cannot perform port operations on port X because it
|
||||
// doesn't exist in hardware.
|
||||
if (pin == 0xFFFF)
|
||||
return 0;
|
||||
|
||||
// Map PX pin numbers to GPIO pin numbers
|
||||
if( pin < 0 ) return 0;
|
||||
if( pin <= 10 ) gpio = 100 - pin;
|
||||
else if( pin <= 14 ) gpio = 109 - (pin - 11);
|
||||
else if( pin <= 34 ) gpio = 89 - (pin - 15);
|
||||
else if( pin <= 39 ) gpio = 105 - (pin - 35);
|
||||
else return 0;
|
||||
// Map PX pin numbers to GPIO pin numbers
|
||||
if( pin < 0 ) return 0;
|
||||
if( pin <= 10 ) gpio = 100 - pin;
|
||||
else if( pin <= 14 ) gpio = 109 - (pin - 11);
|
||||
else if( pin <= 34 ) gpio = 89 - (pin - 15);
|
||||
else if( pin <= 39 ) gpio = 105 - (pin - 35);
|
||||
else return 0;
|
||||
|
||||
port = gpio >> 5;
|
||||
pin = gpio & 0x1F;
|
||||
port = gpio >> 5;
|
||||
pin = gpio & 0x1F;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -392,10 +392,10 @@ static const LUA_REG_TYPE pio_port_map[] =
|
||||
|
||||
const LUA_REG_TYPE pio_map[] =
|
||||
{
|
||||
{ LSTRKEY( "decode" ), LFUNCVAL( pio_decode ) },
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
{ LSTRKEY( "pin" ), LROVAL( pio_pin_map ) },
|
||||
{ LSTRKEY( "port" ), LROVAL( pio_port_map ) },
|
||||
{ LSTRKEY( "decode" ), LFUNCVAL( pio_decode ) },
|
||||
{ LSTRKEY( "INPUT" ), LNUMVAL( PIO_DIR_INPUT ) },
|
||||
{ LSTRKEY( "OUTPUT" ), LNUMVAL( PIO_DIR_OUTPUT ) },
|
||||
{ LSTRKEY( "PULLUP" ), LNUMVAL( PLATFORM_IO_PIN_PULLUP ) },
|
||||
|
@ -10,16 +10,20 @@
|
||||
// Lua: realfrequency = setup( id, frequency, duty )
|
||||
static int pwm_setup( lua_State* L )
|
||||
{
|
||||
u32 freq;
|
||||
unsigned duty, id;
|
||||
s32 freq; // signed, to error check for negative values
|
||||
unsigned duty;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
freq = luaL_checkinteger( L, 2 );
|
||||
if ( freq <= 0 )
|
||||
return luaL_error( L, "frequency must be > 0" );
|
||||
duty = luaL_checkinteger( L, 3 );
|
||||
if( duty > 100 )
|
||||
duty = 100;
|
||||
freq = platform_pwm_setup( id, freq, duty );
|
||||
if ( duty > 100 )
|
||||
// Negative values will turn out > 100, so will also fail.
|
||||
return luaL_error( L, "duty cycle must be from 0 to 100" );
|
||||
freq = platform_pwm_setup( id, (u32)freq, duty );
|
||||
lua_pushinteger( L, freq );
|
||||
return 1;
|
||||
}
|
||||
@ -31,7 +35,7 @@ static int pwm_start( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
platform_pwm_op( id, PLATFORM_PWM_OP_START, 0 );
|
||||
platform_pwm_start( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -42,7 +46,7 @@ static int pwm_stop( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
platform_pwm_op( id, PLATFORM_PWM_OP_STOP, 0 );
|
||||
platform_pwm_stop( id );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -50,12 +54,14 @@ static int pwm_stop( lua_State* L )
|
||||
static int pwm_setclock( lua_State* L )
|
||||
{
|
||||
unsigned id;
|
||||
u32 clk;
|
||||
s32 clk; // signed to error-check for negative values
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
clk = luaL_checkinteger( L, 2 );
|
||||
clk = platform_pwm_op( id, PLATFORM_PWM_OP_SET_CLOCK, clk );
|
||||
if ( clk <= 0 )
|
||||
return luaL_error( L, "frequency must be > 0" );
|
||||
clk = platform_pwm_set_clock( id, (u32)clk );
|
||||
lua_pushinteger( L, clk );
|
||||
return 1;
|
||||
}
|
||||
@ -68,7 +74,7 @@ static int pwm_getclock( lua_State* L )
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( pwm, id );
|
||||
clk = platform_pwm_op( id, PLATFORM_PWM_OP_GET_CLOCK, 0 );
|
||||
clk = platform_pwm_get_clock( id );
|
||||
lua_pushinteger( L, clk );
|
||||
return 1;
|
||||
}
|
||||
|
@ -21,120 +21,136 @@ static int tmrh_timer_op( lua_State* L, int op )
|
||||
unsigned id;
|
||||
timer_data_type res;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
res = platform_timer_op( id, op, 0 );
|
||||
lua_pushinteger( L, res );
|
||||
lua_pushnumber( L, ( lua_Number )res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: delay( id, period )
|
||||
// Lua: delay( period, [id] )
|
||||
static int tmr_delay( lua_State* L )
|
||||
{
|
||||
unsigned id, period;
|
||||
timer_data_type period;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
period = luaL_checkinteger( L, 2 );
|
||||
period = ( timer_data_type )luaL_checknumber( L, 1 );
|
||||
id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
platform_timer_delay( id, period );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: timervalue = read( id )
|
||||
// Lua: timervalue = read( [id] )
|
||||
static int tmr_read( lua_State* L )
|
||||
{
|
||||
return tmrh_timer_op( L, PLATFORM_TIMER_OP_READ );
|
||||
}
|
||||
|
||||
// Lua: timervalue = start( id )
|
||||
// Lua: timervalue = start( [id] )
|
||||
static int tmr_start( lua_State* L )
|
||||
{
|
||||
return tmrh_timer_op( L, PLATFORM_TIMER_OP_START );
|
||||
}
|
||||
|
||||
// Lua: time_us = gettimediff( id, end, start )
|
||||
// Lua: time_us = gettimediff( end, start, [id] )
|
||||
static int tmr_gettimediff( lua_State* L )
|
||||
{
|
||||
timer_data_type end, start;
|
||||
u32 res;
|
||||
timer_data_type end, start, res;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
end = ( timer_data_type )luaL_checkinteger( L, 2 );
|
||||
start = ( timer_data_type )luaL_checkinteger( L, 3 );
|
||||
id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
end = ( timer_data_type )luaL_checknumber( L, 1 );
|
||||
start = ( timer_data_type )luaL_checknumber( L, 2 );
|
||||
res = platform_timer_get_diff_us( id, end, start );
|
||||
lua_pushinteger( L, res );
|
||||
lua_pushnumber( L, ( lua_Number )res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: res = getmindelay( id )
|
||||
// Lua: time_us = getdiffnow( start, [id] )
|
||||
static int tmr_getdiffnow( lua_State *L )
|
||||
{
|
||||
timer_data_type start, res;
|
||||
unsigned id;
|
||||
|
||||
id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
start = ( timer_data_type )luaL_checknumber( L, 1 );
|
||||
res = platform_timer_get_diff_crt( id, start );
|
||||
lua_pushnumber( L, ( lua_Number )res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: res = getmindelay( [id] )
|
||||
static int tmr_getmindelay( lua_State* L )
|
||||
{
|
||||
u32 res;
|
||||
timer_data_type res;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_MIN_DELAY, 0 );
|
||||
lua_pushinteger( L, res );
|
||||
lua_pushnumber( L, ( lua_Number )res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: res = getmaxdelay( id )
|
||||
// Lua: res = getmaxdelay( [id] )
|
||||
static int tmr_getmaxdelay( lua_State* L )
|
||||
{
|
||||
u32 res;
|
||||
timer_data_type res;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_DELAY, 0 );
|
||||
lua_pushinteger( L, res );
|
||||
lua_pushnumber( L, ( lua_Number )res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: realclock = setclock( id, clock )
|
||||
// Lua: realclock = setclock( clock, [id] )
|
||||
static int tmr_setclock( lua_State* L )
|
||||
{
|
||||
u32 clock;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
clock = ( u32 )luaL_checkinteger( L, 2 );
|
||||
id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
clock = ( u32 )luaL_checkinteger( L, 1 );
|
||||
clock = platform_timer_op( id, PLATFORM_TIMER_OP_SET_CLOCK, clock );
|
||||
lua_pushinteger( L, clock );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua: clock = getclock( id )
|
||||
// Lua: clock = getclock( [id] )
|
||||
static int tmr_getclock( lua_State* L )
|
||||
{
|
||||
u32 res;
|
||||
unsigned id;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_CLOCK, 0 );
|
||||
lua_pushinteger( L, res );
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef BUILD_LUA_INT_HANDLERS
|
||||
// Lua: set_match_int( id, timeout, type )
|
||||
// Lua: set_match_int( timeout, type, [id] )
|
||||
static int tmr_set_match_int( lua_State *L )
|
||||
{
|
||||
unsigned id;
|
||||
u32 res;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( timer, id );
|
||||
res = platform_timer_set_match_int( id, ( u32 )luaL_checknumber( L, 2 ), ( int )luaL_checkinteger( L, 3 ) );
|
||||
id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
|
||||
MOD_CHECK_TIMER( id );
|
||||
res = platform_timer_set_match_int( id, ( timer_data_type )luaL_checknumber( L, 1 ), ( int )luaL_checkinteger( L, 2 ) );
|
||||
if( res == PLATFORM_TIMER_INT_TOO_SHORT )
|
||||
return luaL_error( L, "timer interval too small" );
|
||||
else if( res == PLATFORM_TIMER_INT_TOO_LONG )
|
||||
return luaL_error( L, "timer interval too long" );
|
||||
else if( res == PLATFORM_TIMER_INT_INVALID_ID )
|
||||
return luaL_error( L, "mach interrupt cannot be set on this timer" );
|
||||
return luaL_error( L, "match interrupt cannot be set on this timer" );
|
||||
return 0;
|
||||
}
|
||||
#endif // #ifdef BUILD_LUA_INT_HANDLERS
|
||||
@ -171,6 +187,7 @@ const LUA_REG_TYPE tmr_map[] =
|
||||
{ LSTRKEY( "read" ), LFUNCVAL( tmr_read ) },
|
||||
{ LSTRKEY( "start" ), LFUNCVAL( tmr_start ) },
|
||||
{ LSTRKEY( "gettimediff" ), LFUNCVAL( tmr_gettimediff ) },
|
||||
{ LSTRKEY( "getdiffnow" ), LFUNCVAL( tmr_getdiffnow ) },
|
||||
{ LSTRKEY( "getmindelay" ), LFUNCVAL( tmr_getmindelay ) },
|
||||
{ LSTRKEY( "getmaxdelay" ), LFUNCVAL( tmr_getmaxdelay ) },
|
||||
{ LSTRKEY( "setclock" ), LFUNCVAL( tmr_setclock ) },
|
||||
@ -183,6 +200,7 @@ const LUA_REG_TYPE tmr_map[] =
|
||||
#endif
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
{ LSTRKEY( "__index" ), LFUNCVAL( tmr_mt_index ) },
|
||||
{ LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) },
|
||||
#endif
|
||||
#if LUA_OPTIMIZE_MEMORY > 0 && defined( BUILD_LUA_INT_HANDLERS )
|
||||
{ LSTRKEY( "INT_ONESHOT" ), LNUMVAL( PLATFORM_TIMER_INT_ONESHOT ) },
|
||||
@ -202,6 +220,11 @@ LUALIB_API int luaopen_tmr( lua_State *L )
|
||||
lua_pushvalue( L, -1 );
|
||||
lua_setmetatable( L, -2 );
|
||||
#endif // #if VTMR_NUM_TIMERS > 0
|
||||
MOD_REG_NUMBER( L, "SYS_TIMER", PLATFORM_TIMER_SYS_ID );
|
||||
#ifdef BUILD_LUA_INT_HANDLERS
|
||||
MOD_REG_NUMBER( L, "INT_ONESHOT", PLATFORM_TIMER_INT_ONESHOT );
|
||||
MOD_REG_NUMBER( L, "INT_CYCLIC", PLATFORM_TIMER_INT_CYCLIC );
|
||||
#endif //#ifdef BUILD_LUA_INT_HANDLERS
|
||||
return 1;
|
||||
#endif // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ enum
|
||||
UART_READ_MODE_MAXSIZE
|
||||
};
|
||||
|
||||
#define UART_INFINITE_TIMEOUT PLATFORM_TIMER_INF_TIMEOUT
|
||||
|
||||
// Lua: actualbaud = setup( id, baud, databits, parity, stopbits )
|
||||
static int uart_setup( lua_State* L )
|
||||
{
|
||||
@ -71,14 +73,16 @@ static int uart_write( lua_State* L )
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lua: uart.read( id, format, [timeout], [timer_id] )
|
||||
static int uart_read( lua_State* L )
|
||||
{
|
||||
int id, res, mode, issign;
|
||||
unsigned timer_id = 0;
|
||||
s32 timeout = PLATFORM_UART_INFINITE_TIMEOUT, maxsize = 0, count = 0;
|
||||
unsigned timer_id = PLATFORM_TIMER_SYS_ID;
|
||||
s32 maxsize = 0, count = 0;
|
||||
const char *fmt;
|
||||
luaL_Buffer b;
|
||||
char cres;
|
||||
timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
@ -104,14 +108,7 @@ static int uart_read( lua_State* L )
|
||||
}
|
||||
|
||||
// Check timeout and timer id
|
||||
if( lua_gettop( L ) >= 3 )
|
||||
{
|
||||
timeout = luaL_checkinteger( L, 3 );
|
||||
if( ( timeout < 0 ) && ( timeout != PLATFORM_UART_INFINITE_TIMEOUT ) )
|
||||
return luaL_error( L, "invalid timeout value" );
|
||||
if( ( timeout != PLATFORM_UART_INFINITE_TIMEOUT ) && ( timeout != 0 ) )
|
||||
timer_id = luaL_checkinteger( L, 4 );
|
||||
}
|
||||
cmn_get_timeout_data( L, 3, &timeout, &timer_id );
|
||||
|
||||
// Read data
|
||||
luaL_buffinit( L, &b );
|
||||
@ -151,21 +148,13 @@ static int uart_getchar( lua_State* L )
|
||||
{
|
||||
int id, res;
|
||||
char cres;
|
||||
unsigned timer_id = 0;
|
||||
s32 timeout = PLATFORM_UART_INFINITE_TIMEOUT;
|
||||
unsigned timer_id = PLATFORM_TIMER_SYS_ID;
|
||||
timer_data_type timeout = PLATFORM_TIMER_INF_TIMEOUT;
|
||||
|
||||
id = luaL_checkinteger( L, 1 );
|
||||
MOD_CHECK_ID( uart, id );
|
||||
|
||||
// Check timeout and timer id
|
||||
if( lua_gettop( L ) >= 2 )
|
||||
{
|
||||
timeout = luaL_checkinteger( L, 2 );
|
||||
if( ( timeout < 0 ) && ( timeout != PLATFORM_UART_INFINITE_TIMEOUT ) )
|
||||
return luaL_error( L, "invalid timeout value" );
|
||||
if( ( timeout != PLATFORM_UART_INFINITE_TIMEOUT ) && ( timeout != 0 ) )
|
||||
timer_id = luaL_checkinteger( L, 3 );
|
||||
}
|
||||
cmn_get_timeout_data( L, 2, &timeout, &timer_id );
|
||||
res = platform_uart_recv( id, timer_id, timeout );
|
||||
if( res == -1 )
|
||||
lua_pushstring( L, "" );
|
||||
@ -252,10 +241,11 @@ const LUA_REG_TYPE uart_map[] =
|
||||
{ LSTRKEY( "STOP_1_5" ), LNUMVAL( PLATFORM_UART_STOPBITS_1_5 ) },
|
||||
{ LSTRKEY( "STOP_2" ), LNUMVAL( PLATFORM_UART_STOPBITS_2 ) },
|
||||
{ LSTRKEY( "NO_TIMEOUT" ), LNUMVAL( 0 ) },
|
||||
{ LSTRKEY( "INF_TIMEOUT" ), LNUMVAL( PLATFORM_UART_INFINITE_TIMEOUT ) },
|
||||
{ LSTRKEY( "INF_TIMEOUT" ), LNUMVAL( UART_INFINITE_TIMEOUT ) },
|
||||
{ LSTRKEY( "FLOW_NONE" ), LNUMVAL( PLATFORM_UART_FLOW_NONE ) },
|
||||
{ LSTRKEY( "FLOW_RTS" ), LNUMVAL( PLATFORM_UART_FLOW_RTS ) },
|
||||
{ LSTRKEY( "FLOW_CTS" ), LNUMVAL( PLATFORM_UART_FLOW_CTS ) },
|
||||
{ LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) },
|
||||
#endif
|
||||
#if LUA_OPTIMIZE_MEMORY > 0 && defined( BUILD_SERMUX )
|
||||
{ LSTRKEY( "__metatable" ), LROVAL( uart_map ) },
|
||||
@ -281,7 +271,9 @@ LUALIB_API int luaopen_uart( lua_State *L )
|
||||
|
||||
// Add the "none" and "infinite" constant used in recv()
|
||||
MOD_REG_NUMBER( L, "NO_TIMEOUT", 0 );
|
||||
MOD_REG_NUMBER( L, "INF_TIMEOUT", PLATFORM_UART_INFINITE_TIMEOUT );
|
||||
MOD_REG_NUMBER( L, "INF_TIMEOUT", UART_INFINITE_TIMEOUT );
|
||||
// Also add the system timer ID
|
||||
MOD_REG_NUMBER( L, "SYS_TIMER", PLATFORM_TIMER_SYS_ID );
|
||||
|
||||
// Add the UART flow constants
|
||||
MOD_REG_NUMBER( L, "FLOW_RTS", PLATFORM_UART_FLOW_RTS );
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
local cpumode = ( builder:get_option( 'cpumode' ) or 'thumb' ):lower()
|
||||
|
||||
specific_files = "board_cstartup.s board_lowlevel.c board_memories.c usart.c pmc.c pio.c platform.c tc.c pwmc.c aic.c platform_int.c"
|
||||
specific_files = "board_cstartup.s board_lowlevel.c board_memories.c usart.c pmc.c pio.c platform.c tc.c pwmc.c aic.c platform_int.c pit.c"
|
||||
local ldscript
|
||||
if comp.cpu:upper() == 'AT91SAM7X256' then
|
||||
ldscript = "flash256.lds"
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
cpumode = ARGUMENTS.get( 'cpumode', 'thumb' ).lower()
|
||||
|
||||
specific_files = "board_cstartup.s board_lowlevel.c board_memories.c usart.c pmc.c pio.c platform.c tc.c pwmc.c aic.c platform_int.c"
|
||||
specific_files = "board_cstartup.s board_lowlevel.c board_memories.c usart.c pmc.c pio.c platform.c tc.c pwmc.c aic.c platform_int.c pit.c"
|
||||
if comp[ 'cpu' ] == 'AT91SAM7X256':
|
||||
ldscript = "flash256.lds"
|
||||
comp.Append(CPPDEFINES = 'at91sam7x256')
|
||||
|
129
src/platform/at91sam7x/pit.c
Normal file
129
src/platform/at91sam7x/pit.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Headers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include "pit.h"
|
||||
#include <board.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Global functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Initialize the Periodic Interval Timer to generate a tick at the specified
|
||||
/// period, given the current master clock frequency.
|
||||
/// \param period Period in <20>second.
|
||||
/// \param pit_frequency Master clock frequency in MHz.
|
||||
//------------------------------------------------------------------------------
|
||||
void PIT_Init(unsigned int period, unsigned int pit_frequency)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR = period? (period * pit_frequency + 8) >> 4 : 0;
|
||||
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Set the Periodic Interval Value of the PIT.
|
||||
/// \param piv PIV value to set.
|
||||
//------------------------------------------------------------------------------
|
||||
void PIT_SetPIV(unsigned int piv)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR = (AT91C_BASE_PITC->PITC_PIMR & AT91C_PITC_PIV)
|
||||
| piv;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Enables the PIT if this is not already the case.
|
||||
//------------------------------------------------------------------------------
|
||||
void PIT_Enable(void)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/// Disables the PIT
|
||||
//------------------------------------------------------------------------------
|
||||
void PIT_Disable(void)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITEN;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// Enable the PIT periodic interrupt.
|
||||
//----------------------------------------------------------------------------
|
||||
void PIT_EnableIT(void)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Disables the PIT periodic interrupt.
|
||||
//------------------------------------------------------------------------------
|
||||
void PIT_DisableIT(void)
|
||||
{
|
||||
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns the value of the PIT mode register.
|
||||
/// \return PIT_MR value.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int PIT_GetMode(void)
|
||||
{
|
||||
return AT91C_BASE_PITC->PITC_PIMR;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns the value of the PIT status register, clearing it as a side effect.
|
||||
/// \return PIT_SR value.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int PIT_GetStatus(void)
|
||||
{
|
||||
return AT91C_BASE_PITC->PITC_PISR;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns the value of the PIT Image Register, to read PICNT and CPIV without
|
||||
/// clearing the current values.
|
||||
/// \return PIT_PIIR value.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int PIT_GetPIIR(void)
|
||||
{
|
||||
return AT91C_BASE_PITC->PITC_PIIR;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Returns the value of the PIT Value Register, clearing it as a side effect.
|
||||
/// \return PIT_PIVR value.
|
||||
//------------------------------------------------------------------------------
|
||||
unsigned int PIT_GetPIVR(void)
|
||||
{
|
||||
return AT91C_BASE_PITC->PITC_PIVR;
|
||||
}
|
79
src/platform/at91sam7x/pit.h
Normal file
79
src/platform/at91sam7x/pit.h
Normal file
@ -0,0 +1,79 @@
|
||||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2008, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// \unit
|
||||
///
|
||||
/// !Purpose
|
||||
///
|
||||
/// Interface for configuration the Periodic Interval Timer (PIT) peripheral.
|
||||
///
|
||||
/// !Usage
|
||||
///
|
||||
/// -# Initialize the PIT with the desired period using PIT_Init().
|
||||
/// Alternatively, the Periodic Interval Value (PIV) can be configured
|
||||
/// manually using PIT_SetPIV().
|
||||
/// -# Start the PIT counting using PIT_Enable().
|
||||
/// -# Enable & disable the PIT interrupt using PIT_EnableIT() and
|
||||
/// PIT_DisableIT().
|
||||
/// -# Retrieve the current status of the PIT using PIT_GetStatus().
|
||||
/// -# To get the current value of the internal counter and the number of ticks
|
||||
/// that have occurred, use either PIT_GetPIVR() or PIT_GetPIIR() depending
|
||||
/// on whether you want the values to be cleared or not.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef PIT_H
|
||||
#define PIT_H
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Global Functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern void PIT_Init(unsigned int period, unsigned int pit_frequency);
|
||||
|
||||
extern void PIT_SetPIV(unsigned int piv);
|
||||
|
||||
extern void PIT_Enable(void);
|
||||
|
||||
extern void PIT_Disable(void);
|
||||
|
||||
extern void PIT_EnableIT(void);
|
||||
|
||||
extern void PIT_DisableIT(void);
|
||||
|
||||
extern unsigned int PIT_GetMode(void);
|
||||
|
||||
extern unsigned int PIT_GetStatus(void);
|
||||
|
||||
extern unsigned int PIT_GetPIIR(void);
|
||||
|
||||
extern unsigned int PIT_GetPIVR(void);
|
||||
|
||||
#endif //#ifndef PIT_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Platform-dependent functions
|
||||
// platform-dependent functions
|
||||
|
||||
#include "platform.h"
|
||||
#include "type.h"
|
||||
@ -21,6 +21,7 @@
|
||||
#include "aic.h"
|
||||
#include "platform_conf.h"
|
||||
#include "buf.h"
|
||||
#include "pit.h"
|
||||
|
||||
// "Stubs" used for our interrupt handlers
|
||||
// Just a trick to avoid interworking and some other complications
|
||||
@ -33,6 +34,41 @@
|
||||
"bx r0\n\t"\
|
||||
)\
|
||||
|
||||
// ****************************************************************************
|
||||
// AT91SAM7X system timer
|
||||
// We implement this using the PIT, as it has a 20-bit counter (the timers only
|
||||
// have 16-bit counters) and is not used by eLua in any other way. It is clocked
|
||||
// at 3MHz (MCLK/16) which means we have 3 ticks per microsecond. To keep things
|
||||
// as precise as possible, we choose the counter limit to be a multiple of 3.
|
||||
// This translates to limit = 1048575 (kept as high as possible to minimize system
|
||||
// impact), which means PIV = 1048574 (since the period is PIV + 1) which in turn
|
||||
// means 349525us/interrupt
|
||||
|
||||
#define SYSTIMER_US_PER_INTERRUPT 349525
|
||||
#define SYSTIMER_LIMIT 1048574
|
||||
#define SYSTIMER_MASK ( ( 1 << 20 ) - 1 )
|
||||
|
||||
void __isr_pit_helper()
|
||||
{
|
||||
PIT_GetPIVR();
|
||||
cmn_systimer_periodic();
|
||||
AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_SYS;
|
||||
}
|
||||
|
||||
static void __attribute__((naked)) ISR_Pit()
|
||||
{
|
||||
INT_STUB( __isr_pit_helper );
|
||||
}
|
||||
|
||||
static void platform_systimer_init()
|
||||
{
|
||||
PIT_SetPIV( SYSTIMER_LIMIT );
|
||||
AIC_ConfigureIT( AT91C_ID_SYS, 0, ISR_Pit );
|
||||
PIT_EnableIT();
|
||||
AIC_EnableIT( AT91C_ID_SYS );
|
||||
PIT_Enable();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Platform initialization
|
||||
|
||||
@ -100,6 +136,11 @@ int platform_init()
|
||||
TC_Start( AT91C_BASE_TC2 );
|
||||
#endif
|
||||
|
||||
// Initialize the system timer
|
||||
cmn_systimer_set_base_freq( BOARD_MCK / 16 );
|
||||
cmn_systimer_set_interrupt_period_us( SYSTIMER_US_PER_INTERRUPT );
|
||||
platform_systimer_init();
|
||||
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
@ -228,7 +269,7 @@ void platform_s_uart_send( unsigned id, u8 data )
|
||||
USART_Write( base, data, 0 );
|
||||
}
|
||||
|
||||
int platform_s_uart_recv( unsigned id, s32 timeout )
|
||||
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
|
||||
{
|
||||
AT91S_USART* base = id == 0 ? AT91C_BASE_US0 : AT91C_BASE_US1;
|
||||
|
||||
@ -276,7 +317,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
|
||||
return BOARD_MCK / clkdivs[ mini ];
|
||||
}
|
||||
|
||||
void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
|
||||
{
|
||||
AT91S_TC* base = ( AT91S_TC* )timer_base[ id ];
|
||||
u32 freq;
|
||||
@ -292,7 +333,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
while( base->TC_CV < final );
|
||||
}
|
||||
|
||||
u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
|
||||
{
|
||||
u32 res = 0;
|
||||
AT91S_TC* base = ( AT91S_TC* )timer_base[ id ];
|
||||
@ -310,14 +351,6 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
res = base->TC_CV;
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 0xFFFF );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 1 );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
res = platform_timer_set_clock( id, data );
|
||||
break;
|
||||
@ -325,10 +358,34 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = platform_timer_get_clock( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_CNT:
|
||||
res = 0xFFFF;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
u64 platform_timer_sys_raw_read()
|
||||
{
|
||||
return PIT_GetPIIR() & SYSTIMER_MASK;
|
||||
}
|
||||
|
||||
void platform_timer_sys_disable_int()
|
||||
{
|
||||
PIT_DisableIT();
|
||||
}
|
||||
|
||||
void platform_timer_sys_enable_int()
|
||||
{
|
||||
PIT_EnableIT();
|
||||
}
|
||||
|
||||
timer_data_type platform_timer_read_sys()
|
||||
{
|
||||
return cmn_systimer_get();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// PWMs
|
||||
|
||||
@ -338,8 +395,8 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
// PWM pins
|
||||
static const Pin pwm_pins[] = { PIN_PWMC_PWM0, PIN_PWMC_PWM1, PIN_PWMC_PWM2, PIN_PWMC_PWM3 };
|
||||
|
||||
// Helper function: return the PWM clock
|
||||
static u32 platform_pwm_get_clock( unsigned id )
|
||||
// Return the PWM clock
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
u32 cfg = AT91C_BASE_PWMC->PWMC_CH[ id ].PWMC_CMR;
|
||||
u16 clkdata;
|
||||
@ -358,8 +415,8 @@ static u32 platform_pwm_get_clock( unsigned id )
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function: set the PWM clock
|
||||
static u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
// Set the PWM clock
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 clock )
|
||||
{
|
||||
if( id < 2 )
|
||||
PWMC_ConfigureClocks( clock, 0, BOARD_MCK );
|
||||
@ -386,30 +443,14 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
return pwmclk / period;
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data )
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
res = platform_pwm_set_clock( id, data );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
res = platform_pwm_get_clock( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
PIO_Configure( pwm_pins + id, 1 );
|
||||
res = AT91C_BASE_PWMC->PWMC_ISR;
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
platform_pio_op( 1, 1 << ( 19 + id ), PLATFORM_IO_PIN_DIR_INPUT );
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
volatile u32 dummy;
|
||||
PIO_Configure( pwm_pins + id, 1 );
|
||||
dummy = AT91C_BASE_PWMC->PWMC_ISR;
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
platform_pio_op( 1, 1 << ( 19 + id ), PLATFORM_IO_PIN_DIR_INPUT );
|
||||
}
|
||||
|
@ -19,17 +19,18 @@
|
||||
#define BUILD_TERM
|
||||
#define BUILD_CON_GENERIC
|
||||
//#define BUILD_RPC
|
||||
#define BUILD_RFS
|
||||
#define BUILD_SERMUX
|
||||
//#define BUILD_RFS
|
||||
//#define BUILD_SERMUX
|
||||
#define BUILD_C_INT_HANDLERS
|
||||
|
||||
#define PLATFORM_HAS_SYSTIMER
|
||||
|
||||
// *****************************************************************************
|
||||
// UART/Timer IDs configuration data (used in main.c)
|
||||
|
||||
#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
|
||||
//#define CON_UART_ID 0
|
||||
//#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
|
||||
#define CON_UART_ID 0
|
||||
#define CON_UART_SPEED 115200
|
||||
#define CON_TIMER_ID 0
|
||||
#define TERM_LINES 25
|
||||
#define TERM_COLS 80
|
||||
|
||||
@ -82,14 +83,13 @@
|
||||
|
||||
// RPC boot options
|
||||
#define RPC_UART_ID CON_UART_ID
|
||||
#define RPC_TIMER_ID CON_TIMER_ID
|
||||
#define RPC_UART_SPEED CON_UART_SPEED
|
||||
|
||||
// Enable RX buffering on UART
|
||||
#define BUF_ENABLE_UART
|
||||
#define CON_BUF_SIZE BUF_SIZE_128
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
|
||||
#define CPU_FREQUENCY BOARD_MCK
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
@ -111,9 +111,9 @@
|
||||
#define MEM_START_ADDRESS { ( void* )end }
|
||||
#define MEM_END_ADDRESS { ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
|
||||
|
||||
/*
|
||||
#define RFS_BUFFER_SIZE BUF_SIZE_512
|
||||
#define RFS_UART_ID ( SERMUX_SERVICE_ID_FIRST )
|
||||
#define RFS_TIMER_ID 0
|
||||
#define RFS_TIMEOUT 100000
|
||||
#define RFS_UART_SPEED 115200
|
||||
|
||||
@ -121,6 +121,7 @@
|
||||
#define SERMUX_PHYS_SPEED 115200
|
||||
#define SERMUX_NUM_VUART 2
|
||||
#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
|
||||
*/
|
||||
|
||||
// Interrupt list
|
||||
#define INT_UART_RX ELUA_INT_FIRST_ID
|
||||
|
@ -33,7 +33,6 @@
|
||||
//#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
|
||||
#define CON_UART_ID 0
|
||||
#define CON_UART_SPEED 115200
|
||||
#define CON_TIMER_ID 0
|
||||
#define TERM_LINES 25
|
||||
#define TERM_COLS 80
|
||||
|
||||
@ -87,6 +86,7 @@
|
||||
_ROM( AUXLIB_UART, luaopen_uart, uart_map )\
|
||||
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
|
||||
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
|
||||
_ROM( AUXLIB_I2C, luaopen_i2c, i2c_map )\
|
||||
_ROM( AUXLIB_SPI, luaopen_spi, spi_map )\
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
|
||||
@ -104,7 +104,7 @@
|
||||
|
||||
// Virtual timers (0 if not used)
|
||||
#define VTMR_NUM_TIMERS 4
|
||||
#define VTMR_FREQ_HZ 4
|
||||
#define VTMR_FREQ_HZ 10
|
||||
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 4
|
||||
@ -115,13 +115,13 @@
|
||||
#else
|
||||
#define NUM_TIMER 3
|
||||
#endif
|
||||
#define NUM_PWM 7
|
||||
#define NUM_PWM 6
|
||||
#define NUM_I2C 1
|
||||
#define NUM_ADC 8
|
||||
#define NUM_CAN 0
|
||||
|
||||
// RPC boot options
|
||||
#define RPC_UART_ID CON_UART_ID
|
||||
#define RPC_TIMER_ID CON_TIMER_ID
|
||||
#define RPC_UART_SPEED CON_UART_SPEED
|
||||
|
||||
// Enable RX buffering on UART
|
||||
@ -138,13 +138,11 @@
|
||||
#define ADC_NUM_TIMERS 0
|
||||
|
||||
// SD/MMC Filesystem Setup
|
||||
#define MMCFS_TICK_HZ 10
|
||||
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
|
||||
#define MMCFS_SPI_NUM 5
|
||||
#define MMCFS_CS_PORT 0
|
||||
#define MMCFS_CS_PIN SD_MMC_SPI_NPCS_PIN
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
|
||||
#define CPU_FREQUENCY REQ_CPU_FREQ
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
@ -154,6 +152,7 @@
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PIN_ARRAY { 31, 32, 32, 14 }
|
||||
#define AVR32_NUM_GPIO 110 // actually 109, but consider also PA31
|
||||
|
||||
// Allocator data: define your free memory zones here in two arrays
|
||||
// (start address and end address)
|
||||
@ -162,7 +161,6 @@
|
||||
|
||||
#define RFS_BUFFER_SIZE BUF_SIZE_512
|
||||
#define RFS_UART_ID ( SERMUX_SERVICE_ID_FIRST )
|
||||
#define RFS_TIMER_ID 0
|
||||
#define RFS_TIMEOUT 100000
|
||||
#define RFS_UART_SPEED 115200
|
||||
|
||||
@ -171,16 +169,6 @@
|
||||
//#define SERMUX_NUM_VUART 2
|
||||
//#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
|
||||
|
||||
// Interrupt queue size
|
||||
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
|
||||
|
||||
// Interrupt list
|
||||
#define INT_UART_RX ELUA_INT_FIRST_ID
|
||||
#define INT_ELUA_LAST INT_UART_RX
|
||||
|
||||
#define PLATFORM_CPU_CONSTANTS\
|
||||
_C( INT_UART_RX )
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU constants that should be exposed to the eLua "cpu" module
|
||||
|
||||
|
@ -14,13 +14,13 @@
|
||||
#define BUILD_CON_GENERIC
|
||||
//#define BUILD_RPC
|
||||
#define BUILD_C_INT_HANDLERS
|
||||
#define BUILD_ADC
|
||||
|
||||
// *****************************************************************************
|
||||
// UART/Timer IDs configuration data (used in main.c)
|
||||
|
||||
#define CON_UART_ID 1
|
||||
#define CON_UART_SPEED 115200
|
||||
#define CON_TIMER_ID 0
|
||||
#define TERM_LINES 25
|
||||
#define TERM_COLS 80
|
||||
|
||||
@ -43,6 +43,12 @@
|
||||
#define BUILD_RPC
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_ADC
|
||||
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
|
||||
#else
|
||||
#define ADCLINE
|
||||
#endif
|
||||
|
||||
#if defined( BUILD_RPC )
|
||||
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
|
||||
#else
|
||||
@ -57,6 +63,7 @@
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
|
||||
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
|
||||
ADCLINE\
|
||||
RPCLINE\
|
||||
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
|
||||
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
|
||||
@ -67,7 +74,7 @@
|
||||
|
||||
// Virtual timers (0 if not used)
|
||||
#define VTMR_NUM_TIMERS 4
|
||||
#define VTMR_FREQ_HZ 4
|
||||
#define VTMR_FREQ_HZ 10
|
||||
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 2
|
||||
@ -78,27 +85,29 @@
|
||||
#else
|
||||
#define NUM_TIMER 3
|
||||
#endif
|
||||
#define NUM_PWM 0
|
||||
#define NUM_ADC 0
|
||||
#define NUM_PWM 6
|
||||
#define NUM_ADC 8
|
||||
#define NUM_CAN 0
|
||||
|
||||
// RPC boot options
|
||||
#define RPC_UART_ID CON_UART_ID
|
||||
#define RPC_TIMER_ID CON_TIMER_ID
|
||||
#define RPC_UART_SPEED CON_UART_SPEED
|
||||
|
||||
// Enable RX buffering on UART
|
||||
#define BUF_ENABLE_UART
|
||||
#define CON_BUF_SIZE BUF_SIZE_128
|
||||
|
||||
// ADC Configuration Params
|
||||
#define ADC_BIT_RESOLUTION 10
|
||||
#define BUF_ENABLE_ADC
|
||||
#define ADC_BUF_SIZE BUF_SIZE_2
|
||||
|
||||
// SD/MMC Filesystem Setup
|
||||
#define MMCFS_TICK_HZ 10
|
||||
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
|
||||
#define MMCFS_SPI_NUM 1
|
||||
#define MMCFS_CS_PORT 0 //PA17
|
||||
#define MMCFS_CS_PIN SD_MMC_SPI_NPCS_PIN
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
|
||||
#define CPU_FREQUENCY REQ_CPU_FREQ
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
@ -108,22 +117,13 @@
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PIN_ARRAY { 32, 12 }
|
||||
#define AVR32_NUM_GPIO 44
|
||||
|
||||
// Allocator data: define your free memory zones here in two arrays
|
||||
// (start address and end address)
|
||||
#define MEM_START_ADDRESS { ( void* )end }
|
||||
#define MEM_END_ADDRESS { ( void* )( AVR32_SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
|
||||
|
||||
// Interrupt queue size
|
||||
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
|
||||
|
||||
// Interrupt list
|
||||
#define INT_UART_RX ELUA_INT_FIRST_ID
|
||||
#define INT_ELUA_LAST INT_UART_RX
|
||||
|
||||
#define PLATFORM_CPU_CONSTANTS\
|
||||
_C( INT_UART_RX )
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU constants that should be exposed to the eLua "cpu" module
|
||||
|
||||
|
@ -16,30 +16,51 @@
|
||||
|
||||
#define BUILD_MMCFS
|
||||
//#define BUILD_XMODEM
|
||||
#define BUILD_SHELL
|
||||
#define BUILD_ROMFS
|
||||
//#define BUILD_TERM
|
||||
//#define BUILD_CON_GENERIC
|
||||
//#define BUILD_SHELL
|
||||
//#define BUILD_ROMFS
|
||||
#define BUILD_CON_GENERIC
|
||||
//#define BUILD_RPC
|
||||
#define BUF_ENABLE_UART
|
||||
#define BUILD_C_INT_HANDLERS
|
||||
//#define BUILD_ADC
|
||||
#define BUILA_LUA_INT_HANDLERS
|
||||
#define BUILD_LUA_INT_HANDLERS
|
||||
//#define BUILD_RFS
|
||||
//#define BUILD_SERMUX
|
||||
|
||||
#define BUILD_UIP
|
||||
#if defined( ELUA_CPU_AT32UC3A0128 )
|
||||
// Build options for 120KB image
|
||||
# define RAM_SIZE 0x8000
|
||||
#else
|
||||
// Build options for 256KB and 512KB flash
|
||||
# define RAM_SIZE 0x10000
|
||||
# define BUILD_ADC
|
||||
# define BUILD_LCD
|
||||
# define BUILD_TERM
|
||||
# define BUILD_UIP
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
//#define BUILD_DHCPC
|
||||
#define BUILD_DNS
|
||||
#define BUILD_CON_TCP
|
||||
//#define BUILD_CON_TCP
|
||||
#endif
|
||||
|
||||
// ****************************************************************************
|
||||
// Auxiliary libraries that will be compiled for this platform
|
||||
|
||||
// The name of the platform specific libs table
|
||||
#ifdef BUILD_LCD
|
||||
#define PS_LIB_TABLE_NAME "mizar32"
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
// UART/Timer IDs configuration data (used in main.c)
|
||||
|
||||
//#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
|
||||
#define CON_UART_ID 0
|
||||
#ifdef BUILD_SERMUX
|
||||
# define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
|
||||
#else
|
||||
# define CON_UART_ID 0
|
||||
#endif
|
||||
#define CON_UART_SPEED 115200
|
||||
#define CON_TIMER_ID 0
|
||||
#define TERM_LINES 25
|
||||
#define TERM_COLS 80
|
||||
|
||||
@ -75,6 +96,7 @@
|
||||
#else
|
||||
#define ADCLINE
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
#define NETLINE _ROM( AUXLIB_NET, luaopen_net, net_map )
|
||||
#else
|
||||
@ -87,11 +109,28 @@
|
||||
#define RPCLINE
|
||||
#endif
|
||||
|
||||
#if defined( PS_LIB_TABLE_NAME )
|
||||
#define PLATLINE _ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map )
|
||||
#else
|
||||
#define PLATLINE
|
||||
#endif
|
||||
|
||||
#if defined( ELUA_CPU_AT32UC3A0128 )
|
||||
|
||||
// Minimal ROM modules, to fit in 120KB
|
||||
#define LUA_PLATFORM_LIBS_ROM\
|
||||
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
|
||||
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
|
||||
#else
|
||||
|
||||
#define LUA_PLATFORM_LIBS_ROM\
|
||||
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
|
||||
_ROM( AUXLIB_UART, luaopen_uart, uart_map )\
|
||||
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
|
||||
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
|
||||
_ROM( AUXLIB_I2C, luaopen_i2c, i2c_map )\
|
||||
_ROM( AUXLIB_SPI, luaopen_spi, spi_map )\
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
NETLINE\
|
||||
@ -101,15 +140,10 @@
|
||||
RPCLINE\
|
||||
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
|
||||
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
|
||||
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )
|
||||
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
|
||||
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\
|
||||
PLATLINE\
|
||||
|
||||
#if MINIMAL_ROM_MODULES_TO_FIT_IN_120KB
|
||||
/* Minimal ROM modules, to fit in 120KB */
|
||||
#undef LUA_PLATFORM_LIBS_ROM
|
||||
#define LUA_PLATFORM_LIBS_ROM\
|
||||
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
|
||||
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
|
||||
NETLINE
|
||||
#endif
|
||||
|
||||
// *****************************************************************************
|
||||
@ -117,7 +151,7 @@
|
||||
|
||||
// Virtual timers (0 if not used)
|
||||
#define VTMR_NUM_TIMERS 4
|
||||
#define VTMR_FREQ_HZ 4
|
||||
#define VTMR_FREQ_HZ 10
|
||||
|
||||
// Number of resources (0 if not available/not implemented)
|
||||
#define NUM_PIO 4
|
||||
@ -128,8 +162,9 @@
|
||||
#else
|
||||
#define NUM_TIMER 3
|
||||
#endif
|
||||
#define NUM_PWM 7 // PWM7 is on GPIO50
|
||||
#define NUM_ADC 8 // Though ADC3 pin is the Ethernet IRQ
|
||||
#define NUM_PWM 6 // PWM7 is on GPIO50
|
||||
#define NUM_I2C 1
|
||||
#define NUM_ADC 8 // Though ADC3 pin is the Ethernet IRQ
|
||||
#define NUM_CAN 0
|
||||
|
||||
// As flow control seems not to work, we use a large buffer so that people
|
||||
@ -140,7 +175,6 @@
|
||||
|
||||
// RPC boot options
|
||||
#define RPC_UART_ID CON_UART_ID
|
||||
#define RPC_TIMER_ID CON_TIMER_ID
|
||||
#define RPC_UART_SPEED CON_UART_SPEED
|
||||
|
||||
// ADC Configuration Params
|
||||
@ -153,13 +187,11 @@
|
||||
#define ADC_NUM_TIMERS 0
|
||||
|
||||
// SD/MMC Filesystem Setup
|
||||
#define MMCFS_TICK_HZ 10
|
||||
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
|
||||
#define MMCFS_SPI_NUM 4
|
||||
#define MMCFS_CS_PORT 0
|
||||
#define MMCFS_CS_PIN SD_MMC_SPI_NPCS_PIN
|
||||
|
||||
// CPU frequency (needed by the CPU module, 0 if not used)
|
||||
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
|
||||
#define CPU_FREQUENCY REQ_CPU_FREQ
|
||||
|
||||
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
|
||||
@ -169,6 +201,7 @@
|
||||
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
|
||||
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
|
||||
#define PIO_PIN_ARRAY { 31, 32, 32, 14 }
|
||||
#define AVR32_NUM_GPIO 110 // actually 109, but consider also PA31
|
||||
|
||||
#ifdef BOOTLOADER_EMBLOD
|
||||
# define ELUA_FIRMWARE_SIZE 0x80000
|
||||
@ -179,14 +212,10 @@
|
||||
// Allocator data: define your free memory zones here in two arrays
|
||||
// (start address and end address)
|
||||
#define MEM_START_ADDRESS { ( void* )end, ( void* )( SDRAM + ELUA_FIRMWARE_SIZE ) }
|
||||
#define MEM_END_ADDRESS { ( void* )( 0x8000 - STACK_SIZE_TOTAL - 1 ), ( void* )( SDRAM + SDRAM_SIZE - 1 ) }
|
||||
|
||||
// Interrupt queue size
|
||||
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
|
||||
#define MEM_END_ADDRESS { ( void* )( RAM_SIZE - STACK_SIZE_TOTAL - 1 ), ( void* )( SDRAM + SDRAM_SIZE - 1 ) }
|
||||
|
||||
#define RFS_BUFFER_SIZE BUF_SIZE_512
|
||||
#define RFS_UART_ID ( SERMUX_SERVICE_ID_FIRST )
|
||||
#define RFS_TIMER_ID 0
|
||||
#define RFS_TIMEOUT 100000
|
||||
#define RFS_UART_SPEED 115200
|
||||
|
||||
@ -195,13 +224,6 @@
|
||||
//#define SERMUX_NUM_VUART 2
|
||||
//#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
|
||||
|
||||
// Interrupt list
|
||||
#define INT_UART_RX ELUA_INT_FIRST_ID
|
||||
#define INT_ELUA_LAST INT_UART_RX
|
||||
|
||||
#define PLATFORM_CPU_CONSTANTS\
|
||||
_C( INT_UART_RX )
|
||||
|
||||
// *****************************************************************************
|
||||
// CPU constants that should be exposed to the eLua "cpu" module
|
||||
|
||||
|
@ -87,11 +87,7 @@ void adc_disable(volatile avr32_adc_t * adc, unsigned short channel)
|
||||
Assert( adc!=NULL );
|
||||
Assert( channel <= AVR32_ADC_CHANNELS_MSB ); // check if channel exist
|
||||
|
||||
if (adc_get_status(adc, channel) == ENABLED)
|
||||
{
|
||||
// disable channel
|
||||
adc->chdr |= (1 << channel);
|
||||
}
|
||||
adc->chdr = (1 << channel);
|
||||
}
|
||||
|
||||
Bool adc_get_status(volatile avr32_adc_t * adc, unsigned short channel)
|
||||
|
50
src/platform/avr32/at32uc3a0256.ld
Normal file
50
src/platform/avr32/at32uc3a0256.ld
Normal file
@ -0,0 +1,50 @@
|
||||
MEMORY
|
||||
{
|
||||
sram (W!RX) : ORIGIN = 0x00000004, LENGTH = 0x0000FFFC
|
||||
flash (RX) : ORIGIN = 0x80002000, LENGTH = 0x00040000 - 0x2000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_stext = .;
|
||||
PROVIDE(stext = .);
|
||||
KEEP(*(.start))
|
||||
*(.text .text.*)
|
||||
*(.rodata .rodata.*)
|
||||
*(.gnu.linkonce.t.*)
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.exception .exception.*)
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
} >flash
|
||||
|
||||
.data : AT (_etext)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_data = .;
|
||||
*(.ramfunc .ramfunc.* .fastrun .fastrun.*)
|
||||
*(.data .data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
. = ALIGN(4);
|
||||
_edata = .;
|
||||
} >sram
|
||||
|
||||
.bss (NOLOAD) : {
|
||||
_bss = .;
|
||||
*(.bss .bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = .;
|
||||
} >sram
|
||||
|
||||
end = .;
|
||||
_sstack = 0x00010000;
|
||||
}
|
@ -120,7 +120,16 @@
|
||||
#define FRCOSC AVR32_PM_RCOSC_FREQUENCY //!< Default RCOsc frequency.
|
||||
#endif
|
||||
|
||||
#if BOARD == MIZAR32
|
||||
// All Mizar32 peripherals seem to work OK at max freq:
|
||||
// All derived frequencies (sdram, USB, tmr, VTMT, SPI, UARTs, PWM, MMC)
|
||||
// compensate correctly for the different PBA freq and
|
||||
// tmr.getmaxdelay() is still just over 0.5 sec (by a hair!).
|
||||
#define REQ_CPU_FREQ 66000000
|
||||
#define REQ_PBA_FREQ 16500000
|
||||
#else
|
||||
#define REQ_CPU_FREQ 60000000
|
||||
#define REQ_PBA_FREQ 15000000
|
||||
#endif
|
||||
|
||||
#endif // _BOARD_H_
|
||||
|
@ -1,6 +1,6 @@
|
||||
-- Configuration file for the AVR32 microcontrollers
|
||||
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c ethernet.c"
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c lcd.c"
|
||||
addm( "FORAVR32" )
|
||||
|
||||
-- See board.h for possible BOARD values.
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Configuration file for the AVR32 microcontrollers
|
||||
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c ethernet.c"
|
||||
specific_files = "crt0.s trampoline.s platform.c exception.s intc.c pm.c flashc.c pm_conf_clocks.c usart.c gpio.c tc.c spi.c platform_int.c adc.c pwm.c i2c.c ethernet.c lcd.c"
|
||||
comp.Append(CPPDEFINES = 'FORAVR32')
|
||||
|
||||
# See board.h for possible BOARD values.
|
||||
|
@ -789,7 +789,7 @@ __attribute__((__interrupt__)) void vMACB_ISR(void)
|
||||
// Variable definitions can be made now.
|
||||
volatile unsigned long ulIntStatus, ulEventStatus;
|
||||
|
||||
// Find the cause of the interrupt.
|
||||
// Find the cause of the interrupt.
|
||||
ulIntStatus = AVR32_MACB.isr;
|
||||
ulEventStatus = AVR32_MACB.rsr;
|
||||
|
||||
|
@ -275,7 +275,7 @@ to use an MII interface. */
|
||||
#define ETHERNET_CONF_TX_BUFFER_SIZE 512
|
||||
|
||||
/*! Clock definition */
|
||||
#define ETHERNET_CONF_SYSTEM_CLOCK 60000000
|
||||
#define ETHERNET_CONF_SYSTEM_CLOCK REQ_CPU_FREQ
|
||||
|
||||
/*! Allow Auto Negociation */
|
||||
#define ETHERNET_CONF_AN_ENABLE 1
|
||||
|
352
src/platform/avr32/i2c.c
Normal file
352
src/platform/avr32/i2c.c
Normal file
@ -0,0 +1,352 @@
|
||||
// This file implements I2C protocol on AVR32 devices in eLua.
|
||||
//
|
||||
// For reasons outlined below, it does not use the Atmel TWI hardware
|
||||
// but implements it by bit-banging two GPIO lines.
|
||||
//
|
||||
// Martin Guy <martinwguy@gmail.com>, June 2011
|
||||
|
||||
// AVR32 has two families of "two wire" interfaces, both of them inadequate:
|
||||
//
|
||||
// AT32UC3A[01]* and AT32UC3B* have a single "TWI" "I2C-compatibile" interface
|
||||
// that can be switched between master and slave modes;
|
||||
// AT32UC3A[34]* and AT32UC3C* devices have separate "TWIM" and "TWIS"
|
||||
// interfaces, three of each in the C series.
|
||||
// Their registers and functionality are completely different,
|
||||
//
|
||||
// All currently supported eLua AVR32 targets
|
||||
// (EVK1100 Mizar32 == AT32UC3A0* and EVK1101 == AT32UC3B*)
|
||||
// have one "TWI" interface.
|
||||
//
|
||||
// 1) "TWI" hardware limitations
|
||||
//
|
||||
// The only repeated start sequence that TWI can generate as master is
|
||||
// START/ADDRESS(W)/WRITE 1, 2 or 3 bytes/START/ADDRESS(R)/READ n BYTES/STOP.
|
||||
//
|
||||
// It cannot emit START/ADDRESS(R/W)/STOP, which is necessary to probe
|
||||
// for the presence of a device on the bus. Their SDK writes a single 0 bytes
|
||||
// to do this, which has different effects on different hardware.
|
||||
// This makes I2C unimplementable using this variant of the hardware.
|
||||
//
|
||||
// Worse, you have to have all the data in hand before you start any transfer
|
||||
// because if you fail to rewrite the "Transmit Holding Register" with the next
|
||||
// byte while the current byte is being sent, the hardware automatically
|
||||
// generates a STOP without asking you.
|
||||
// This makes eLua's current Lua and C I2C interfaces unimplementable.
|
||||
//
|
||||
// 2) "TWIM" and "TWIS" hardware limitations
|
||||
//
|
||||
// This seems to be able to generate a wider range of repeated start signals
|
||||
// but the amount of data you can send or receive in one packet is limited to
|
||||
// 255 bytes.
|
||||
//
|
||||
// 3) Bit-banging them as GPIO pins
|
||||
//
|
||||
// Given the two sets of incompatible hardware and the fact that neither is
|
||||
// capable either of speaking I2C or of implementing the current eLua I2C
|
||||
// interface, we just bit-bang the IO pins.
|
||||
//
|
||||
// Some of the chips (e.g. AVR32UC3[01]*) have a GPIO open-collector mode,
|
||||
// which sounds promising, but others (AVR32UC3A[34], AVR32UC3[BC]) do not
|
||||
// so we obtain a pseudo-open-collector mode by switching the GPIO pins
|
||||
// between output (always low) and input (of high impedance).
|
||||
//
|
||||
// The disadvantage of bit-banging GPIO pins instead of using the TWI hardware
|
||||
// is that in TWI mode, the pins "are open-drain outputs with slew-rate
|
||||
// limitation and inputs with spike-filtering" (AT32UC3A Datasheet, para 8.3).
|
||||
// In GPIO mode, a "glitch filter" is available to reject pulses of 1 CPU cycle
|
||||
// but this only affects the interrupt function, not the value read from the
|
||||
// PVR register. (para 22.4.8)
|
||||
|
||||
// This first hack only support a single I2C channel and is only tested on the
|
||||
// currently supported hardware (AVR32UC3A0*), all of which has a single TWI
|
||||
// interface.
|
||||
// To extend it to have multiple I2C channels you need to turn the variables
|
||||
// started, delay, sda_regs, scl_regs
|
||||
// and the constants
|
||||
// {SDA,SCL}_{PIN,PORT,PINMASK}
|
||||
// into arrays[NUM_I2C] and index them with id.
|
||||
|
||||
#include "platform_conf.h"
|
||||
#include "compiler.h"
|
||||
#include "gpio.h"
|
||||
#include "i2c.h"
|
||||
|
||||
// Which port/pins are used for I2C?
|
||||
|
||||
#if defined(ELUA_CPU_AT32UC3A0128) || \
|
||||
defined(ELUA_CPU_AT32UC3A0256) || \
|
||||
defined(ELUA_CPU_AT32UC3A0512) || \
|
||||
defined(ELUA_CPU_AT32UC3A1128) || \
|
||||
defined(ELUA_CPU_AT32UC3A1256) || \
|
||||
defined(ELUA_CPU_AT32UC3A1512)
|
||||
|
||||
// One master-slave TWI interface
|
||||
# define SDA_PIN AVR32_PIN_PA29
|
||||
# define SCL_PIN AVR32_PIN_PA30
|
||||
|
||||
#elif defined(ELUA_CPU_AT32UC3A364) || defined(ELUA_CPU_AT32UC3A364S) || \
|
||||
defined(ELUA_CPU_AT32UC3A3128) || defined(ELUA_CPU_AT32UC3A3128S) || \
|
||||
defined(ELUA_CPU_AT32UC3A3256) || defined(ELUA_CPU_AT32UC3A3256S) || \
|
||||
defined(ELUA_CPU_AT32UC3A464) || defined(ELUA_CPU_AT32UC3A464S) || \
|
||||
defined(ELUA_CPU_AT32UC3A4128) || defined(ELUA_CPU_AT32UC3A4128S) || \
|
||||
defined(ELUA_CPU_AT32UC3A4256) || defined(ELUA_CPU_AT32UC3A4256S)
|
||||
|
||||
// The first of the two TWIM/TWIS interfaces, in pin configuration A
|
||||
# define SDA_PIN AVR32_PIN_PA25
|
||||
# define SCL_PIN AVR32_PIN_PA26
|
||||
|
||||
#elif defined(ELUA_CPU_AT32UC3B064) || \
|
||||
defined(ELUA_CPU_AT32UC3B0128) || \
|
||||
defined(ELUA_CPU_AT32UC3B0256) || \
|
||||
defined(ELUA_CPU_AT32UC3B0512) || \
|
||||
defined(ELUA_CPU_AT32UC3B164) || \
|
||||
defined(ELUA_CPU_AT32UC3B1128) || \
|
||||
defined(ELUA_CPU_AT32UC3B1256) || \
|
||||
defined(ELUA_CPU_AT32UC3B1512)
|
||||
|
||||
// One master-slave TWI interface
|
||||
# define SDA_PIN AVR32_PIN_PA10
|
||||
# define SCL_PIN AVR32_PIN_PA09
|
||||
|
||||
#elif defined(ELUA_CPU_AT32UC3C064C) || \
|
||||
defined(ELUA_CPU_AT32UC3C0128C) || \
|
||||
defined(ELUA_CPU_AT32UC3C0256C) || \
|
||||
defined(ELUA_CPU_AT32UC3C0512C) || \
|
||||
defined(ELUA_CPU_AT32UC3C164C) || \
|
||||
defined(ELUA_CPU_AT32UC3C1128C) || \
|
||||
defined(ELUA_CPU_AT32UC3C1256C) || \
|
||||
defined(ELUA_CPU_AT32UC3C1512C) || \
|
||||
defined(ELUA_CPU_AT32UC3C264C) || \
|
||||
defined(ELUA_CPU_AT32UC3C2128C) || \
|
||||
defined(ELUA_CPU_AT32UC3C2256C) || \
|
||||
defined(ELUA_CPU_AT32UC3C2512C)
|
||||
|
||||
// One master-slave TWI interface
|
||||
# define SDA_PIN AVR32_PIN_PC02
|
||||
# define SCL_PIN AVR32_PIN_PC03
|
||||
|
||||
#else
|
||||
# error "I2C pin assignment is unknown for this CPU"
|
||||
#endif
|
||||
|
||||
// Split these into port and pinmask
|
||||
#define SDA_PORT ( SDA_PIN >> 5 )
|
||||
#define SCL_PORT ( SCL_PIN >> 5 )
|
||||
#define SDA_PINMASK ( 1 << ( SDA_PIN & 31 ) )
|
||||
#define SCL_PINMASK ( 1 << ( SCL_PIN & 31 ) )
|
||||
|
||||
// The set of GPIO registers we will be using for each bus line.
|
||||
// In practice, these two will always have the same value. Ho hum.
|
||||
static volatile avr32_gpio_port_t *sda_regs =
|
||||
&AVR32_GPIO.port[ SDA_PORT ];
|
||||
static volatile avr32_gpio_port_t *scl_regs =
|
||||
&AVR32_GPIO.port[ SCL_PORT ];
|
||||
|
||||
// Half an I2C bus clock cycle, as a number of HSB(==CPU) clock cycles;
|
||||
// Be default, use the slow mode setting.
|
||||
// This is exported to the LCD display driver ("disp") so that it can
|
||||
// change the bus speed as required by the LCD, then restore it.
|
||||
u32 i2c_delay = REQ_CPU_FREQ / 100000 / 2;
|
||||
|
||||
// Local functions used by the bit-banger
|
||||
static void I2CDELAY(void); // Pause for half an I2C bus clock cycle
|
||||
static int READSCL(void); // Set SCL as input and return current level of line
|
||||
static int READSDA(void); // Set SDA as input and return current level of line
|
||||
static void CLRSCL(void); // Actively drive SCL signal low
|
||||
static void CLRSDA(void); // Actively drive SDA signal low
|
||||
static void ARBITRATION_LOST(void); // Bus control was lost
|
||||
|
||||
// ************************
|
||||
// The bitbanger itself, taken from http://en.wikipedia.org/wiki/I2C
|
||||
|
||||
// We don't use GPIO open-drain mode, which is not available on all hardware
|
||||
// models. Instead, we use two modes to simulate open-drain:
|
||||
// output of 0 and input.
|
||||
u32 i2c_setup( u32 speed )
|
||||
{
|
||||
// First, set both pins as high-impedance inputs to avoid startup glitches
|
||||
sda_regs->oderc = SDA_PINMASK;
|
||||
scl_regs->oderc = SCL_PINMASK;
|
||||
|
||||
// When they are outputs, they will always output 0.
|
||||
sda_regs->ovrc = SDA_PINMASK;
|
||||
scl_regs->ovrc = SCL_PINMASK;
|
||||
|
||||
// Let the GPIO hardware control these pins
|
||||
sda_regs->gpers = SDA_PINMASK;
|
||||
scl_regs->gpers = SCL_PINMASK;
|
||||
|
||||
// Limit range to possible values, to avoid divisions by zero below.
|
||||
if (speed == 0) speed = 1;
|
||||
if (speed > REQ_CPU_FREQ / 2) speed = REQ_CPU_FREQ / 2;
|
||||
|
||||
// Figure out how many clock cycles correspond to half a clock waveform.
|
||||
// "+(speed-1)" ensures we never set a faster speed than what they asked for.
|
||||
i2c_delay = ( REQ_CPU_FREQ / 2 + (speed - 1) ) / speed;
|
||||
|
||||
// Return the closest integer to the actual speed we set
|
||||
return ( REQ_CPU_FREQ / 2 + i2c_delay / 2 ) / i2c_delay;
|
||||
}
|
||||
|
||||
// Are we between a start bit and a stop bit?
|
||||
static int started = 0;
|
||||
|
||||
void i2c_start_cond(void)
|
||||
{
|
||||
if (started) {
|
||||
// if started, do a restart cond
|
||||
// set SDA to 1
|
||||
READSDA();
|
||||
I2CDELAY();
|
||||
// Clock stretching
|
||||
while (READSCL() == 0)
|
||||
; // You can add a timeout to this loop to
|
||||
// recover from SCL being stuck low.
|
||||
// Repeated start setup time, minimum 4.7us
|
||||
I2CDELAY();
|
||||
}
|
||||
if (READSDA() == 0)
|
||||
ARBITRATION_LOST();
|
||||
// SCL is high, set SDA from 1 to 0
|
||||
CLRSDA();
|
||||
I2CDELAY();
|
||||
CLRSCL();
|
||||
started = true;
|
||||
}
|
||||
|
||||
void i2c_stop_cond(void)
|
||||
{
|
||||
/* set SDA to 0 */
|
||||
CLRSDA();
|
||||
I2CDELAY();
|
||||
/* Clock stretching */
|
||||
while (READSCL() == 0)
|
||||
; /* You should add timeout to this loop */
|
||||
/* SCL is high. Respect I2C spec's minimum stop setup time of 4ms. */
|
||||
I2CDELAY();
|
||||
/* set SDA from 0 to 1 */
|
||||
if (READSDA() == 0)
|
||||
ARBITRATION_LOST();
|
||||
I2CDELAY();
|
||||
started = false;
|
||||
}
|
||||
|
||||
/* Write a bit to I2C bus */
|
||||
static void i2c_write_bit(int bit)
|
||||
{
|
||||
if (bit)
|
||||
READSDA();
|
||||
else
|
||||
CLRSDA();
|
||||
I2CDELAY();
|
||||
/* Clock stretching */
|
||||
while (READSCL() == 0)
|
||||
; /* You should add timeout to this loop */
|
||||
/* SCL is high, now data is valid */
|
||||
/* If SDA is high, check that nobody else is driving SDA */
|
||||
if (bit && READSDA() == 0)
|
||||
ARBITRATION_LOST();
|
||||
I2CDELAY();
|
||||
CLRSCL();
|
||||
}
|
||||
|
||||
/* Read a bit from I2C bus */
|
||||
static int i2c_read_bit(void)
|
||||
{
|
||||
int bit;
|
||||
|
||||
/* Let the slave drive data */
|
||||
READSDA();
|
||||
I2CDELAY();
|
||||
/* Clock stretching */
|
||||
while (READSCL() == 0)
|
||||
; /* You should add timeout to this loop */
|
||||
/* SCL is high, now data is valid */
|
||||
bit = READSDA();
|
||||
I2CDELAY();
|
||||
CLRSCL();
|
||||
return bit;
|
||||
}
|
||||
|
||||
/* Write a byte to I2C bus. Return 0 if ack by the slave */
|
||||
int i2c_write_byte(unsigned char byte)
|
||||
{
|
||||
unsigned bit;
|
||||
int nack;
|
||||
|
||||
for (bit = 0; bit < 8; bit++) {
|
||||
i2c_write_bit((byte & 0x80) != 0);
|
||||
byte <<= 1;
|
||||
}
|
||||
nack = i2c_read_bit();
|
||||
|
||||
return nack;
|
||||
}
|
||||
|
||||
/* Read a byte from I2C bus */
|
||||
unsigned char i2c_read_byte(int nack)
|
||||
{
|
||||
unsigned char byte = 0;
|
||||
unsigned bit;
|
||||
|
||||
for (bit = 0; bit < 8; bit++)
|
||||
byte = (byte << 1) | i2c_read_bit();
|
||||
i2c_write_bit(nack);
|
||||
|
||||
return byte;
|
||||
}
|
||||
|
||||
//*******************
|
||||
// Low-level functions used by the bit-banger
|
||||
|
||||
// Pause for half an I2C bus clock cycle
|
||||
static void I2CDELAY()
|
||||
{
|
||||
// Code stolen from sdramc.c::sdramc_ck_delay()
|
||||
|
||||
// Use the CPU cycle counter (CPU and HSB clocks are the same).
|
||||
u32 delay_start_cycle = Get_system_register(AVR32_COUNT);
|
||||
u32 delay_end_cycle = delay_start_cycle + i2c_delay;
|
||||
|
||||
// To be safer, the end of wait is based on an inequality test, so CPU cycle
|
||||
// counter wrap around is checked.
|
||||
if (delay_start_cycle > delay_end_cycle)
|
||||
{
|
||||
while ((unsigned long)Get_system_register(AVR32_COUNT) > delay_end_cycle);
|
||||
}
|
||||
while ((unsigned long)Get_system_register(AVR32_COUNT) < delay_end_cycle);
|
||||
}
|
||||
|
||||
// Set SCL as input and return current level of line
|
||||
static int READSCL()
|
||||
{
|
||||
scl_regs->oderc = SCL_PINMASK;
|
||||
return ( scl_regs->pvr & SCL_PINMASK ) ? 1 : 0;
|
||||
}
|
||||
|
||||
// Set SDA as input and return current level of line
|
||||
static int READSDA()
|
||||
{
|
||||
sda_regs->oderc = SDA_PINMASK;
|
||||
return ( sda_regs->pvr & SDA_PINMASK ) ? 1 : 0;
|
||||
}
|
||||
|
||||
// Actively drive SCL signal low
|
||||
static void CLRSCL(void)
|
||||
{
|
||||
scl_regs->oders = SCL_PINMASK;
|
||||
}
|
||||
|
||||
// Actively drive SDA signal low
|
||||
static void CLRSDA(void)
|
||||
{
|
||||
sda_regs->oders = SDA_PINMASK;
|
||||
}
|
||||
|
||||
// Bus control was lost.
|
||||
// Not currently used. With a higher-level I2C interface, this can do a
|
||||
// longjmp back to the eLua C interface routine which can retry the transfer
|
||||
// when the bus is free.
|
||||
static void ARBITRATION_LOST(void)
|
||||
{
|
||||
}
|
9
src/platform/avr32/i2c.h
Normal file
9
src/platform/avr32/i2c.h
Normal file
@ -0,0 +1,9 @@
|
||||
// Declarations for the low-level AVR32 I2C driver for eLua
|
||||
|
||||
#include "type.h" // for u32
|
||||
|
||||
u32 i2c_setup( u32 speed ); // speed is in Hz
|
||||
void i2c_start_cond( void );
|
||||
void i2c_stop_cond( void );
|
||||
int i2c_write_byte( unsigned char byte ); // returns 0 if acked by slave
|
||||
unsigned char i2c_read_byte( int nack );
|
392
src/platform/avr32/lcd.c
Normal file
392
src/platform/avr32/lcd.c
Normal file
@ -0,0 +1,392 @@
|
||||
// eLua module for Mizar32 LCD character display
|
||||
|
||||
#include "lua.h"
|
||||
#include "lualib.h"
|
||||
#include "lauxlib.h"
|
||||
#include "platform.h"
|
||||
#include "lrotable.h"
|
||||
#include "platform_conf.h"
|
||||
|
||||
#include "lcd.h"
|
||||
#include "i2c.h"
|
||||
|
||||
|
||||
// Since the LCD firmware currently only runs at up to 20kHz on the I2C bus,
|
||||
// we bracket all I2C packets to the LCD module with two functions
|
||||
// to be able to save, change and restore the I2C clock rate to what it was
|
||||
// before.
|
||||
|
||||
// Declarations to save/restore the I2C clock rate
|
||||
extern u32 i2c_delay;
|
||||
static u32 old_i2c_delay;
|
||||
|
||||
static void lcd_start()
|
||||
{
|
||||
old_i2c_delay = i2c_delay;
|
||||
i2c_delay = REQ_CPU_FREQ / LCD_BUS_FREQ / 2;
|
||||
}
|
||||
|
||||
static void lcd_stop()
|
||||
{
|
||||
i2c_delay = old_i2c_delay;
|
||||
}
|
||||
|
||||
|
||||
// Low-level functions to send LCD commands or data.
|
||||
// The command and data packets differ only in the slave address used,
|
||||
// so we coalesce them into a single function, generating smaller code.
|
||||
//
|
||||
// All three are designed to be used in a tail call:
|
||||
// return send_generic( data, len );
|
||||
|
||||
// Send a command or data packet.
|
||||
// "address" is LCD_CMD for LCD commands, LCD_DATA for LCD data.
|
||||
static int send_generic(char address, const char *data, int len)
|
||||
{
|
||||
while (len > 0) {
|
||||
int nbytes; // number of bytes sent in this I2C packet
|
||||
|
||||
lcd_start();
|
||||
i2c_start_cond();
|
||||
i2c_write_byte( address );
|
||||
// Mizar32 LCD module has a maximum of 31 bytes per data packet
|
||||
nbytes = 0;
|
||||
while ( len > 0 && nbytes < 31 ) {
|
||||
i2c_write_byte( *data++ );
|
||||
nbytes++; len--;
|
||||
}
|
||||
i2c_stop_cond();
|
||||
lcd_stop();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Send a single command byte
|
||||
static int send_command(const char command)
|
||||
{
|
||||
return send_generic(LCD_CMD, &command, 1);
|
||||
}
|
||||
|
||||
// Send multiple command bytes as one message
|
||||
static int send_commands(const char *commands, int len)
|
||||
{
|
||||
return send_generic(LCD_CMD, commands, len);
|
||||
}
|
||||
|
||||
// Send data bytes
|
||||
// This is used for printing data and for programming the user-defining chars
|
||||
static int send_data(const char *data, int len)
|
||||
{
|
||||
return send_generic(LCD_DATA, data, len);
|
||||
}
|
||||
|
||||
|
||||
// *** Lua module functions begin... ***
|
||||
|
||||
|
||||
// Turning the display on can only be achieved by simultaneously specifying the
|
||||
// cursor type, so we have to remember what type of cursor they last set.
|
||||
// Similarly, if they have turned the display off then set the cursor, this
|
||||
// shouldn-t turn the display on.
|
||||
|
||||
// Power-on setting is no cursor
|
||||
#define DEFAULT_CURSOR_TYPE LCD_CMD_CURSOR_NONE
|
||||
|
||||
static char cursor_type = DEFAULT_CURSOR_TYPE;
|
||||
static char display_is_off = 0; // Have they called display("off")?
|
||||
|
||||
|
||||
// Should we try to maintain the current cursor position across a definechar()?
|
||||
// Unfortunately we can't read the current cursor position, and definechar()
|
||||
// destroys it. The LCD controller does have a read-cursor-position primitive
|
||||
// but the current PIC firmware doesn't pass this on as an I2C read.2
|
||||
// So we have to track the cursor position. Yuk.
|
||||
// The only relief is that we don't have to track the display scrolling.
|
||||
// Adds 284 bytes of code to the executable.
|
||||
//
|
||||
// If, one day, we can read the LCD cursor position through the PIC firmware
|
||||
// we can remove all this stuff.
|
||||
#define KEEP_CURSOR_POSITION 1
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Where is the cursor in the character memory? Required ONLY to be able to
|
||||
// restore the cursor position when they define a character :-/
|
||||
static int current_row = 0; // 0 or 1
|
||||
static int current_column = 0; // 0-39 (though it over- and underflows)
|
||||
static int current_direction = 1; // left-to-right. -1 is right-to-left
|
||||
#endif
|
||||
|
||||
|
||||
// Lua: mizar32.disp.reset()
|
||||
// Ensure the display is in a known initial state
|
||||
static int lcd_reset( lua_State *L )
|
||||
{
|
||||
// Initialise the display to a known state
|
||||
static const char reset[] = {
|
||||
0 /* reset */
|
||||
};
|
||||
|
||||
// Set the static variables
|
||||
cursor_type = DEFAULT_CURSOR_TYPE;
|
||||
display_is_off = 0;
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
current_direction = 1;
|
||||
#endif
|
||||
|
||||
return send_commands( reset, sizeof( reset ) );
|
||||
}
|
||||
|
||||
// "Entry mode" function.
|
||||
|
||||
// Lua: mizar32.disp.setup( shift_display, right-to-left )
|
||||
// Set right-to-left mode,
|
||||
static int lcd_setup( lua_State *L )
|
||||
{
|
||||
// lua_toboolean returns 0 or 1, and returns 0 if the parameter is absent
|
||||
unsigned shift_display = lua_toboolean( L, 1 ); // Default: move cursor
|
||||
unsigned right_to_left = lua_toboolean( L, 2 ); // Default: print left-to-right
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_direction = right_to_left ? -1 : 1;
|
||||
#endif
|
||||
|
||||
return send_command( LCD_CMD_ENTRYMODE + shift_display +
|
||||
(!right_to_left) * 2 );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.clear()
|
||||
// Clear the display, reset its shiftedness and put the cursor at 1,1
|
||||
static int lcd_clear( lua_State *L )
|
||||
{
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
#endif
|
||||
return send_command( LCD_CMD_CLEAR );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.home()
|
||||
// Reset the display's shiftedness and put the cursor at 1,1
|
||||
static int lcd_home(lua_State *L)
|
||||
{
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = current_column = 0;
|
||||
#endif
|
||||
return send_command( LCD_CMD_HOME );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.goto( row, col )
|
||||
// Move the cursor to the specified row (1 or 2) and column (1-40)
|
||||
// in the character memory.
|
||||
static int lcd_goto(lua_State *L)
|
||||
{
|
||||
unsigned row = luaL_checkinteger( L, 1 );
|
||||
unsigned col = luaL_checkinteger( L, 2 );
|
||||
unsigned address;
|
||||
|
||||
if ( row < 1 || row > 2 || col < 1 || col > 40 )
|
||||
return luaL_error( L, "row/column must be 1-2 and 1-40" );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_row = row - 1;
|
||||
current_column = col - 1;
|
||||
#endif
|
||||
address = ( row - 1 ) * 0x40 + ( col - 1 ) ;
|
||||
return send_command( LCD_CMD_DDADDR + address );
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.print( string )
|
||||
// Send data bytes to the LCD module.
|
||||
// Usually this will be a string of text or a list of character codes.
|
||||
// If they pass us integer values <0 or >255, we just use the bottom 8 bits.
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Adjust current cursor position by N printed characters.
|
||||
// Written for shortest code.
|
||||
static void current_print(int n)
|
||||
{
|
||||
current_column += current_direction * n;
|
||||
if (current_column < 0 || current_column >= 40) {
|
||||
current_row = ! current_row;
|
||||
current_column -= 40 * current_direction;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lcd_print(lua_State *L)
|
||||
{
|
||||
unsigned argc = lua_gettop( L ); // Number of parameters supplied
|
||||
int argn;
|
||||
|
||||
for ( argn = 1; argn <= argc; argn ++ )
|
||||
{
|
||||
switch (lua_type( L, argn ) )
|
||||
{
|
||||
case LUA_TNUMBER:
|
||||
{
|
||||
char byte = luaL_checkint( L, argn );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_print(1);
|
||||
#endif
|
||||
send_data(&byte, (size_t) 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case LUA_TSTRING:
|
||||
{
|
||||
size_t len; // Number of chars in string
|
||||
const char *str = luaL_checklstring( L, argn, &len );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
current_print(len);
|
||||
#endif
|
||||
send_data(str, len);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return luaL_typerror( L, argn, "integer or string" );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// "Display on/off control" functions
|
||||
|
||||
// Helper function to set a cursor type if the display is on,
|
||||
// or to remember which cursor they asked for, to be able to set it
|
||||
// when they turn the display on.
|
||||
static int set_cursor( char command_byte )
|
||||
{
|
||||
cursor_type = command_byte;
|
||||
|
||||
// Setting cursor type always turns the display on
|
||||
if (display_is_off)
|
||||
return 0;
|
||||
else
|
||||
return send_command( cursor_type );
|
||||
}
|
||||
|
||||
// Perform cursor operations, selected by a string parameter,
|
||||
// as recommended in the Lua Reference Manual, p.58: "luaL_checkoption()"
|
||||
static int lcd_cursor( lua_State *L )
|
||||
{
|
||||
static const char const *args[] =
|
||||
{ "none", "block", "line", "left", "right", NULL };
|
||||
|
||||
switch ( luaL_checkoption( L, 1, NULL, args ) )
|
||||
{
|
||||
case 0:
|
||||
return set_cursor( LCD_CMD_CURSOR_NONE );
|
||||
case 1:
|
||||
return set_cursor( LCD_CMD_CURSOR_BLOCK );
|
||||
case 2:
|
||||
return set_cursor( LCD_CMD_CURSOR_LINE );
|
||||
|
||||
case 3:
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
if (--current_column < 0) {
|
||||
current_row = !current_row;
|
||||
current_column = 39;
|
||||
}
|
||||
#endif
|
||||
return send_command( LCD_CMD_SHIFT_CURSOR_LEFT );
|
||||
|
||||
case 4:
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
if (++current_column >= 40) {
|
||||
current_row = !current_row;
|
||||
current_column = 0;
|
||||
}
|
||||
#endif
|
||||
return send_command( LCD_CMD_SHIFT_CURSOR_RIGHT );
|
||||
|
||||
default: return luaL_argerror( L, 1, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Perform display operations, selected by a string parameter.
|
||||
static int lcd_display( lua_State *L )
|
||||
{
|
||||
static const char const *args[] =
|
||||
{ "off", "on", "left", "right", NULL };
|
||||
|
||||
switch ( luaL_checkoption( L, 1, NULL, args ) )
|
||||
{
|
||||
case 0: display_is_off = 1;
|
||||
return send_command( LCD_CMD_DISPLAY_OFF );
|
||||
case 1: display_is_off = 0;
|
||||
return send_command( cursor_type ); // Turns display on
|
||||
case 2: return send_command( LCD_CMD_SHIFT_DISPLAY_LEFT );
|
||||
case 3: return send_command( LCD_CMD_SHIFT_DISPLAY_RIGHT );
|
||||
default: return luaL_argerror( L, 1, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Lua: mizar32.disp.definechar( code, glyph )
|
||||
// code: 0-7
|
||||
// glyph: a table of up to 8 numbers with values 0-31.
|
||||
// If less than 8 are supplied, the bottom rows are blanked.
|
||||
// If more than 8 are supplied, the extra are ignored.
|
||||
|
||||
static int lcd_definechar( lua_State *L ) {
|
||||
int code; // The character code we are defining, 0-7
|
||||
size_t datalen; // The number of elements in the glyph table
|
||||
size_t line; // Which line of the char are we defining?
|
||||
char data[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
int old_column = current_column, old_row = current_row;
|
||||
#endif
|
||||
|
||||
// First parameter: glyph code to define
|
||||
code = luaL_checkint( L, 1 );
|
||||
if( code < 0 || code > 7 )
|
||||
return luaL_error( L, "user-defined characters have codes 0-7");
|
||||
|
||||
// Second parameter: table of integer values to define the glyph
|
||||
luaL_checktype( L, 2, LUA_TTABLE );
|
||||
datalen = lua_objlen( L, 2 );
|
||||
// Check all parameters before starting the I2C command.
|
||||
if( datalen >= 8) datalen = 8; // Ignore extra parameters
|
||||
for( line = 0; line < datalen; line ++ )
|
||||
{
|
||||
int value;
|
||||
lua_rawgeti( L, 2, line + 1 );
|
||||
value = luaL_checkint( L, -1 );
|
||||
lua_pop( L, 1 );
|
||||
data[line] = value;
|
||||
}
|
||||
|
||||
send_command( LCD_CMD_CGADDR + code * 8 );
|
||||
send_data( data, sizeof(data) );
|
||||
|
||||
#ifdef KEEP_CURSOR_POSITION
|
||||
// Move back to where we were
|
||||
current_row = old_row; current_column = old_column;
|
||||
return send_command( LCD_CMD_DDADDR + current_row * 0x40 + current_column );
|
||||
#else
|
||||
// Sadly, we cannot save and restore the current cursor position
|
||||
// so return to the home position.
|
||||
return send_command( LCD_CMD_DDADDR );
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lrodefs.h"
|
||||
|
||||
// mizar32.disp.*() module function map
|
||||
const LUA_REG_TYPE lcd_map[] =
|
||||
{
|
||||
{ LSTRKEY( "reset" ), LFUNCVAL( lcd_reset ) },
|
||||
{ LSTRKEY( "setup" ), LFUNCVAL( lcd_setup ) },
|
||||
{ LSTRKEY( "clear" ), LFUNCVAL( lcd_clear ) },
|
||||
{ LSTRKEY( "home" ), LFUNCVAL( lcd_home ) },
|
||||
{ LSTRKEY( "goto" ), LFUNCVAL( lcd_goto ) },
|
||||
{ LSTRKEY( "print" ), LFUNCVAL( lcd_print ) },
|
||||
{ LSTRKEY( "definechar" ), LFUNCVAL( lcd_definechar ) },
|
||||
{ LSTRKEY( "cursor" ), LFUNCVAL( lcd_cursor ) },
|
||||
{ LSTRKEY( "display" ), LFUNCVAL( lcd_display ) },
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
102
src/platform/avr32/lcd.h
Normal file
102
src/platform/avr32/lcd.h
Normal file
@ -0,0 +1,102 @@
|
||||
// Mizar32 LCD character display
|
||||
|
||||
#ifndef __LCD_H__
|
||||
#define __LCD_H__
|
||||
|
||||
// See the Ampire datasheet http://home.comet.bg/datasheets/LCD/AC-162B.pdf
|
||||
// and http://embeddedtutorial.com/2010/01/interfacing-lcd-with-8051/
|
||||
|
||||
// I2C bus frequency that the LCD display runs at.
|
||||
// It works up to 54kHz, with another window at 67 to 68kHz.
|
||||
// For reliable operation, we set it to 10% less than the highest "normal" speed.
|
||||
#define LCD_BUS_FREQ 50000
|
||||
|
||||
// I2C slave addresses for command bytes and data strings
|
||||
// Command address is followed by a dingle byte giving the command to perform
|
||||
// Data address is followed by multiple bytes of ASCII data to display
|
||||
// on the character display at the current cursor location.
|
||||
#define LCD_CMD 0x7C
|
||||
#define LCD_DATA 0x7E
|
||||
|
||||
// Command bytes
|
||||
|
||||
// "Clear display: Write "20H" to DDRAM and set DDRAM address to "00H" from AC"
|
||||
#define LCD_CMD_CLEAR 1
|
||||
|
||||
// "Return Home: Sets DDRAM address to "00H" from AC and return cursor to its
|
||||
// original position if shifted."
|
||||
#define LCD_CMD_HOME 2 // Bit 0: don't care
|
||||
|
||||
// "Assign cursor moving direction and enable the shift of entire display"
|
||||
#define LCD_CMD_ENTRYMODE 4
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT 1 // 0: move cursor / 1: shift display
|
||||
#define LCD_CMD_ENTRYMODE_DIRECTION 2 // 0: move/shift left / 1: right
|
||||
// or, if you prefer...
|
||||
#define LCD_CMD_ENTRYMODE_MOVE_LEFT 4 // move cursor left when printing
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT_LEFT 5 // shift display left when printing
|
||||
#define LCD_CMD_ENTRYMODE_MOVE_RIGHT 6 // move cursor right when printing
|
||||
#define LCD_CMD_ENTRYMODE_SHIFT_RIGHT 7 // shift display right when printing
|
||||
|
||||
// Command 8 uses bits 4,2,1 to set display on/off, underline cursor on/off
|
||||
// and blinking block on/off.
|
||||
#define LCD_CMD_DISPLAY_OFF 8
|
||||
#define LCD_CMD_CURSOR_NONE 12
|
||||
#define LCD_CMD_CURSOR_BLOCK 13
|
||||
#define LCD_CMD_CURSOR_LINE 14
|
||||
#define LCD_CMD_CURSOR_BOTH 15
|
||||
|
||||
// "Set cursor moving and display shift control bit, and the direction,
|
||||
// without changing of DDRAM data".
|
||||
//
|
||||
// Actually, this sets no bits at all. It just moves the cursor one place
|
||||
// left or right or shift the display contents one place left or right.
|
||||
//
|
||||
// Command 16 uses bits 8 and 4 to move the cursor one place left or right in
|
||||
// the character memory and on the display,
|
||||
// or to shift the displayed characters one place left or right.
|
||||
// Bit 8 is 0 to move the cursor, 1 to shift the display
|
||||
// Bit 4 is 0 to move the cursor or to shift the displayed characters left,
|
||||
// 1 to move the cursor or to shift the displayed characters right
|
||||
// When shifting the display left, the cursor also moves one place left in the
|
||||
// physical display, so remains over the same character as before.
|
||||
#define LCD_CMD_SHIFT 16
|
||||
#define LCD_CMD_SHIFT_LEFT 0
|
||||
#define LCD_CMD_SHIFT_RIGHT 4
|
||||
#define LCD_CMD_SHIFT_CURSOR 0
|
||||
#define LCD_CMD_SHIFT_DISPLAY 8
|
||||
// or, if you prefer...
|
||||
#define LCD_CMD_SHIFT_CURSOR_LEFT 16
|
||||
#define LCD_CMD_SHIFT_CURSOR_RIGHT 20
|
||||
#define LCD_CMD_SHIFT_DISPLAY_LEFT 24
|
||||
#define LCD_CMD_SHIFT_DISPLAY_RIGHT 28
|
||||
|
||||
// Command 32 uses bits 16, 8 and 4 to set
|
||||
// - interface data length (0 = 4-bit, 16 = 8-bit). Mizar32 uses 4-bit
|
||||
// - number of displayed lines (0 = one, 8 = two)
|
||||
// - display font type (0 = 5x8, 4 = 5x11).
|
||||
#define LCD_CMD_FUNCTION 32
|
||||
#define LCD_CMD_FUNCTION_DATABITS_4 0
|
||||
#define LCD_CMD_FUNCTION_DATABITS_8 16
|
||||
#define LCD_CMD_FUNCTION_LINES_1 0
|
||||
#define LCD_CMD_FUNCTION_LINES_2 8
|
||||
#define LCD_CMD_FUNCTION_FONT_5x8 0
|
||||
#define LCD_CMD_FUNCTION_FONT_5x11 4
|
||||
|
||||
// "Sets CG RAM address in address counter"
|
||||
// Sets an address in the user-defined character generator RAM.
|
||||
// The bottom 6 bits define which character to define as code(0-7) * 8.
|
||||
// Data is then sent to write values 0-31 into the CG RAM, which define a
|
||||
// character with one byte per row from top to bottom, and bits
|
||||
// 16, 8, 4, 2, 1 defining the row's pixels left to right.
|
||||
#define LCD_CMD_CGADDR 64
|
||||
|
||||
// "Sets DD RAM address in address counter"
|
||||
// Bits 0-7 are the address:
|
||||
// 00-0F are the first line
|
||||
// 40-4F are the second line
|
||||
// The location automatically wraps from the end of the first row to the
|
||||
// start of the second, the end of the second to the start of the first and,
|
||||
// when printing from right to left, vice versa.
|
||||
#define LCD_CMD_DDADDR 128
|
||||
|
||||
#endif
|
@ -15,7 +15,6 @@
|
||||
#include "platform_conf.h"
|
||||
#include "common.h"
|
||||
#include "buf.h"
|
||||
#include "spi.h"
|
||||
#ifdef BUILD_MMCFS
|
||||
#include "diskio.h"
|
||||
#endif
|
||||
@ -40,21 +39,76 @@
|
||||
#include "spi.h"
|
||||
#include "adc.h"
|
||||
#include "pwm.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
|
||||
// UIP sys tick data
|
||||
// NOTE: when using virtual timers, SYSTICKHZ and VTMR_FREQ_HZ should have the
|
||||
// same value, as they're served by the same timer (the systick)
|
||||
#define SYSTICKHZ 4
|
||||
#define SYSTICKMS (1000 / SYSTICKHZ)
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
static int eth_timer_fired;
|
||||
#if !defined( VTMR_NUM_TIMERS ) || VTMR_NUM_TIMERS == 0
|
||||
# error "On AVR32, UIP needs virtual timer support. Define VTMR_NUM_TIMERS > 0."
|
||||
#endif
|
||||
|
||||
#define SYSTICKHZ VTMR_FREQ_HZ
|
||||
#define SYSTICKMS (1000 / SYSTICKHZ)
|
||||
|
||||
static int eth_timer_fired;
|
||||
|
||||
#endif // BUILD_UIP
|
||||
|
||||
// ****************************************************************************
|
||||
// AVR32 system timer implementation
|
||||
|
||||
// Since the timer hardware (TC) on the AVR32 is pretty basic (16-bit timers,
|
||||
// limited prescaling options) we'll be using the PWM subsystem for the system
|
||||
// timer. The PWM hardware has much better prescaling options and it uses 20-bit
|
||||
// timers which are perfect for our needs. As a bonus, each PWM channel can be
|
||||
// clocked from two independent linear prescalers (CLKA and CLKB). The AVR32
|
||||
// PWM driver (pwm.c) uses only CLKA and disables CLKB, so by using CLKB we
|
||||
// won't change the regular PWM behaviour. The only downside is that we'll steal
|
||||
// a PWM channel for the system timer.
|
||||
|
||||
#define SYSTIMER_PWM_CH 6
|
||||
|
||||
__attribute__((__interrupt__)) static void systimer_int_handler()
|
||||
{
|
||||
volatile u32 dummy = AVR32_PWM.isr; // clear interrupt
|
||||
|
||||
( void )dummy;
|
||||
cmn_systimer_periodic();
|
||||
}
|
||||
|
||||
static void platform_systimer_init()
|
||||
{
|
||||
avr32_pwm_mr_t mr = AVR32_PWM.MR;
|
||||
|
||||
// Set CLKB prescaler for 1MHz clock (which is exactly our system clock frequency)
|
||||
mr.preb = 0; // main source clock is MCK (PBA)
|
||||
mr.divb = REQ_PBA_FREQ / 1000000; // set CLKB to 1MHz
|
||||
AVR32_PWM.MR = mr;
|
||||
|
||||
// Now setup our PWM channel
|
||||
// Clock from CLKB, left aligned (the other parameters are not important)
|
||||
AVR32_PWM.channel[ SYSTIMER_PWM_CH ].cmr = AVR32_PWM_CMR_CPRE_CLKB;
|
||||
// The period register is 20-bit wide (1048576). We set it so we get interrupts
|
||||
// every second (which results in a very reasonable system load)
|
||||
AVR32_PWM.channel[ SYSTIMER_PWM_CH ].cprd = 1000000;
|
||||
// The duty cycle is arbitrary set to 50%
|
||||
AVR32_PWM.channel[ SYSTIMER_PWM_CH ].cdty = 500000;
|
||||
|
||||
// Setup PWM interrupt
|
||||
INTC_register_interrupt( &systimer_int_handler, AVR32_PWM_IRQ, AVR32_INTC_INT0 );
|
||||
AVR32_PWM.ier = 1 << SYSTIMER_PWM_CH;
|
||||
|
||||
// Enable the channel
|
||||
AVR32_PWM.ena = 1 << SYSTIMER_PWM_CH;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Platform initialization
|
||||
#ifdef BUILD_UIP
|
||||
u32 platform_ethernet_setup(void);
|
||||
u32 platform_ethernet_setup( void );
|
||||
#endif
|
||||
|
||||
extern int pm_configure_clocks( pm_freq_param_t *param );
|
||||
@ -65,32 +119,6 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock );
|
||||
__attribute__((__interrupt__)) static void adc_int_handler();
|
||||
#endif
|
||||
|
||||
// Virtual timers support
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
#define VTMR_CH (2)
|
||||
|
||||
__attribute__((__interrupt__)) static void tmr_int_handler()
|
||||
{
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
|
||||
tc_read_sr( tc, VTMR_CH );
|
||||
cmn_virtual_timer_cb();
|
||||
|
||||
#ifdef BUILD_MMCFS
|
||||
disk_timerproc();
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
// Indicate that a SysTick interrupt has occurred.
|
||||
eth_timer_fired = 1;
|
||||
|
||||
// Generate a fake Ethernet interrupt. This will perform the actual work
|
||||
// of incrementing the timers and taking the appropriate actions.
|
||||
platform_eth_force_interrupt();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
const u32 uart_base_addr[ ] = {
|
||||
AVR32_USART0_ADDRESS,
|
||||
AVR32_USART1_ADDRESS,
|
||||
@ -145,10 +173,12 @@ int platform_init()
|
||||
// Setup clocks
|
||||
if( PM_FREQ_STATUS_FAIL == pm_configure_clocks( &pm_freq_param ) )
|
||||
return PLATFORM_ERR;
|
||||
#ifdef FOSC32
|
||||
// Select the 32-kHz oscillator crystal
|
||||
pm_enable_osc32_crystal (&AVR32_PM );
|
||||
// Enable the 32-kHz clock
|
||||
pm_enable_clk32_no_wait( &AVR32_PM, AVR32_PM_OSCCTRL32_STARTUP_0_RCOSC );
|
||||
#endif
|
||||
|
||||
// Initialize external memory if any.
|
||||
#ifdef AVR32_SDRAMC
|
||||
@ -168,47 +198,16 @@ int platform_init()
|
||||
#endif
|
||||
}
|
||||
|
||||
// Setup timer interrupt for the virtual timers if needed
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
INTC_register_interrupt( &tmr_int_handler, AVR32_TC_IRQ2, AVR32_INTC_INT0 );
|
||||
tmropt.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER;
|
||||
tc_init_waveform( tc, VTMR_CH, &tmropt );
|
||||
tc_interrupt_t tmrint =
|
||||
{
|
||||
0, // External trigger interrupt.
|
||||
0, // RB load interrupt.
|
||||
0, // RA load interrupt.
|
||||
1, // RC compare interrupt.
|
||||
0, // RB compare interrupt.
|
||||
0, // RA compare interrupt.
|
||||
0, // Load overrun interrupt.
|
||||
0 // Counter overflow interrupt.
|
||||
};
|
||||
# ifdef FOSC32
|
||||
tc_write_rc( tc, VTMR_CH, FOSC32 / VTMR_FREQ_HZ );
|
||||
# else
|
||||
// Run VTMR from the slowest available PBA clock divisor
|
||||
{ u32 vt_clock_freq = platform_timer_set_clock( VTMR_CH, REQ_PBA_FREQ / 128 );
|
||||
u32 div = vt_clock_freq / VTMR_FREQ_HZ;
|
||||
if (div > 0xffff) div = 0xffff;
|
||||
tc_write_rc( tc, VTMR_CH, div );
|
||||
}
|
||||
# endif
|
||||
tc_configure_interrupts( tc, VTMR_CH, &tmrint );
|
||||
Enable_global_interrupt();
|
||||
tc_start( tc, VTMR_CH );
|
||||
#endif
|
||||
|
||||
// Setup spi controller(s) : up to 4 slave by controller.
|
||||
#if NUM_SPI > 0
|
||||
spi_master_options_t spiopt;
|
||||
spiopt.modfdis = TRUE;
|
||||
spiopt.pcs_decode = FALSE;
|
||||
spiopt.delay = 0;
|
||||
spi_initMaster(&AVR32_SPI0, &spiopt, REQ_CPU_FREQ);
|
||||
spi_initMaster(&AVR32_SPI0, &spiopt, REQ_PBA_FREQ);
|
||||
|
||||
#if NUM_SPI > 4
|
||||
spi_initMaster(&AVR32_SPI1, &spiopt, REQ_CPU_FREQ);
|
||||
spi_initMaster(&AVR32_SPI1, &spiopt, REQ_PBA_FREQ);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -225,7 +224,6 @@ int platform_init()
|
||||
pwm_init();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
platform_ethernet_setup();
|
||||
#endif
|
||||
@ -240,6 +238,19 @@ int platform_init()
|
||||
platform_pio_op( 0, ( pio_type )1 << 0 , PLATFORM_IO_PIN_PULLUP );
|
||||
#endif
|
||||
|
||||
// Setup system timer
|
||||
// NOTE: this MUST come AFTER pwm_init!
|
||||
cmn_systimer_set_base_freq( 1000000 );
|
||||
cmn_systimer_set_interrupt_freq( 1 );
|
||||
platform_systimer_init();
|
||||
|
||||
// Setup virtual timers if needed
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
#define VTMR_CH 2
|
||||
platform_cpu_set_interrupt( INT_TMR_MATCH, VTMR_CH, PLATFORM_CPU_ENABLE );
|
||||
platform_timer_set_match_int( VTMR_CH, 1000000 / VTMR_FREQ_HZ, PLATFORM_TIMER_INT_CYCLIC );
|
||||
#endif // #if VTMR_NUM_TIMERS > 0
|
||||
|
||||
cmn_platform_init();
|
||||
|
||||
// All done
|
||||
@ -249,104 +260,59 @@ int platform_init()
|
||||
// ****************************************************************************
|
||||
// PIO functions
|
||||
|
||||
// Reg types for our helper function
|
||||
#define PIO_REG_PVR 0
|
||||
#define PIO_REG_OVR 1
|
||||
#define PIO_REG_GPER 2
|
||||
#define PIO_REG_ODER 3
|
||||
#define PIO_REG_PUER 4
|
||||
|
||||
#define GPIO AVR32_GPIO
|
||||
|
||||
// Helper function: for a given port, return the address of a specific register (value, direction, pullup ...)
|
||||
static volatile unsigned long* platform_pio_get_port_reg_addr( unsigned port, int regtype )
|
||||
{
|
||||
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[ port ];
|
||||
|
||||
switch( regtype )
|
||||
{
|
||||
case PIO_REG_PVR:
|
||||
return ( unsigned long * )&gpio_port->pvr;
|
||||
case PIO_REG_OVR:
|
||||
return &gpio_port->ovr;
|
||||
case PIO_REG_GPER:
|
||||
return &gpio_port->gper;
|
||||
case PIO_REG_ODER:
|
||||
return &gpio_port->oder;
|
||||
case PIO_REG_PUER:
|
||||
return &gpio_port->puer;
|
||||
}
|
||||
// Should never get here
|
||||
return ( unsigned long* )&gpio_port->pvr;
|
||||
}
|
||||
|
||||
// Helper function: get port value, get direction, get pullup, ...
|
||||
static pio_type platform_pio_get_port_reg( unsigned port, int reg )
|
||||
{
|
||||
volatile unsigned long *pv = platform_pio_get_port_reg_addr( port, reg );
|
||||
|
||||
return *pv;
|
||||
}
|
||||
|
||||
// Helper function: set port value, set direction, set pullup ...
|
||||
static void platform_pio_set_port_reg( unsigned port, pio_type val, int reg )
|
||||
{
|
||||
volatile unsigned long *pv = platform_pio_get_port_reg_addr( port, reg );
|
||||
|
||||
*pv = val;
|
||||
}
|
||||
|
||||
pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
|
||||
{
|
||||
pio_type retval = 1;
|
||||
|
||||
// Pointer to the register set for this GPIO port
|
||||
volatile avr32_gpio_port_t *gpio_regs = &AVR32_GPIO.port[ port ];
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_IO_PORT_SET_VALUE:
|
||||
platform_pio_set_port_reg( port, pinmask, PIO_REG_OVR );
|
||||
gpio_regs->ovr = pinmask;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_SET:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_OVR ) | pinmask, PIO_REG_OVR );
|
||||
gpio_regs->ovrs = pinmask;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_CLEAR:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_OVR ) & ~pinmask, PIO_REG_OVR );
|
||||
gpio_regs->ovrc = pinmask;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PORT_DIR_INPUT:
|
||||
pinmask = 0xFFFFFFFF;
|
||||
case PLATFORM_IO_PIN_DIR_INPUT:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_ODER ) & ~pinmask, PIO_REG_ODER );
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_GPER ) | pinmask, PIO_REG_GPER );
|
||||
gpio_regs->oderc = pinmask; // Disable output drivers
|
||||
gpio_regs->gpers = pinmask; // Make GPIO control this pin
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PORT_DIR_OUTPUT:
|
||||
pinmask = 0xFFFFFFFF;
|
||||
case PLATFORM_IO_PIN_DIR_OUTPUT:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_ODER ) | pinmask, PIO_REG_ODER );
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_GPER ) | pinmask, PIO_REG_GPER );
|
||||
gpio_regs->oders = pinmask; // Enable output drivers
|
||||
gpio_regs->gpers = pinmask; // Make GPIO control this pin
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PORT_GET_VALUE:
|
||||
retval = platform_pio_get_port_reg( port, PIO_REG_PVR );
|
||||
retval = gpio_regs->pvr;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_GET:
|
||||
retval = platform_pio_get_port_reg( port, PIO_REG_PVR ) & pinmask ? 1 : 0;
|
||||
retval = gpio_regs->pvr & pinmask ? 1 : 0;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_PULLUP:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_PUER ) | pinmask, PIO_REG_PUER );
|
||||
gpio_regs->puers = pinmask;
|
||||
break;
|
||||
|
||||
case PLATFORM_IO_PIN_NOPULL:
|
||||
platform_pio_set_port_reg( port, platform_pio_get_port_reg( port, PIO_REG_PUER ) & ~pinmask, PIO_REG_PUER );
|
||||
gpio_regs->puerc = pinmask;
|
||||
break;
|
||||
|
||||
default:
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
@ -436,7 +402,7 @@ void platform_s_uart_send( unsigned id, u8 data )
|
||||
pusart->thr = ( data << AVR32_USART_THR_TXCHR_OFFSET ) & AVR32_USART_THR_TXCHR_MASK;
|
||||
}
|
||||
|
||||
int platform_s_uart_recv( unsigned id, s32 timeout )
|
||||
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
|
||||
{
|
||||
volatile avr32_usart_t *pusart = ( volatile avr32_usart_t* )uart_base_addr[ id ];
|
||||
int temp;
|
||||
@ -517,7 +483,7 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
|
||||
gpio_enable_module_pin( ppindata->pin, ppindata->function );
|
||||
else // release pin to GPIO module
|
||||
{
|
||||
gpio_port = &GPIO.port[ ppindata->pin >> 5 ];
|
||||
gpio_port = &AVR32_GPIO.port[ ppindata->pin >> 5 ];
|
||||
gpio_port->gpers = 1 << ( ppindata->pin & 0x1F );
|
||||
}
|
||||
return PLATFORM_OK;
|
||||
@ -527,6 +493,7 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
|
||||
// Timer functions
|
||||
|
||||
static const u16 clkdivs[] = { 0xFFFF, 2, 8, 32, 128 };
|
||||
u8 avr32_timer_int_periodic_flag[ 3 ];
|
||||
|
||||
// Helper: get timer clock
|
||||
static u32 platform_timer_get_clock( unsigned id )
|
||||
@ -566,7 +533,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
|
||||
#endif
|
||||
}
|
||||
|
||||
void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
|
||||
{
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
u32 freq;
|
||||
@ -584,7 +551,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
|
||||
while( ( tc_read_tc( tc, id ) < final ) && !sr->covfs );
|
||||
}
|
||||
|
||||
u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
|
||||
{
|
||||
u32 res = 0;
|
||||
volatile int i;
|
||||
@ -602,14 +569,6 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
res = tc_read_tc( tc, id );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 0xFFFF );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
|
||||
res = platform_timer_get_diff_us( id, 0, 1 );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_SET_CLOCK:
|
||||
res = platform_timer_set_clock( id, data );
|
||||
break;
|
||||
@ -617,13 +576,55 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
|
||||
case PLATFORM_TIMER_OP_GET_CLOCK:
|
||||
res = platform_timer_get_clock( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_TIMER_OP_GET_MAX_CNT:
|
||||
res = 0xFFFF;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type )
|
||||
int platform_s_timer_set_match_int( unsigned id, timer_data_type period_us, int type )
|
||||
{
|
||||
return PLATFORM_TIMER_INT_INVALID_ID;
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
u32 final;
|
||||
|
||||
if( period_us == 0 )
|
||||
{
|
||||
tc->channel[ id ].CMR.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE;
|
||||
return PLATFORM_TIMER_INT_OK;
|
||||
}
|
||||
final = ( u32 )( ( u64 )( platform_timer_get_clock( id ) * period_us ) / 1000000 );
|
||||
if( final == 0 )
|
||||
return PLATFORM_TIMER_INT_TOO_SHORT;
|
||||
if( final > 0xFFFF )
|
||||
return PLATFORM_TIMER_INT_TOO_LONG;
|
||||
tc_stop( tc, id );
|
||||
tc->channel[ id ].CMR.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER;
|
||||
tc->channel[ id ].rc = final;
|
||||
avr32_timer_int_periodic_flag[ id ] = type;
|
||||
tc_start( tc, id );
|
||||
return PLATFORM_TIMER_INT_OK;
|
||||
}
|
||||
|
||||
u64 platform_timer_sys_raw_read()
|
||||
{
|
||||
return AVR32_PWM.channel[ SYSTIMER_PWM_CH ].ccnt;
|
||||
}
|
||||
|
||||
void platform_timer_sys_disable_int()
|
||||
{
|
||||
AVR32_PWM.idr = 1 << SYSTIMER_PWM_CH;
|
||||
}
|
||||
|
||||
void platform_timer_sys_enable_int()
|
||||
{
|
||||
AVR32_PWM.ier = 1 << SYSTIMER_PWM_CH;
|
||||
}
|
||||
|
||||
timer_data_type platform_timer_read_sys()
|
||||
{
|
||||
return cmn_systimer_get();
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
@ -670,14 +671,12 @@ u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigne
|
||||
opt.bits = min(databits, 16);
|
||||
opt.spck_delay = 0;
|
||||
opt.trans_delay = 0;
|
||||
opt.mode = ((cpol & 1) << 1) | (cpha & 1);
|
||||
opt.mode = (cpol << 1) | cpha;
|
||||
|
||||
// Set actual interface
|
||||
gpio_enable_module(spi_pins + (id >> 2) * 4, 4);
|
||||
spi_setupChipReg((volatile avr32_spi_t *) spireg[id >> 2], id % 4, &opt, REQ_CPU_FREQ);
|
||||
|
||||
// TODO: return the actual baudrate.
|
||||
return clock;
|
||||
return spi_setupChipReg((volatile avr32_spi_t *) spireg[id >> 2], id % 4,
|
||||
&opt, REQ_PBA_FREQ);
|
||||
}
|
||||
|
||||
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
|
||||
@ -753,6 +752,8 @@ void platform_adc_stop( unsigned id )
|
||||
s->op_pending = 0;
|
||||
INACTIVATE_CHANNEL( d, id );
|
||||
|
||||
adc_disable( adc, s->id );
|
||||
|
||||
// If there are no more active channels, stop the sequencer
|
||||
if( d->ch_active == 0 )
|
||||
d->running = 0;
|
||||
@ -781,7 +782,6 @@ int platform_adc_update_sequence( )
|
||||
|
||||
__attribute__((__interrupt__)) static void adc_int_handler()
|
||||
{
|
||||
int i;
|
||||
elua_adc_dev_state *d = adc_get_dev_state( 0 );
|
||||
elua_adc_ch_state *s;
|
||||
|
||||
@ -795,9 +795,6 @@ __attribute__((__interrupt__)) static void adc_int_handler()
|
||||
d->sample_buf[ d->seq_ctr ] = ( u16 )adc_get_value(adc, s->id );
|
||||
s->value_fresh = 1;
|
||||
|
||||
// Read LCDR to signal that conversion has been captured
|
||||
i = adc->lcdr;
|
||||
|
||||
if ( s->logsmoothlen > 0 && s->smooth_ready == 0)
|
||||
adc_smooth_data( s->id );
|
||||
#if defined( BUF_ENABLE_ADC )
|
||||
@ -817,18 +814,14 @@ __attribute__((__interrupt__)) static void adc_int_handler()
|
||||
}
|
||||
d->seq_ctr = 0;
|
||||
|
||||
// Only attempt to refresh sequence order if still running
|
||||
// This allows us to "cache" an old sequence if all channels
|
||||
// finish at the same time
|
||||
if ( d->running == 1 )
|
||||
adc_update_dev_sequence( 0 );
|
||||
adc_update_dev_sequence( 0 );
|
||||
|
||||
if ( d->clocked == 0 && d->running == 1 )
|
||||
adc_start( adc );
|
||||
}
|
||||
|
||||
|
||||
u32 platform_adc_setclock( unsigned id, u32 frequency )
|
||||
u32 platform_adc_set_clock( unsigned id, u32 frequency )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -864,15 +857,32 @@ int platform_adc_start_sequence( )
|
||||
# error "NUM_PWM > AVR32_PWM_CHANNEL_LENGTH"
|
||||
#endif
|
||||
|
||||
#if NUM_PWM > 0
|
||||
|
||||
// One PWM channel is used by the AVR32 system timer (look at the start of this
|
||||
// file for more information). Currently this channel is hardcoded in platform.c
|
||||
// (SYSTIMER_PWM_CH) to 6. If this is not convenient feel free to move the
|
||||
// definition of SYSTIMER_PWM_CH in platform_conf.h and select another PWM channel,
|
||||
// BUT remember to modify the below PWM pin mapping accordingly!
|
||||
static const gpio_map_t pwm_pins =
|
||||
{
|
||||
{ AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION },
|
||||
{ AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION },
|
||||
{ AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION },
|
||||
{ AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION },
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB28
|
||||
{ AVR32_PWM_6_PIN, AVR32_PWM_6_FUNCTION },
|
||||
#if ( BOARD == ATEVK1100 ) || ( BOARD == MIZAR32 )
|
||||
{ AVR32_PWM_0_PIN, AVR32_PWM_0_FUNCTION }, // PB19 - LED4
|
||||
{ AVR32_PWM_1_PIN, AVR32_PWM_1_FUNCTION }, // PB20 - LED5
|
||||
{ AVR32_PWM_2_PIN, AVR32_PWM_2_FUNCTION }, // PB21 - LED6
|
||||
{ AVR32_PWM_3_PIN, AVR32_PWM_3_FUNCTION }, // PB22 - LED7
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PB27 - LED0
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB28 - LED1
|
||||
// { AVR32_PWM_6_PIN, AVR32_PWM_6_FUNCTION }, // PB18 - LCD_C / GPIO50
|
||||
#elif BOARD == ATEVK1101
|
||||
{ AVR32_PWM_0_0_PIN, AVR32_PWM_0_0_FUNCTION }, // PA7 LED0
|
||||
{ AVR32_PWM_1_0_PIN, AVR32_PWM_1_0_FUNCTION }, // PA8 LED1
|
||||
{ AVR32_PWM_2_0_PIN, AVR32_PWM_2_0_FUNCTION }, // PA21 LED2
|
||||
{ AVR32_PWM_3_0_PIN, AVR32_PWM_3_0_FUNCTION }, // PA14 ? or _1 PA25
|
||||
{ AVR32_PWM_4_1_PIN, AVR32_PWM_4_1_FUNCTION }, // PA28 - audio out
|
||||
{ AVR32_PWM_5_1_PIN, AVR32_PWM_5_1_FUNCTION }, // PB5: UART1-RTS & Nexus i/f EVTIn / _0 PA18=Xin0
|
||||
// { AVR32_PWM_6_0_PIN, AVR32_PWM_6_0_FUNCTION }, // PA22 - LED3 and audio out
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@ -899,27 +909,22 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
//
|
||||
// PWM output wave frequency is requested in Hz but programmed as a
|
||||
// number of cycles of the master PWM clock frequency.
|
||||
// The obvious but simple formulae to convert between these values:
|
||||
// channel_period = pwmclk / frequency; return pwmclk / channel_period;
|
||||
// return the same values as requested from 1 to just over sqrt(pwmclk)
|
||||
// (up to 1031 for 1000000 Hz).
|
||||
// In reality, they always set a frequency <= the one requested.
|
||||
// A better formula would program the geometrically closest available
|
||||
// actual frequency and return the geometrically closest integer frequency
|
||||
// to that.
|
||||
// Unfortunately we mustn't use floating point because that would pull
|
||||
// the whole FP subsystem into the integer-only executable.
|
||||
//
|
||||
// Here, we use rounding to select the numerically closest available
|
||||
// frequency and return the closest integer in Hz to that.
|
||||
|
||||
period = pwmclk / frequency;
|
||||
duty_cycle = (period * duty) / 100;
|
||||
period = (pwmclk + frequency/2) / frequency;
|
||||
if (period == 0) period = 1;
|
||||
if (period >= 1<<20) period = (1<<20) - 1;
|
||||
duty_cycle = (period * duty + 50) / 100;
|
||||
|
||||
// The AVR32 PWM duty cycle is upside down:
|
||||
// duty_period==0 gives an all-active output, while
|
||||
// duty_period==period gives an all-inactive output.
|
||||
// So we invert the cuty cycle here.
|
||||
pwm_channel_set_period_and_duty_cycle( id, period, period - duty_cycle );
|
||||
|
||||
return pwmclk / period; // Inaccurate. We Should return the nearest int.
|
||||
// TODO: Try (pwmclk + period/2) / period
|
||||
return (pwmclk + period/2) / period;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -930,18 +935,18 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
|
||||
* If the configuration cannot be met (because freq is too high), set the
|
||||
* maximum frequency possible.
|
||||
*
|
||||
* The algorithm is too simple: the actual frequency is always <= the one
|
||||
* requested, not the closest possible.
|
||||
* The algorithm is too simple: the actual clock frequency is always >=
|
||||
* the one requested, not the closest possible.
|
||||
*/
|
||||
static void find_clock_configuration( u32 frequency,
|
||||
unsigned *pre, unsigned *div )
|
||||
static void pwm_find_clock_configuration( u32 frequency,
|
||||
unsigned *pre, unsigned *div )
|
||||
{
|
||||
// prescalers[11] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
|
||||
#define prescalers( n ) ( 1 << n )
|
||||
const unsigned nprescalers = 11;
|
||||
|
||||
unsigned prescaler; // Select a prescaler
|
||||
unsigned divisor = 0;
|
||||
unsigned prescaler; // Which of the prescalers are we considering?
|
||||
unsigned divisor;
|
||||
|
||||
if ( frequency > REQ_PBA_FREQ )
|
||||
{
|
||||
@ -951,6 +956,7 @@ static void find_clock_configuration( u32 frequency,
|
||||
}
|
||||
|
||||
// Find prescaler and divisor values
|
||||
prescaler = 0;
|
||||
do
|
||||
divisor = REQ_PBA_FREQ / ( prescalers( prescaler ) * frequency );
|
||||
while ( ( divisor > 255 ) && ( ++prescaler < nprescalers ) );
|
||||
@ -970,122 +976,212 @@ static void find_clock_configuration( u32 frequency,
|
||||
}
|
||||
#undef prescalers
|
||||
|
||||
|
||||
static u32 pwm_set_clock_freq( u32 freq )
|
||||
u32 platform_pwm_set_clock( unsigned id, u32 freq )
|
||||
{
|
||||
unsigned pre, div;
|
||||
|
||||
find_clock_configuration( freq, &pre, &div );
|
||||
pwm_find_clock_configuration( freq, &pre, &div );
|
||||
pwm_set_linear_divider( pre, div );
|
||||
|
||||
return pwm_get_clock_freq();
|
||||
}
|
||||
|
||||
u32 platform_pwm_op( unsigned id, int op, u32 data)
|
||||
u32 platform_pwm_get_clock( unsigned id )
|
||||
{
|
||||
// Sanity check
|
||||
if (id < 0 || id >= NUM_PWM)
|
||||
return 0;
|
||||
|
||||
switch( op )
|
||||
{
|
||||
case PLATFORM_PWM_OP_SET_CLOCK:
|
||||
return pwm_set_clock_freq( data );
|
||||
|
||||
case PLATFORM_PWM_OP_GET_CLOCK:
|
||||
return pwm_get_clock_freq();
|
||||
|
||||
case PLATFORM_PWM_OP_START:
|
||||
pwm_channel_start( id );
|
||||
break;
|
||||
|
||||
case PLATFORM_PWM_OP_STOP:
|
||||
pwm_channel_stop( id );
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
return pwm_get_clock_freq();
|
||||
}
|
||||
|
||||
void platform_pwm_start( unsigned id )
|
||||
{
|
||||
pwm_channel_start( id );
|
||||
}
|
||||
|
||||
void platform_pwm_stop( unsigned id )
|
||||
{
|
||||
pwm_channel_stop( id );
|
||||
}
|
||||
|
||||
#endif // #if NUM_PWM > 0
|
||||
|
||||
// ****************************************************************************
|
||||
// I2C support
|
||||
|
||||
u32 platform_i2c_setup( unsigned id, u32 speed )
|
||||
{
|
||||
return i2c_setup(speed);
|
||||
}
|
||||
|
||||
void platform_i2c_send_start( unsigned id )
|
||||
{
|
||||
i2c_start_cond();
|
||||
}
|
||||
|
||||
void platform_i2c_send_stop( unsigned id )
|
||||
{
|
||||
i2c_stop_cond();
|
||||
}
|
||||
|
||||
int platform_i2c_send_address( unsigned id, u16 address, int direction )
|
||||
{
|
||||
// Convert enum codes to R/w bit value.
|
||||
// If TX == 0 and RX == 1, this test will be removed by the compiler
|
||||
if ( ! ( PLATFORM_I2C_DIRECTION_TRANSMITTER == 0 &&
|
||||
PLATFORM_I2C_DIRECTION_RECEIVER == 1 ) ) {
|
||||
direction = ( direction == PLATFORM_I2C_DIRECTION_TRANSMITTER ) ? 0 : 1;
|
||||
}
|
||||
|
||||
// Low-level returns nack (0=acked); we return ack (1=acked).
|
||||
return ! i2c_write_byte( (address << 1) | direction );
|
||||
}
|
||||
|
||||
int platform_i2c_send_byte( unsigned id, u8 data )
|
||||
{
|
||||
// Low-level returns nack (0=acked); we return ack (1=acked).
|
||||
return ! i2c_write_byte( data );
|
||||
}
|
||||
|
||||
int platform_i2c_recv_byte( unsigned id, int ack )
|
||||
{
|
||||
return i2c_read_byte( !ack );
|
||||
}
|
||||
|
||||
|
||||
// ****************************************************************************
|
||||
// Network support
|
||||
|
||||
#ifdef BUILD_UIP
|
||||
static const gpio_map_t MACB_GPIO_MAP =
|
||||
{
|
||||
{AVR32_MACB_MDC_0_PIN, AVR32_MACB_MDC_0_FUNCTION },
|
||||
{AVR32_MACB_MDIO_0_PIN, AVR32_MACB_MDIO_0_FUNCTION },
|
||||
{AVR32_MACB_RXD_0_PIN, AVR32_MACB_RXD_0_FUNCTION },
|
||||
{AVR32_MACB_TXD_0_PIN, AVR32_MACB_TXD_0_FUNCTION },
|
||||
{AVR32_MACB_RXD_1_PIN, AVR32_MACB_RXD_1_FUNCTION },
|
||||
{AVR32_MACB_TXD_1_PIN, AVR32_MACB_TXD_1_FUNCTION },
|
||||
{AVR32_MACB_TX_EN_0_PIN, AVR32_MACB_TX_EN_0_FUNCTION },
|
||||
{AVR32_MACB_RX_ER_0_PIN, AVR32_MACB_RX_ER_0_FUNCTION },
|
||||
{AVR32_MACB_RX_DV_0_PIN, AVR32_MACB_RX_DV_0_FUNCTION },
|
||||
{AVR32_MACB_TX_CLK_0_PIN, AVR32_MACB_TX_CLK_0_FUNCTION}
|
||||
{ AVR32_MACB_MDC_0_PIN, AVR32_MACB_MDC_0_FUNCTION },
|
||||
{ AVR32_MACB_MDIO_0_PIN, AVR32_MACB_MDIO_0_FUNCTION },
|
||||
{ AVR32_MACB_RXD_0_PIN, AVR32_MACB_RXD_0_FUNCTION },
|
||||
{ AVR32_MACB_TXD_0_PIN, AVR32_MACB_TXD_0_FUNCTION },
|
||||
{ AVR32_MACB_RXD_1_PIN, AVR32_MACB_RXD_1_FUNCTION },
|
||||
{ AVR32_MACB_TXD_1_PIN, AVR32_MACB_TXD_1_FUNCTION },
|
||||
{ AVR32_MACB_TX_EN_0_PIN, AVR32_MACB_TX_EN_0_FUNCTION },
|
||||
{ AVR32_MACB_RX_ER_0_PIN, AVR32_MACB_RX_ER_0_FUNCTION },
|
||||
{ AVR32_MACB_RX_DV_0_PIN, AVR32_MACB_RX_DV_0_FUNCTION },
|
||||
{ AVR32_MACB_TX_CLK_0_PIN, AVR32_MACB_TX_CLK_0_FUNCTION },
|
||||
};
|
||||
|
||||
u32 platform_ethernet_setup()
|
||||
u32 platform_ethernet_setup()
|
||||
{
|
||||
static struct uip_eth_addr sTempAddr;
|
||||
// Assign GPIO to MACB
|
||||
gpio_enable_module(MACB_GPIO_MAP, sizeof(MACB_GPIO_MAP) / sizeof(MACB_GPIO_MAP[0]));
|
||||
static struct uip_eth_addr sTempAddr = {
|
||||
.addr[0] = ETHERNET_CONF_ETHADDR0,
|
||||
.addr[1] = ETHERNET_CONF_ETHADDR1,
|
||||
.addr[2] = ETHERNET_CONF_ETHADDR2,
|
||||
.addr[3] = ETHERNET_CONF_ETHADDR3,
|
||||
.addr[4] = ETHERNET_CONF_ETHADDR4,
|
||||
.addr[5] = ETHERNET_CONF_ETHADDR5,
|
||||
};
|
||||
|
||||
// initialize MACB & Phy Layers
|
||||
if (xMACBInit(&AVR32_MACB) == FALSE ) {
|
||||
return PLATFORM_ERR;
|
||||
}
|
||||
// Assign GPIO to MACB
|
||||
gpio_enable_module( MACB_GPIO_MAP, sizeof(MACB_GPIO_MAP ) / sizeof( MACB_GPIO_MAP[0] ) );
|
||||
|
||||
sTempAddr.addr[0] = ETHERNET_CONF_ETHADDR0;
|
||||
sTempAddr.addr[1] = ETHERNET_CONF_ETHADDR1;
|
||||
sTempAddr.addr[2] = ETHERNET_CONF_ETHADDR2;
|
||||
sTempAddr.addr[3] = ETHERNET_CONF_ETHADDR3;
|
||||
sTempAddr.addr[4] = ETHERNET_CONF_ETHADDR4;
|
||||
sTempAddr.addr[5] = ETHERNET_CONF_ETHADDR5;
|
||||
// initialize MACB & Phy Layers
|
||||
if ( xMACBInit( &AVR32_MACB ) == FALSE ) {
|
||||
return PLATFORM_ERR;
|
||||
}
|
||||
|
||||
// Initialize the eLua uIP layer
|
||||
elua_uip_init( &sTempAddr );
|
||||
return PLATFORM_OK;
|
||||
// Initialize the eLua uIP layer
|
||||
elua_uip_init( &sTempAddr );
|
||||
return PLATFORM_OK;
|
||||
}
|
||||
|
||||
void platform_eth_send_packet( const void* src, u32 size )
|
||||
{
|
||||
lMACBSend(&AVR32_MACB,src, size, TRUE);
|
||||
lMACBSend( &AVR32_MACB,src, size, TRUE );
|
||||
}
|
||||
|
||||
u32 platform_eth_get_packet_nb( void* buf, u32 maxlen )
|
||||
{
|
||||
u32 len;
|
||||
u32 len;
|
||||
|
||||
/* Obtain the size of the packet. */
|
||||
len = ulMACBInputLength();
|
||||
/* Obtain the size of the packet. */
|
||||
len = ulMACBInputLength();
|
||||
|
||||
if (len > maxlen) {
|
||||
return 0;
|
||||
}
|
||||
if( len > maxlen ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( len ) {
|
||||
/* Let the driver know we are going to read a new packet. */
|
||||
vMACBRead( NULL, 0, len );
|
||||
vMACBRead( buf, len, len );
|
||||
}
|
||||
if( len ) {
|
||||
/* Let the driver know we are going to read a new packet. */
|
||||
vMACBRead( NULL, 0, len );
|
||||
vMACBRead( buf, len, len );
|
||||
}
|
||||
|
||||
return len;
|
||||
return len;
|
||||
}
|
||||
|
||||
void platform_eth_force_interrupt()
|
||||
{
|
||||
elua_uip_mainloop();
|
||||
elua_uip_mainloop();
|
||||
}
|
||||
|
||||
u32 platform_eth_get_elapsed_time()
|
||||
{
|
||||
if( eth_timer_fired )
|
||||
{
|
||||
eth_timer_fired = 0;
|
||||
return SYSTICKMS;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
if( eth_timer_fired )
|
||||
{
|
||||
eth_timer_fired = 0;
|
||||
return SYSTICKMS;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void platform_eth_timer_handler()
|
||||
{
|
||||
// Indicate that a SysTick interrupt has occurred.
|
||||
eth_timer_fired = 1;
|
||||
|
||||
// Generate a fake Ethernet interrupt. This will perform the actual work
|
||||
// of incrementing the timers and taking the appropriate actions.
|
||||
platform_eth_force_interrupt();
|
||||
}
|
||||
|
||||
#else // #ifdef BUILD_UIP
|
||||
|
||||
void platform_eth_timer_handler()
|
||||
{
|
||||
}
|
||||
|
||||
#endif // #ifdef BUILD_UIP
|
||||
|
||||
// ****************************************************************************
|
||||
// Platform specific modules go here
|
||||
|
||||
#ifdef PS_LIB_TABLE_NAME
|
||||
|
||||
#define MIN_OPT_LEVEL 2
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lrotable.h"
|
||||
#include "lrodefs.h"
|
||||
|
||||
extern const LUA_REG_TYPE lcd_map[];
|
||||
|
||||
const LUA_REG_TYPE platform_map[] =
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
{ LSTRKEY( "lcd" ), LROVAL( lcd_map ) },
|
||||
#endif
|
||||
{ LNILKEY, LNILVAL }
|
||||
};
|
||||
|
||||
LUALIB_API int luaopen_platform( lua_State *L )
|
||||
{
|
||||
#if LUA_OPTIMIZE_MEMORY > 0
|
||||
return 0;
|
||||
#else // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
luaL_register( L, PS_LIB_TABLE_NAME, platform_map );
|
||||
|
||||
// Setup the new tables inside platform table
|
||||
lua_newtable( L );
|
||||
luaL_register( L, NULL, lcd_map );
|
||||
lua_setfield( L, -2, "lcd" );
|
||||
|
||||
return 1;
|
||||
#endif // #if LUA_OPTIMIZE_MEMORY > 0
|
||||
}
|
||||
|
||||
#endif // #ifdef PS_LIB_TABLE_NAME
|
||||
|
@ -6,6 +6,9 @@
|
||||
#include "auxmods.h"
|
||||
#include "board.h"
|
||||
#include "stacks.h"
|
||||
#include "elua_int.h"
|
||||
|
||||
#define PLATFORM_HAS_SYSTIMER
|
||||
|
||||
#if BOARD == EVK1100
|
||||
#include "EVK1100/evk1100_conf.h"
|
||||
@ -17,4 +20,22 @@
|
||||
#error No known AVR32 board defined
|
||||
#endif
|
||||
|
||||
// Common parts
|
||||
|
||||
// Interrupt queue size
|
||||
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
|
||||
|
||||
// Interrupt list
|
||||
#define INT_UART_RX ELUA_INT_FIRST_ID
|
||||
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 1 )
|
||||
#define INT_GPIO_POSEDGE ( ELUA_INT_FIRST_ID + 2 )
|
||||
#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 3 )
|
||||
#define INT_ELUA_LAST INT_GPIO_NEGEDGE
|
||||
|
||||
#define PLATFORM_CPU_CONSTANTS\
|
||||
_C( INT_UART_RX ),\
|
||||
_C( INT_TMR_MATCH ),\
|
||||
_C( INT_GPIO_POSEDGE ),\
|
||||
_C( INT_GPIO_NEGEDGE )
|
||||
|
||||
#endif // #ifndef __PLATFORM_CONF_H__
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include <avr32/io.h>
|
||||
#include "usart.h"
|
||||
#include "intc.h"
|
||||
#include "tc.h"
|
||||
#include "gpio.h"
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt handlers
|
||||
@ -56,6 +58,130 @@ __attribute__((__interrupt__)) static void uart3_rx_handler()
|
||||
uart_common_rx_handler( 3 );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// TMR_MATCH interrupts
|
||||
|
||||
#ifndef VTMR_CH
|
||||
#if VTMR_NUM_TIMERS > 0
|
||||
#define VTMR_CH (2)
|
||||
#else // #if VTMR_NUM_TIMERS > 0
|
||||
#define VTMR_CH 0xFFFF
|
||||
#endif // #if VTMR_NUM_TIMERS > 0
|
||||
#endif // #ifndef VTMR_CH
|
||||
|
||||
extern void platform_eth_timer_handler();
|
||||
static const int tmr_irqs[] = { AVR32_TC_IRQ0, AVR32_TC_IRQ1, AVR32_TC_IRQ2 };
|
||||
extern u8 avr32_timer_int_periodic_flag[ 3 ];
|
||||
|
||||
static void tmr_match_common_handler( int id )
|
||||
{
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
|
||||
tc_read_sr( tc, id ); // clear interrupt
|
||||
if( id == VTMR_CH )
|
||||
{
|
||||
cmn_virtual_timer_cb();
|
||||
platform_eth_timer_handler();
|
||||
}
|
||||
else
|
||||
cmn_int_handler( INT_TMR_MATCH, id );
|
||||
if( avr32_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )
|
||||
{
|
||||
tc->channel[ id ].IDR.cpcs = 1;
|
||||
tc->channel[ id ].CMR.waveform.wavsel = TC_WAVEFORM_SEL_UP_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__interrupt__)) static void tmr0_int_handler()
|
||||
{
|
||||
tmr_match_common_handler( 0 );
|
||||
}
|
||||
|
||||
__attribute__((__interrupt__)) static void tmr1_int_handler()
|
||||
{
|
||||
tmr_match_common_handler( 1 );
|
||||
}
|
||||
|
||||
__attribute__((__interrupt__)) static void tmr2_int_handler()
|
||||
{
|
||||
tmr_match_common_handler( 2 );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GPIO interrupts and helpers
|
||||
|
||||
// AVR32 has a special "pin change" interrupt mode. eLua doesn't have this
|
||||
// interrupt, so we'll enable it when both POSEDGE and NEGEDGE for a pin are
|
||||
// enabled. To do this, we must keep the individual per-pin status of POSEDGE
|
||||
// and NEGEDGE in the arrays below.
|
||||
|
||||
#define AVR32_NUM_PORTS ( ( AVR32_NUM_GPIO + 31 ) >> 5 )
|
||||
static u32 gpio_posedge_status[ AVR32_NUM_PORTS ];
|
||||
static u32 gpio_negedge_status[ AVR32_NUM_PORTS ];
|
||||
|
||||
static void gpioh_set_interrupt( elua_int_resnum resnum )
|
||||
{
|
||||
u8 port = resnum >> 5, pin = resnum & 0x1F;
|
||||
u32 posedge_mask = gpio_posedge_status[ port ] & ( 1 << pin );
|
||||
u32 negedge_mask = gpio_negedge_status[ port ] & ( 1 << pin );
|
||||
|
||||
if( posedge_mask && negedge_mask )
|
||||
gpio_enable_pin_interrupt( resnum, GPIO_PIN_CHANGE );
|
||||
else if( posedge_mask )
|
||||
gpio_enable_pin_interrupt( resnum, GPIO_RISING_EDGE );
|
||||
else if( negedge_mask )
|
||||
gpio_enable_pin_interrupt( resnum, GPIO_FALLING_EDGE );
|
||||
else
|
||||
gpio_disable_pin_interrupt( resnum );
|
||||
}
|
||||
|
||||
/* Now for the interrupt handlers ... a bit weird, but easy to follow. The manual
|
||||
has this to say: "In every port there are four interrupt lines connected to the
|
||||
interrupt controller. Every eigth interrupts in the port are ORed together to form
|
||||
an interrupt line.". So we have an IRQ for each group of 8 consecutive GPIO pins.
|
||||
We could use a single interrupt handler and scan through all pins to see which one
|
||||
generated the interrupt, but it would take a lot of time for 109 pins. Instead,
|
||||
we use all the interrupts that the system can provide and we point them to a single
|
||||
handler; with the proper arguments, it needs to scan only 8 GPIO pins. */
|
||||
|
||||
static void gpio_int_common_handler( int resnum )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 8; i ++, resnum ++ )
|
||||
if( gpio_get_pin_interrupt_flag( resnum ) )
|
||||
{
|
||||
if( gpio_get_pin_value( resnum ) )
|
||||
cmn_int_handler( INT_GPIO_POSEDGE, resnum );
|
||||
else
|
||||
cmn_int_handler( INT_GPIO_NEGEDGE, resnum );
|
||||
gpio_clear_pin_interrupt_flag( resnum );
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_GPIO_HANDLER( num )\
|
||||
__attribute__((__interrupt__)) static void gpio_irq##num##_handler ()\
|
||||
{\
|
||||
gpio_int_common_handler( num << 3 );\
|
||||
}
|
||||
|
||||
DEFINE_GPIO_HANDLER( 0 )
|
||||
DEFINE_GPIO_HANDLER( 1 )
|
||||
DEFINE_GPIO_HANDLER( 2 )
|
||||
DEFINE_GPIO_HANDLER( 3 )
|
||||
DEFINE_GPIO_HANDLER( 4 )
|
||||
DEFINE_GPIO_HANDLER( 5 )
|
||||
#if AVR32_NUM_GPIO > 44 // not an UC3B, asume 109 pins, thus 14 IRQs
|
||||
DEFINE_GPIO_HANDLER( 6 )
|
||||
DEFINE_GPIO_HANDLER( 7 )
|
||||
DEFINE_GPIO_HANDLER( 8 )
|
||||
DEFINE_GPIO_HANDLER( 9 )
|
||||
DEFINE_GPIO_HANDLER( 10 )
|
||||
DEFINE_GPIO_HANDLER( 11 )
|
||||
DEFINE_GPIO_HANDLER( 12 )
|
||||
DEFINE_GPIO_HANDLER( 13 )
|
||||
#endif // #if AVR32_NUM_GPIO > 44
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt: INT_UART_RX
|
||||
|
||||
@ -86,11 +212,116 @@ static int int_uart_rx_get_flag( elua_int_resnum resnum, int clear )
|
||||
return ( pusart->csr & AVR32_USART_CSR_RXRDY_MASK ) ? 1 : 0;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt: INT_TMR_MATCH
|
||||
|
||||
static int int_tmr_match_get_status( elua_int_resnum resnum )
|
||||
{
|
||||
volatile avr32_tc_channel_t *pch = AVR32_TC.channel + resnum;
|
||||
|
||||
return pch->IMR.cpcs;
|
||||
}
|
||||
|
||||
static int int_tmr_match_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
volatile avr32_tc_channel_t *pch = AVR32_TC.channel + resnum;
|
||||
int previous = pch->IMR.cpcs;
|
||||
|
||||
if( status == PLATFORM_CPU_ENABLE )
|
||||
pch->IER.cpcs = 1;
|
||||
else
|
||||
pch->IDR.cpcs = 1;
|
||||
return previous;
|
||||
}
|
||||
|
||||
static int int_tmr_match_get_flag( elua_int_resnum resnum, int clear )
|
||||
{
|
||||
volatile avr32_tc_channel_t *pch = AVR32_TC.channel + resnum;
|
||||
|
||||
( void )clear; // reading the status register will automatically clear the interrupt flag
|
||||
return pch->SR.cpcs;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt: INT_GPIO_POSEDGE
|
||||
|
||||
static int int_gpio_posedge_get_status( elua_int_resnum resnum )
|
||||
{
|
||||
u8 port = resnum >> 5, pin = resnum & 0x1F;
|
||||
|
||||
return ( gpio_posedge_status[ port ] & ( 1 << pin ) ) != 0;
|
||||
}
|
||||
|
||||
static int int_gpio_posedge_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
u8 port = resnum >> 5, pin = resnum & 0x1F;
|
||||
int prev = int_gpio_posedge_get_status( resnum );
|
||||
|
||||
if( status == PLATFORM_CPU_ENABLE )
|
||||
gpio_posedge_status[ port ] |= 1 << pin;
|
||||
else
|
||||
gpio_posedge_status[ port ] &= ~( 1 << pin );
|
||||
gpioh_set_interrupt( resnum );
|
||||
return prev;
|
||||
}
|
||||
|
||||
static int int_gpio_posedge_get_flag( elua_int_resnum resnum, int clear )
|
||||
{
|
||||
if( !int_gpio_posedge_get_status( resnum ) )
|
||||
return 0;
|
||||
int status = gpio_get_pin_interrupt_flag( resnum );
|
||||
|
||||
if( clear )
|
||||
gpio_clear_pin_interrupt_flag( resnum );
|
||||
return status;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt: INT_GPIO_NEGEDGE
|
||||
|
||||
static int int_gpio_negedge_get_status( elua_int_resnum resnum )
|
||||
{
|
||||
u8 port = resnum >> 5, pin = resnum & 0x1F;
|
||||
|
||||
return ( gpio_negedge_status[ port ] & ( 1 << pin ) ) != 0;
|
||||
}
|
||||
|
||||
static int int_gpio_negedge_set_status( elua_int_resnum resnum, int status )
|
||||
{
|
||||
u8 port = resnum >> 5, pin = resnum & 0x1F;
|
||||
int prev = int_gpio_negedge_get_status( resnum );
|
||||
|
||||
if( status == PLATFORM_CPU_ENABLE )
|
||||
gpio_negedge_status[ port ] |= 1 << pin;
|
||||
else
|
||||
gpio_negedge_status[ port ] &= ~( 1 << pin );
|
||||
gpioh_set_interrupt( resnum );
|
||||
return prev;
|
||||
}
|
||||
|
||||
static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear )
|
||||
{
|
||||
if( !int_gpio_negedge_get_status( resnum ) )
|
||||
return 0;
|
||||
int status = gpio_get_pin_interrupt_flag( resnum );
|
||||
|
||||
if( clear )
|
||||
gpio_clear_pin_interrupt_flag( resnum );
|
||||
return status;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
// Interrupt initialization
|
||||
|
||||
typedef void ( *phandler )();
|
||||
static const phandler phandlers[] = { uart0_rx_handler, uart1_rx_handler, uart2_rx_handler, uart3_rx_handler };
|
||||
static const phandler phandlers_usart[] = { uart0_rx_handler, uart1_rx_handler, uart2_rx_handler, uart3_rx_handler };
|
||||
static const phandler phandlers_tmr[] = { tmr0_int_handler, tmr1_int_handler, tmr2_int_handler };
|
||||
#if AVR32_NUM_GPIO == 44 // UC3B - 44 pins
|
||||
static const phandler phandlers_gpio[] = { gpio_irq0_handler, gpio_irq1_handler, gpio_irq2_handler, gpio_irq3_handler, gpio_irq4_handler, gpio_irq5_handler };
|
||||
#else // UC3A - 109 pins
|
||||
static const phandler phandlers_gpio[] = { gpio_irq0_handler, gpio_irq1_handler, gpio_irq2_handler, gpio_irq3_handler, gpio_irq4_handler, gpio_irq5_handler,
|
||||
gpio_irq6_handler, gpio_irq7_handler, gpio_irq8_handler, gpio_irq9_handler, gpio_irq10_handler, gpio_irq11_handler, gpio_irq12_handler, gpio_irq13_handler };
|
||||
#endif
|
||||
|
||||
void platform_int_init()
|
||||
{
|
||||
@ -98,7 +329,11 @@ void platform_int_init()
|
||||
|
||||
for( i = 0; i < NUM_UART; i ++ )
|
||||
if( usart_irqs[ i ] != -1 )
|
||||
INTC_register_interrupt( phandlers[ i ], usart_irqs[ i ], AVR32_INTC_INT0 );
|
||||
INTC_register_interrupt( phandlers_usart[ i ], usart_irqs[ i ], AVR32_INTC_INT0 );
|
||||
for( i = 0; i < sizeof( phandlers_tmr ) / sizeof( phandler ); i ++ )
|
||||
INTC_register_interrupt( phandlers_tmr[ i ], tmr_irqs[ i ], AVR32_INTC_INT0 );
|
||||
for( i = 0; i < sizeof( phandlers_gpio ) / sizeof( phandler ); i ++ )
|
||||
INTC_register_interrupt( phandlers_gpio[ i ], AVR32_GPIO_IRQ_0 + i, AVR32_INTC_INT0 );
|
||||
Enable_global_interrupt();
|
||||
}
|
||||
|
||||
@ -108,7 +343,11 @@ void platform_int_init()
|
||||
|
||||
const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ] =
|
||||
{
|
||||
{ int_uart_rx_set_status, int_uart_rx_get_status, int_uart_rx_get_flag }
|
||||
{ int_uart_rx_set_status, int_uart_rx_get_status, int_uart_rx_get_flag },
|
||||
{ int_tmr_match_set_status, int_tmr_match_get_status, int_tmr_match_get_flag },
|
||||
{ int_gpio_posedge_set_status, int_gpio_posedge_get_status, int_gpio_posedge_get_flag },
|
||||
{ int_gpio_negedge_set_status, int_gpio_negedge_get_status, int_gpio_negedge_get_flag }
|
||||
};
|
||||
|
||||
#endif // #if defined( BUILD_C_INT_HANDLERS ) || defined( BUILD_LUA_INT_HANDLERS )
|
||||
|
||||
|
@ -259,16 +259,18 @@ void pm_configure_usb_clock(void)
|
||||
pm_gc_enable(&AVR32_PM, AVR32_PM_GCLK_USBB);
|
||||
#else
|
||||
// Use 12MHz from OSC0 and generate 96 MHz
|
||||
pm_pll_setup(&AVR32_PM, 1, // pll.
|
||||
7, // mul.
|
||||
1, // div.
|
||||
0, // osc.
|
||||
16); // lockcount.
|
||||
pm_pll_setup(&AVR32_PM,
|
||||
1, // pll.
|
||||
7, // mul.
|
||||
1, // div.
|
||||
0, // osc.
|
||||
16); // lockcount.
|
||||
|
||||
pm_pll_set_option(&AVR32_PM, 1, // pll.
|
||||
1, // pll_freq: choose the range 80-180MHz.
|
||||
1, // pll_div2.
|
||||
0); // pll_wbwdisable.
|
||||
pm_pll_set_option(&AVR32_PM,
|
||||
1, // pll.
|
||||
1, // pll_freq: choose the range 80-180MHz.
|
||||
1, // pll_div2.
|
||||
0); // pll_wbwdisable.
|
||||
|
||||
// start PLL1 and wait forl lock
|
||||
pm_pll_enable(&AVR32_PM, 1);
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "pwm.h"
|
||||
#include "platform_conf.h" // for REQ_PBA_FREQ
|
||||
#include "platform_conf.h" // for REQ_PBA_FREQ
|
||||
|
||||
/*
|
||||
* The AVR32 has 7 PWM channels, each of which chooses its clock from
|
||||
@ -91,7 +91,7 @@ void pwm_set_linear_divider( unsigned prea, unsigned diva )
|
||||
|
||||
mr.prea = prea;
|
||||
mr.diva = diva;
|
||||
mr.preb = 0; // Turn clock B off
|
||||
mr.preb = 0; // Turn clock B off
|
||||
mr.divb = 0;
|
||||
AVR32_PWM.MR = mr;
|
||||
}
|
||||
@ -208,16 +208,14 @@ void pwm_channel_set_period_and_duty_cycle( unsigned id, u32 period, u32 duty )
|
||||
}
|
||||
}
|
||||
#else
|
||||
// No nasty interrupts: just disable, configure and re-enable.
|
||||
// In practice, it seems you don't even need to disable the channel
|
||||
// like the User's Guide tells you to, so we don't bother.
|
||||
// No nasty asynchronous stuff. just disable, configure and re-enable.
|
||||
{
|
||||
//int was_enabled = AVR32_PWM.sr & (1 << id);
|
||||
int was_enabled = AVR32_PWM.sr & (1 << id);
|
||||
|
||||
//if (was_enabled) AVR32_PWM.dis = 1 << id;
|
||||
if (was_enabled) AVR32_PWM.dis = 1 << id;
|
||||
AVR32_PWM.channel[id].cprd = period;
|
||||
AVR32_PWM.channel[id].cdty = duty;
|
||||
//if (was_enabled) AVR32_PWM.ena = 1 << id;
|
||||
if (was_enabled) AVR32_PWM.ena = 1 << id;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -236,8 +234,8 @@ static void pwm_channel_set_period( unsigned id, u32 period )
|
||||
|
||||
// Select updating of the period and write into the update register
|
||||
AVR32_PWM.channel[id].CMR.cpd = AVR32_PWM_CMR_CPD_UPDATE_CPRD;
|
||||
update_has_flushed &= ~(1 << id); // The update hasn't happened yet...
|
||||
AVR32_PWM.channel[id].cupd = period; // Schedule the update to be performed
|
||||
update_has_flushed &= ~(1 << id); // The update hasn't happened yet...
|
||||
AVR32_PWM.channel[id].cupd = period; // Schedule the update to be performed
|
||||
}
|
||||
|
||||
static void pwm_channel_set_duty_cycle( unsigned id, u32 duty )
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user