1
0
mirror of https://github.com/elua/elua.git synced 2025-01-25 01:02:54 +08:00

Merge branch 'master' into lm3s_usb_cdc

This commit is contained in:
James Snyder 2011-11-13 17:41:23 -06:00
commit 1b678dfea2
95 changed files with 2886 additions and 1730 deletions

View File

@ -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>

View File

@ -162,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',
@ -277,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:
@ -336,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 ) } )

View File

@ -206,7 +206,7 @@ for k, v in pairs( board_list ) do
end
end
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' } )
@ -310,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'
@ -362,7 +366,8 @@ 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

View File

@ -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" }

View File

@ -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
@ -15,9 +23,10 @@ data_en =
-- 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 specified 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) between 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 enabled, 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.~
]]
}
}
}

View File

@ -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 &gt; 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"
}
},

View File

@ -104,14 +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, in microseconds, after which the accept function returns if no connection was requested.]]
[[$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 =
{
@ -135,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 =
{
@ -145,9 +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, in microseconds, after which the recv function returns if no connection was requested.]]
[[$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 =
{
@ -158,4 +159,3 @@ be specified.]],
},
}
data_pt = data_en

View File

@ -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 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 = "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 )",
{ sig = "mindelay = #tmr.getmindelay#( [id] )",
desc = "Get the minimum achievable delay on 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 minimum achievable delay on the specified timer (in us)."
},
{ sig = "maxdelay = #tmr.getmaxdelay#( id )",
{ sig = "maxdelay = #tmr.getmaxdelay#( [id] )",
desc = "Get the maximum achievable delay on 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 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).]],
}
}

View File

@ -57,12 +57,10 @@ to the IDs of the virtual UARTs in the system.]]
desc = "Read a single character from the serial port",
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$).]]
"$id$ - the ID of the serial port",
[[$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]]
},

View File

@ -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

View File

@ -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

View File

@ -68,8 +68,8 @@ $$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$$

View File

@ -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 />

View File

@ -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]

View File

@ -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.

View File

@ -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
-------------------

View File

@ -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__

View File

@ -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 );

View File

@ -1,65 +1,65 @@
// Lightweight remote procedure call layer
#ifndef __ELUARPC_H__
#define __ELUARPC_H__
#include "type.h"
#define PACKET_SIG 0x18AFC284UL
// Error codes
#define ELUARPC_OK 0
#define ELUARPC_ERR 1
#define ELUARPC_OP_RES_MOD 0x80
// Protocol constants
#define ELUARPC_START_OFFSET 4
#define ELUARPC_START_SIZE 6
#define ELUARPC_END_SIZE 6
#define ELUARPC_RESPONSE_SIZE 1
#define ELUARPC_PTR_HEADER_SIZE 6
#define ELUARPC_SMALL_PTR_HEADER_SIZE 4
#define ELUARPC_U32_SIZE 5
#define ELUARPC_U16_SIZE 3
#define ELUARPC_U8_SIZE 2
#define ELUARPC_OP_ID_SIZE 2
#define ELUARPC_READ_BUF_OFFSET ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_RESPONSE_SIZE + ELUARPC_PTR_HEADER_SIZE )
#define ELUARPC_SMALL_READ_BUF_OFFSET ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_RESPONSE_SIZE + ELUARPC_SMALL_PTR_HEADER_SIZE )
#define ELUARPC_WRITE_REQUEST_EXTRA ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_OP_ID_SIZE + ELUARPC_U32_SIZE + ELUARPC_PTR_HEADER_SIZE + ELUARPC_END_SIZE )
// Public interface
// Get request ID
int eluarpc_get_request_id( const u8 *p, u8 *pid );
// Replace a flag with another flag
u32 eluarpc_replace_flag( u32 val, u32 origflag, u32 newflag );
// Get packet size
int eluarpc_get_packet_size( const u8 *p, u16 *psize );
// Generic write function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// i - int
// L - s32
// p - ptr (given as ptr, len, len is an u32)
// P - ptr (given as ptr, len, len is an u16)
void eluarpc_gen_write( u8 *p, const char *fmt, ... );
// Generic read function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// L - s32
// i - int
// p - ptr (returned as ptr, len, len is an u32)
// P - ptr (returned as ptr, len, len is an u16)
int eluarpc_gen_read( const u8 *p, const char *fmt, ... );
#endif
// Lightweight remote procedure call layer
#ifndef __ELUARPC_H__
#define __ELUARPC_H__
#include "type.h"
#define PACKET_SIG 0x18AFC284UL
// Error codes
#define ELUARPC_OK 0
#define ELUARPC_ERR 1
#define ELUARPC_OP_RES_MOD 0x80
// Protocol constants
#define ELUARPC_START_OFFSET 4
#define ELUARPC_START_SIZE 6
#define ELUARPC_END_SIZE 6
#define ELUARPC_RESPONSE_SIZE 1
#define ELUARPC_PTR_HEADER_SIZE 6
#define ELUARPC_SMALL_PTR_HEADER_SIZE 4
#define ELUARPC_U32_SIZE 5
#define ELUARPC_U16_SIZE 3
#define ELUARPC_U8_SIZE 2
#define ELUARPC_OP_ID_SIZE 2
#define ELUARPC_READ_BUF_OFFSET ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_RESPONSE_SIZE + ELUARPC_PTR_HEADER_SIZE )
#define ELUARPC_SMALL_READ_BUF_OFFSET ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_RESPONSE_SIZE + ELUARPC_SMALL_PTR_HEADER_SIZE )
#define ELUARPC_WRITE_REQUEST_EXTRA ( ELUARPC_START_OFFSET + ELUARPC_START_SIZE + ELUARPC_OP_ID_SIZE + ELUARPC_U32_SIZE + ELUARPC_PTR_HEADER_SIZE + ELUARPC_END_SIZE )
// Public interface
// Get request ID
int eluarpc_get_request_id( const u8 *p, u8 *pid );
// Replace a flag with another flag
u32 eluarpc_replace_flag( u32 val, u32 origflag, u32 newflag );
// Get packet size
int eluarpc_get_packet_size( const u8 *p, u16 *psize );
// Generic write function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// i - int
// L - s32
// p - ptr (given as ptr, len, len is an u32)
// P - ptr (given as ptr, len, len is an u16)
void eluarpc_gen_write( u8 *p, const char *fmt, ... );
// Generic read function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// L - s32
// i - int
// p - ptr (returned as ptr, len, len is an u32)
// P - ptr (returned as ptr, len, len is an u16)
int eluarpc_gen_read( const u8 *p, const char *fmt, ... );
#endif

View File

@ -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 );

View File

@ -68,6 +68,76 @@ 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 )
// *****************************************************************************
// CAN subsection
@ -133,9 +203,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,51 +214,11 @@ 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
@ -230,21 +257,20 @@ u32 platform_cpu_get_frequency();
// The platform ADC functions
// 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_set_clock( 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_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 );
u32 platform_adc_set_clock( unsigned id, u32 freq );
// *****************************************************************************
// I2C platform interface

View File

@ -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 );

View File

@ -74,14 +74,8 @@
#endif
#endif
// MMCFS uses the virtual timer to implement its timeouts
#if defined( BUILD_MMCFS ) && (!defined( VTMR_NUM_TIMERS ) || VTMR_NUM_TIMERS == 0)
#error "BUILD_MMCFS needs virtual timer support. Define VTMR_NUM_TIMERS > 0"
#endif
// MMCFS tick runs off VTMR timer so these values must be the same
#if defined( BUILD_MMCFS ) && MMCFS_TICK_HZ != VTMR_FREQ_HZ
#error "MMCFS_TICK_HZ must be equal to VTMR_FREQ_HZ"
#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

View File

@ -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 );

View File

@ -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

View File

@ -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 );
}
@ -445,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" );
}

View File

@ -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,23 +200,71 @@ 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 );
#if VTMR_NUM_TIMERS > 0
@ -211,6 +286,10 @@ u32 platform_timer_op( unsigned id, int op, u32 data )
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
res = platform_timer_get_diff_us( id, 0, 1 );
break;
case PLATFORM_TIMER_OP_GET_MAX_CNT:
res = VTMR_MAX_PERIOD;
break;
case PLATFORM_TIMER_OP_SET_CLOCK:
case PLATFORM_TIMER_OP_GET_CLOCK:
@ -221,49 +300,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, res;
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;
}
res = ( ( u64 )( start - end ) * 1000000 ) / freq;
// The result always ends up being given to lua_pushinteger() which turns
// 0x80000000-0xFFFFFFFF into negative numbers, so max out at 2^31-1 to
// avoid getting negative results from tmr.getmaxdelay(tmr.VIRT0) and
// tmr.gettimediff(N, small, large).
#define MAX_U32 ( ~(u32)0 >> 1 )
if ( res > MAX_U32 ) res = MAX_U32;
return res;
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 );
@ -271,11 +342,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 );
@ -283,11 +356,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 );
@ -295,7 +370,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;
@ -303,3 +378,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;
}

View File

@ -40,7 +40,7 @@ int platform_uart_exists( unsigned id )
}
// 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;
@ -73,25 +73,24 @@ static int cmn_recv_helper( unsigned id, s32 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;

View File

@ -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 );

View File

@ -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,24 +67,6 @@ BYTE CardType; /* b0:MMC, b1:SDC, b2:Block addressing */
static
BYTE PowerFlag = 0; /* indicates if "power" is on */
/*-----------------------------------------------------------------------*/
/* Find the value to set in Timer1 or Timer2 to obtain a timeout of at */
/* least N milliseconds. */
/* */
/* Timer1 and Timer2 are decremented by the virtual timer interrupt, */
/* which is free-running and will sometimes decrement TimerN immediately */
/* so to wait for N ms to pass, you need to wait for N+1 ticks to occur. */
/* */
/* Usage example: */
/* Timer1 = set_Timer_ms(N); */
/* do { whatever } while (Timer1); */
/*-----------------------------------------------------------------------*/
static UINT set_Timer_ms(UINT ms)
{
UINT ticks = ms / MMCFS_TICK_MS;
return (ticks > 0 ? ticks : 1) + 1;
}
/*-----------------------------------------------------------------------*/
/* Transmit a byte to MMC via SPI (Platform dependent) */
@ -128,11 +110,11 @@ BYTE wait_ready (void)
{
BYTE res;
Timer2 = set_Timer_ms(500); /* 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);
do
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;
}
@ -224,10 +206,11 @@ BOOL rcvr_datablock (
{
BYTE token;
Timer1 = set_Timer_ms(100);
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 */
@ -344,14 +327,15 @@ DSTATUS disk_initialize (
SELECT(); /* CS = L */
ty = 0;
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
Timer1 = set_Timer_ms(1000); /* 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 */
} 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;
}
@ -364,8 +348,9 @@ DSTATUS disk_initialize (
} else {
if (send_cmd(CMD1, 0) == 0) break; /* CMD1 */
}
} while (Timer1);
if (!Timer1 || send_cmd(CMD16, 512) != 0) /* Select R/W block length */
} 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;
}
}
@ -598,23 +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 */
/*---------------------------------------------------------*/

View File

@ -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;

View File

@ -1,359 +1,359 @@
// eLua RPC mechanism
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "type.h"
#include "eluarpc.h"
#include "rtype.h"
static u8 eluarpc_err_flag;
// *****************************************************************************
// Internal functions: fdata serialization
static u8 *eluarpc_write_u8( u8 *p, u8 fdata )
{
*p ++ = TYPE_INT_8;
*p ++ = fdata;
return p;
}
static u8* eluarpc_write_op_id( u8 *p, u8 fdata )
{
*p ++ = TYPE_OP_ID;
*p ++ = fdata;
return p;
}
static u8 *eluarpc_write_u16( u8 *p, u16 fdata )
{
*p ++ = TYPE_INT_16;
*p ++ = fdata & 0xFF;
*p ++ = ( fdata >> 8 ) & 0xFF;
return p;
}
static u8 *eluarpc_write_u32( u8 *p, u32 fdata )
{
*p ++ = TYPE_INT_32;
*p ++ = fdata & 0xFF;
*p ++ = ( fdata >> 8 ) & 0xFF;
*p ++ = ( fdata >> 16 ) & 0xFF;
*p ++ = ( fdata >> 24 ) & 0xFF;
return p;
}
static u8 *eluarpc_write_ptr( u8 *p, const void* src, u32 srclen )
{
*p ++ = TYPE_PTR;
p = eluarpc_write_u32( p, srclen );
if( src )
memcpy( p, src, srclen );
return p + srclen;
}
static u8 *eluarpc_write_small_ptr( u8 *p, const void* src, u16 srclen )
{
*p ++ = TYPE_SMALL_PTR;
p = eluarpc_write_u16( p, srclen );
if( src )
memcpy( p, src, srclen );
return p + srclen;
}
// *****************************************************************************
// Internal functions: fdata deserialization
static const u8* eluarpc_read_expect( const u8 *p, u8 fdata )
{
if( *p ++ != fdata )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8 *eluarpc_read_u8( const u8 *p, u8 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_8 );
*pfdata = *p ++;
return p;
}
static const u8 *eluarpc_read_op_id( const u8 *p, u8 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_OP_ID );
*pfdata = *p ++;
return p;
}
static const u8* eluarpc_expect_op_id( const u8 *p, u8 id )
{
u8 temp;
p = eluarpc_read_expect( p, TYPE_OP_ID );
temp = *p ++;
if( temp != id )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8 *eluarpc_read_u16( const u8 *p, u16 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_16 );
*pfdata = *p ++;
*pfdata |= ( u32 )( *p ++ ) << 8;
return p;
}
static const u8 *eluarpc_read_u32( const u8 *p, u32 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_32 );
*pfdata = *p ++;
*pfdata |= ( u32 )( *p ++ ) << 8;
*pfdata |= ( u32 )( *p ++ ) << 16;
*pfdata |= ( u32 )( *p ++ ) << 24;
return p;
}
static const u8 *eluarpc_read_ptr( const u8 *p, void* src, u32 *psrclen )
{
p = eluarpc_read_expect( p, TYPE_PTR );
p = eluarpc_read_u32( p, psrclen );
if( src && p )
memcpy( src, p, *psrclen );
return p + *psrclen;
}
static const u8 *eluarpc_read_small_ptr( const u8 *p, void* src, u16 *psrclen )
{
p = eluarpc_read_expect( p, TYPE_SMALL_PTR );
p = eluarpc_read_u16( p, psrclen );
if( src && p )
memcpy( src, p, *psrclen );
return p + *psrclen;
}
// *****************************************************************************
// Internal functions: packet handling (read and write)
static u8* eluarpc_packet_ptr;
static u8* eluarpc_start_packet( u8 *p )
{
eluarpc_packet_ptr = p;
p += ELUARPC_START_OFFSET;
*p ++ = TYPE_START;
p = eluarpc_write_u32( p, PACKET_SIG );
return p;
}
static u8* eluarpc_end_packet( u8 *p )
{
u16 len;
*p ++ = TYPE_END;
p = eluarpc_write_u32( p, ~PACKET_SIG );
len = p - eluarpc_packet_ptr;
p = eluarpc_packet_ptr;
*p ++ = TYPE_PKT_SIZE;
eluarpc_write_u16( p, len );
return p;
}
static const u8* eluarpc_match_packet_start( const u8 *p )
{
u32 fdata;
p += ELUARPC_START_OFFSET;
p = eluarpc_read_expect( p, TYPE_START );
p = eluarpc_read_u32( p, &fdata );
if( fdata != PACKET_SIG )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8* eluarpc_match_packet_end( const u8 *p )
{
u32 fdata;
p = eluarpc_read_expect( p, TYPE_END );
p = eluarpc_read_u32( p, &fdata );
if( fdata != ~PACKET_SIG )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
// *****************************************************************************
// Function serialization and deserialization
int eluarpc_get_request_id( const u8 *p, u8 *pid )
{
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_match_packet_start( p );
p = eluarpc_read_op_id( p, pid );
return eluarpc_err_flag;
}
u32 eluarpc_replace_flag( u32 val, u32 origflag, u32 newflag )
{
return ( val & origflag ) ? newflag : 0;
}
int eluarpc_get_packet_size( const u8 *p, u16 *psize )
{
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_read_expect( p, TYPE_PKT_SIZE );
p = eluarpc_read_u16( p, psize );
return eluarpc_err_flag;
}
// Generic write function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// i - int
// L - s32
// p - ptr (given as ptr, len, len is an u32)
// P - ptr (given as ptr, len, len is an u16)
void eluarpc_gen_write( u8 *p, const char *fmt, ... )
{
va_list ap;
const void *ptr;
u32 ptrlen;
va_start( ap, fmt );
p = eluarpc_start_packet( p );
while( *fmt )
switch( *fmt ++ )
{
case 'o':
p = eluarpc_write_op_id( p, va_arg( ap, int ) );
break;
case 'r':
*p++ = ELUARPC_OP_RES_MOD | ( u8 )va_arg( ap, int );
break;
case 'c':
p = eluarpc_write_u8( p, ( u8 )va_arg( ap, int ) );
break;
case 'h':
p = eluarpc_write_u16( p, ( u16 )va_arg( ap, int ) );
break;
case 'i':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, int ) );
break;
case 'l':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, u32 ) );
break;
case 'L':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, s32 ) );
break;
case 'p':
ptr = va_arg( ap, void* );
ptrlen = ( u32 )va_arg( ap, u32 );
p = eluarpc_write_ptr( p, ptr, ptrlen );
break;
case 'P':
ptr = va_arg( ap, void * );
ptrlen = ( u16 )va_arg( ap, int );
p = eluarpc_write_small_ptr( p, ptr, ptrlen );
break;
}
eluarpc_end_packet( p );
}
// Generic read function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// L - s32
// i - int
// p - ptr (returned as ptr, len, len is an u32)
// P - ptr (returned as ptr, len, len is an u16)
int eluarpc_gen_read( const u8 *p, const char *fmt, ... )
{
va_list ap;
const void *pptr;
u32 *ptrlen;
const u8 *tempptr;
u32 temp32;
u16 temp16;
u16 *sptrlen;
va_start( ap, fmt );
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_match_packet_start( p );
while( *fmt )
switch( *fmt ++ )
{
case 'o':
p = eluarpc_expect_op_id( p, va_arg( ap, int ) );
break;
case 'r':
p = eluarpc_read_expect( p, ELUARPC_OP_RES_MOD | ( u8 )va_arg( ap, int ) );
break;
case 'c':
p = eluarpc_read_u8( p, ( u8* )va_arg( ap, void * ) );
break;
case 'h':
p = eluarpc_read_u16( p, ( u16* )va_arg( ap, void * ) );
break;
case 'l':
p = eluarpc_read_u32( p, ( u32* )va_arg( ap, void * ) );
break;
case 'L':
p = eluarpc_read_u32( p, &temp32 );
*( s32 *)va_arg( ap, void * ) = ( s32 )temp32;
break;
case 'i':
p = eluarpc_read_u32( p, &temp32 );
*( int* )va_arg( ap, void * ) = ( int )temp32;
break;
case 'p':
pptr = va_arg( ap, void** );
ptrlen = ( u32* )va_arg( ap, void* );
tempptr = p;
p = eluarpc_read_ptr( p, NULL, &temp32 );
if( p == tempptr + ELUARPC_PTR_HEADER_SIZE )
*( const u8** )pptr = NULL;
else
*( const u8** )pptr = tempptr + ELUARPC_PTR_HEADER_SIZE;
if( ptrlen )
*ptrlen = temp32;
break;
case 'P':
pptr = va_arg( ap, void** );
sptrlen = ( u16* )va_arg( ap, void* );
tempptr = p;
p = eluarpc_read_small_ptr( p, NULL, &temp16 );
if( p == tempptr + ELUARPC_SMALL_PTR_HEADER_SIZE )
*( const u8** )pptr = NULL;
else
*( const u8** )pptr = tempptr + ELUARPC_SMALL_PTR_HEADER_SIZE;
if( sptrlen )
*sptrlen = temp16;
break;
}
eluarpc_match_packet_end( p );
return eluarpc_err_flag;
}
// eLua RPC mechanism
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include "type.h"
#include "eluarpc.h"
#include "rtype.h"
static u8 eluarpc_err_flag;
// *****************************************************************************
// Internal functions: fdata serialization
static u8 *eluarpc_write_u8( u8 *p, u8 fdata )
{
*p ++ = TYPE_INT_8;
*p ++ = fdata;
return p;
}
static u8* eluarpc_write_op_id( u8 *p, u8 fdata )
{
*p ++ = TYPE_OP_ID;
*p ++ = fdata;
return p;
}
static u8 *eluarpc_write_u16( u8 *p, u16 fdata )
{
*p ++ = TYPE_INT_16;
*p ++ = fdata & 0xFF;
*p ++ = ( fdata >> 8 ) & 0xFF;
return p;
}
static u8 *eluarpc_write_u32( u8 *p, u32 fdata )
{
*p ++ = TYPE_INT_32;
*p ++ = fdata & 0xFF;
*p ++ = ( fdata >> 8 ) & 0xFF;
*p ++ = ( fdata >> 16 ) & 0xFF;
*p ++ = ( fdata >> 24 ) & 0xFF;
return p;
}
static u8 *eluarpc_write_ptr( u8 *p, const void* src, u32 srclen )
{
*p ++ = TYPE_PTR;
p = eluarpc_write_u32( p, srclen );
if( src )
memcpy( p, src, srclen );
return p + srclen;
}
static u8 *eluarpc_write_small_ptr( u8 *p, const void* src, u16 srclen )
{
*p ++ = TYPE_SMALL_PTR;
p = eluarpc_write_u16( p, srclen );
if( src )
memcpy( p, src, srclen );
return p + srclen;
}
// *****************************************************************************
// Internal functions: fdata deserialization
static const u8* eluarpc_read_expect( const u8 *p, u8 fdata )
{
if( *p ++ != fdata )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8 *eluarpc_read_u8( const u8 *p, u8 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_8 );
*pfdata = *p ++;
return p;
}
static const u8 *eluarpc_read_op_id( const u8 *p, u8 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_OP_ID );
*pfdata = *p ++;
return p;
}
static const u8* eluarpc_expect_op_id( const u8 *p, u8 id )
{
u8 temp;
p = eluarpc_read_expect( p, TYPE_OP_ID );
temp = *p ++;
if( temp != id )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8 *eluarpc_read_u16( const u8 *p, u16 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_16 );
*pfdata = *p ++;
*pfdata |= ( u32 )( *p ++ ) << 8;
return p;
}
static const u8 *eluarpc_read_u32( const u8 *p, u32 *pfdata )
{
p = eluarpc_read_expect( p, TYPE_INT_32 );
*pfdata = *p ++;
*pfdata |= ( u32 )( *p ++ ) << 8;
*pfdata |= ( u32 )( *p ++ ) << 16;
*pfdata |= ( u32 )( *p ++ ) << 24;
return p;
}
static const u8 *eluarpc_read_ptr( const u8 *p, void* src, u32 *psrclen )
{
p = eluarpc_read_expect( p, TYPE_PTR );
p = eluarpc_read_u32( p, psrclen );
if( src && p )
memcpy( src, p, *psrclen );
return p + *psrclen;
}
static const u8 *eluarpc_read_small_ptr( const u8 *p, void* src, u16 *psrclen )
{
p = eluarpc_read_expect( p, TYPE_SMALL_PTR );
p = eluarpc_read_u16( p, psrclen );
if( src && p )
memcpy( src, p, *psrclen );
return p + *psrclen;
}
// *****************************************************************************
// Internal functions: packet handling (read and write)
static u8* eluarpc_packet_ptr;
static u8* eluarpc_start_packet( u8 *p )
{
eluarpc_packet_ptr = p;
p += ELUARPC_START_OFFSET;
*p ++ = TYPE_START;
p = eluarpc_write_u32( p, PACKET_SIG );
return p;
}
static u8* eluarpc_end_packet( u8 *p )
{
u16 len;
*p ++ = TYPE_END;
p = eluarpc_write_u32( p, ~PACKET_SIG );
len = p - eluarpc_packet_ptr;
p = eluarpc_packet_ptr;
*p ++ = TYPE_PKT_SIZE;
eluarpc_write_u16( p, len );
return p;
}
static const u8* eluarpc_match_packet_start( const u8 *p )
{
u32 fdata;
p += ELUARPC_START_OFFSET;
p = eluarpc_read_expect( p, TYPE_START );
p = eluarpc_read_u32( p, &fdata );
if( fdata != PACKET_SIG )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
static const u8* eluarpc_match_packet_end( const u8 *p )
{
u32 fdata;
p = eluarpc_read_expect( p, TYPE_END );
p = eluarpc_read_u32( p, &fdata );
if( fdata != ~PACKET_SIG )
eluarpc_err_flag = ELUARPC_ERR;
return p;
}
// *****************************************************************************
// Function serialization and deserialization
int eluarpc_get_request_id( const u8 *p, u8 *pid )
{
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_match_packet_start( p );
p = eluarpc_read_op_id( p, pid );
return eluarpc_err_flag;
}
u32 eluarpc_replace_flag( u32 val, u32 origflag, u32 newflag )
{
return ( val & origflag ) ? newflag : 0;
}
int eluarpc_get_packet_size( const u8 *p, u16 *psize )
{
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_read_expect( p, TYPE_PKT_SIZE );
p = eluarpc_read_u16( p, psize );
return eluarpc_err_flag;
}
// Generic write function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// i - int
// L - s32
// p - ptr (given as ptr, len, len is an u32)
// P - ptr (given as ptr, len, len is an u16)
void eluarpc_gen_write( u8 *p, const char *fmt, ... )
{
va_list ap;
const void *ptr;
u32 ptrlen;
va_start( ap, fmt );
p = eluarpc_start_packet( p );
while( *fmt )
switch( *fmt ++ )
{
case 'o':
p = eluarpc_write_op_id( p, va_arg( ap, int ) );
break;
case 'r':
*p++ = ELUARPC_OP_RES_MOD | ( u8 )va_arg( ap, int );
break;
case 'c':
p = eluarpc_write_u8( p, ( u8 )va_arg( ap, int ) );
break;
case 'h':
p = eluarpc_write_u16( p, ( u16 )va_arg( ap, int ) );
break;
case 'i':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, int ) );
break;
case 'l':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, u32 ) );
break;
case 'L':
p = eluarpc_write_u32( p, ( u32 )va_arg( ap, s32 ) );
break;
case 'p':
ptr = va_arg( ap, void* );
ptrlen = ( u32 )va_arg( ap, u32 );
p = eluarpc_write_ptr( p, ptr, ptrlen );
break;
case 'P':
ptr = va_arg( ap, void * );
ptrlen = ( u16 )va_arg( ap, int );
p = eluarpc_write_small_ptr( p, ptr, ptrlen );
break;
}
eluarpc_end_packet( p );
}
// Generic read function
// Specifiers: o - operation
// r - response
// c - u8
// h - u16
// l - u32
// L - s32
// i - int
// p - ptr (returned as ptr, len, len is an u32)
// P - ptr (returned as ptr, len, len is an u16)
int eluarpc_gen_read( const u8 *p, const char *fmt, ... )
{
va_list ap;
const void *pptr;
u32 *ptrlen;
const u8 *tempptr;
u32 temp32;
u16 temp16;
u16 *sptrlen;
va_start( ap, fmt );
eluarpc_err_flag = ELUARPC_OK;
p = eluarpc_match_packet_start( p );
while( *fmt )
switch( *fmt ++ )
{
case 'o':
p = eluarpc_expect_op_id( p, va_arg( ap, int ) );
break;
case 'r':
p = eluarpc_read_expect( p, ELUARPC_OP_RES_MOD | ( u8 )va_arg( ap, int ) );
break;
case 'c':
p = eluarpc_read_u8( p, ( u8* )va_arg( ap, void * ) );
break;
case 'h':
p = eluarpc_read_u16( p, ( u16* )va_arg( ap, void * ) );
break;
case 'l':
p = eluarpc_read_u32( p, ( u32* )va_arg( ap, void * ) );
break;
case 'L':
p = eluarpc_read_u32( p, &temp32 );
*( s32 *)va_arg( ap, void * ) = ( s32 )temp32;
break;
case 'i':
p = eluarpc_read_u32( p, &temp32 );
*( int* )va_arg( ap, void * ) = ( int )temp32;
break;
case 'p':
pptr = va_arg( ap, void** );
ptrlen = ( u32* )va_arg( ap, void* );
tempptr = p;
p = eluarpc_read_ptr( p, NULL, &temp32 );
if( p == tempptr + ELUARPC_PTR_HEADER_SIZE )
*( const u8** )pptr = NULL;
else
*( const u8** )pptr = tempptr + ELUARPC_PTR_HEADER_SIZE;
if( ptrlen )
*ptrlen = temp32;
break;
case 'P':
pptr = va_arg( ap, void** );
sptrlen = ( u16* )va_arg( ap, void* );
tempptr = p;
p = eluarpc_read_small_ptr( p, NULL, &temp16 );
if( p == tempptr + ELUARPC_SMALL_PTR_HEADER_SIZE )
*( const u8** )pptr = NULL;
else
*( const u8** )pptr = tempptr + ELUARPC_SMALL_PTR_HEADER_SIZE;
if( sptrlen )
*sptrlen = temp16;
break;
}
eluarpc_match_packet_end( p );
return eluarpc_err_flag;
}

View File

@ -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);

View File

@ -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.
@ -518,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
/*
@ -553,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
@ -574,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.
@ -827,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

View File

@ -7,15 +7,29 @@
#if defined( BUILD_RPC )
// Buffer for async dispatch
int adispatch_buff = -1;
void set_adispatch_buff( int i )
{
adispatch_buff = i;
}
// Setup Transport
void transport_init (Transport *tpt)
void transport_init( Transport *tpt )
{
tpt->fd = INVALID_TRANSPORT;
tpt->tmr_id = 0;
}
// Read a char from serial buffer
int transport_get_char(Transport *t)
{
return platform_uart_recv( t->fd, t->tmr_id, 0 );
}
// Open Listener / Server
void transport_open_listener(lua_State *L, ServerHandle *handle)
void transport_open_listener( lua_State *L, ServerHandle *handle )
{
// Get args & Set up connection
unsigned uart_id, tmr_id;
@ -38,6 +52,9 @@ void transport_open_listener(lua_State *L, ServerHandle *handle)
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
@ -59,33 +76,45 @@ int transport_open_connection(lua_State *L, Handle *handle)
tmr_id = lua_tonumber( L, 1 );
MOD_CHECK_ID( timer, tmr_id );
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;
}
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
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 );
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
@ -102,7 +131,6 @@ void transport_read_buffer (Transport *tpt, u8 *buffer, int length)
// should follow within a timeout of 0.1 sec
uart_timeout = 100000;
}
}
void transport_write_buffer( Transport *tpt, const u8 *buffer, int length )
@ -110,27 +138,40 @@ void transport_write_buffer( Transport *tpt, const u8 *buffer, int length )
int i;
struct exception e;
TRANSPORT_VERIFY_OPEN;
for( i = 0; i < length; i ++ )
platform_uart_send( CON_UART_ID, buffer[ 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)
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)
int transport_is_open( Transport *tpt )
{
return ( tpt->fd != INVALID_TRANSPORT );
}
// Shut down connection
void transport_close (Transport *tpt)
void transport_close( Transport *tpt )
{
tpt->fd = INVALID_TRANSPORT;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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 )

View File

@ -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;
}
@ -74,7 +78,7 @@ static int i2c_write( lua_State *L )
{
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 ++;
@ -85,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;
}

View File

@ -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 ];
@ -1568,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 )
@ -1659,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 ) },
@ -1721,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 }
};

View File

@ -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

View File

@ -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;
}
@ -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_set_clock( id, 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;
}

View File

@ -21,116 +21,130 @@ 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 )
@ -172,7 +186,8 @@ const LUA_REG_TYPE tmr_map[] =
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "read" ), LFUNCVAL( tmr_read ) },
{ LSTRKEY( "start" ), LFUNCVAL( tmr_start ) },
{ LSTRKEY( "gettimediff" ), LFUNCVAL( tmr_gettimediff ) },
{ 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 ) },
@ -185,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 ) },
@ -204,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
}

View File

@ -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 );

View File

@ -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"

View File

@ -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')

View 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;
}

View 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

View File

@ -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
@ -98,7 +134,12 @@ int platform_init()
AT91C_BASE_TC2->TC_IER = AT91C_TC_CPCS;
AIC_EnableIT( AT91C_ID_TC2 );
TC_Start( AT91C_BASE_TC2 );
#endif
#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 ];
@ -325,10 +366,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

View File

@ -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

View File

@ -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
@ -116,14 +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
@ -140,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, ...)
@ -164,7 +160,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
@ -178,10 +173,12 @@
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 1 )
#define INT_ELUA_LAST INT_TMR_MATCH
#define PLATFORM_CPU_CONSTANTS\
_C( INT_UART_RX )
_C( INT_UART_RX ),\
_C( INT_TMR_MATCH )
// *****************************************************************************
// CPU constants that should be exposed to the eLua "cpu" module

View File

@ -21,7 +21,6 @@
#define CON_UART_ID 1
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -86,13 +85,12 @@
#else
#define NUM_TIMER 3
#endif
#define NUM_PWM 7
#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
@ -105,13 +103,11 @@
#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, ...)
@ -132,10 +128,12 @@
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 1 )
#define INT_ELUA_LAST INT_TMR_MATCH
#define PLATFORM_CPU_CONSTANTS\
_C( INT_UART_RX )
_C( INT_UART_RX ),\
_C( INT_TMR_MATCH )
// *****************************************************************************
// CPU constants that should be exposed to the eLua "cpu" module

View File

@ -61,7 +61,6 @@
# define CON_UART_ID 0
#endif
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -163,7 +162,7 @@
#else
#define NUM_TIMER 3
#endif
#define NUM_PWM 7 // PWM7 is on GPIO50
#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
@ -176,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
@ -189,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, ...)
@ -222,7 +218,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
@ -233,10 +228,12 @@
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 1 )
#define INT_ELUA_LAST INT_TMR_MATCH
#define PLATFORM_CPU_CONSTANTS\
_C( INT_UART_RX )
_C( INT_UART_RX ),\
_C( INT_TMR_MATCH )
// *****************************************************************************
// CPU constants that should be exposed to the eLua "cpu" module

View File

@ -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)

View File

@ -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_

File diff suppressed because it is too large Load Diff

View File

@ -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
@ -413,7 +413,7 @@ typedef struct _AVR32_TxTdDescriptor {
*
* \return TRUE if success, FALSE otherwise.
*/
extern Bool xMACBInit(volatile avr32_macb_t *macb);
extern Bool xMACBInit(volatile avr32_macb_t *macb);
/**
* \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
@ -428,7 +428,7 @@ extern Bool xMACBInit(volatile avr32_macb_t *macb);
*
* \return length sent.
*/
extern long lMACBSend(volatile avr32_macb_t *macb, const void *pvFrom, unsigned long ulLength, long lEndOfFrame);
extern long lMACBSend(volatile avr32_macb_t *macb, const void *pvFrom, unsigned long ulLength, long lEndOfFrame);
/**
* \brief Frames can be read from the MACB in multiple sections.
@ -441,21 +441,21 @@ extern long lMACBSend(volatile avr32_macb_t *macb, const void *pvFrom, unsigned
* \param ulSectionLength Length of the buffer
* \param ulTotalFrameLength Length of the frame
*/
extern void vMACBRead(void *pvTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength);
extern void vMACBRead(void *pvTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength);
/**
* \brief Flush the current received packet.
*
* \param ulTotalFrameLength Length of the packet to flush
*/
extern void vMACBFlushCurrentPacket(unsigned long ulTotalFrameLength);
extern void vMACBFlushCurrentPacket(unsigned long ulTotalFrameLength);
/**
* \brief Called by the Tx interrupt, this function traverses the buffers used to
* hold the frame that has just completed transmission and marks each as
* free again.
*/
extern void vClearMACBTxBuffer(void);
extern void vClearMACBTxBuffer(void);
/**
* \brief Suspend on a semaphore waiting either for the semaphore to be obtained
@ -465,28 +465,28 @@ extern void vClearMACBTxBuffer(void);
* \param ulTimeOut time to wait for an input
*
*/
extern void vMACBWaitForInput(unsigned long ulTimeOut);
extern void vMACBWaitForInput(unsigned long ulTimeOut);
/**
* \brief Function to get length of the next frame in the receive buffers
*
* \return the length of the next frame in the receive buffers.
*/
extern unsigned long ulMACBInputLength(void);
extern unsigned long ulMACBInputLength(void);
/**
* \brief Set the MACB Physical address (SA1B & SA1T registers).
*
* \param *MACAddress the MAC address to set.
*/
extern void vMACBSetMACAddress(const unsigned char *MACAddress);
extern void vMACBSetMACAddress(const unsigned char *MACAddress);
/**
* \brief Disable MACB operations (Tx and Rx).
*
* \param *macb Base address of the MACB
*/
extern void vDisableMACBOperations(volatile avr32_macb_t *macb);
extern void vDisableMACBOperations(volatile avr32_macb_t *macb);
#endif

View File

@ -57,6 +57,54 @@ 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
@ -71,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,
@ -176,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
@ -233,7 +224,6 @@ int platform_init()
pwm_init();
#endif
#ifdef BUILD_UIP
platform_ethernet_setup();
#endif
@ -248,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
@ -399,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;
@ -490,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 )
@ -529,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;
@ -547,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;
@ -580,13 +584,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();
}
// ****************************************************************************
@ -637,10 +683,8 @@ u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigne
// 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 )
@ -716,6 +760,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;
@ -744,7 +790,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;
@ -758,9 +803,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 )
@ -780,11 +822,7 @@ __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 );
@ -829,6 +867,11 @@ int platform_adc_start_sequence( )
#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 =
{
#if ( BOARD == ATEVK1100 ) || ( BOARD == MIZAR32 )
@ -838,7 +881,7 @@ static const gpio_map_t pwm_pins =
{ 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
// { 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
@ -846,7 +889,7 @@ static const gpio_map_t pwm_pins =
{ 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
// { AVR32_PWM_6_0_PIN, AVR32_PWM_6_0_FUNCTION }, // PA22 - LED3 and audio out
#endif
};
@ -874,27 +917,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;
}
/*
@ -905,18 +943,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 )
{
@ -926,6 +964,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 ) );
@ -945,12 +984,11 @@ static void find_clock_configuration( u32 frequency,
}
#undef prescalers
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();
@ -1099,7 +1137,23 @@ u32 platform_eth_get_elapsed_time()
return 0;
}
#endif
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

View File

@ -7,6 +7,8 @@
#include "board.h"
#include "stacks.h"
#define PLATFORM_HAS_SYSTIMER
#if BOARD == EVK1100
#include "EVK1100/evk1100_conf.h"
#elif BOARD == EVK1101

View File

@ -12,6 +12,7 @@
#include <avr32/io.h>
#include "usart.h"
#include "intc.h"
#include "tc.h"
// ****************************************************************************
// Interrupt handlers
@ -56,6 +57,55 @@ __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 );
}
// ****************************************************************************
// Interrupt: INT_UART_RX
@ -86,11 +136,42 @@ 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 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 };
void platform_int_init()
{
@ -98,7 +179,9 @@ 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 );
Enable_global_interrupt();
}
@ -108,7 +191,9 @@ 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 }
};
#endif // #if defined( BUILD_C_INT_HANDLERS ) || defined( BUILD_LUA_INT_HANDLERS )

View File

@ -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
}

View File

@ -72,18 +72,6 @@ typedef union
avr32_spi_csr0_t CSR;
} u_avr32_spi_csr_t;
//! @}
/*-----------------------------------------------------------*/
static int getBaudDiv(const spi_options_t *options, U32 pba_hz)
{
int baudDiv = (pba_hz + options->baudrate / 2) / options->baudrate;
if (baudDiv <= 0 || baudDiv > 255) {
return -1;
}
return baudDiv;
}
/*-----------------------------------------------------------*/
void spi_reset(volatile avr32_spi_t *spi)
{
@ -98,14 +86,15 @@ int spi_initMaster(volatile avr32_spi_t *spi, const spi_master_options_t *opt, U
spi->cr = AVR32_SPI_CR_SWRST_MASK;
// Master Mode.
// The mode register's reset state is all 0s, so omit 0 values.
u_avr32_spi_mr.mr = spi->mr;
u_avr32_spi_mr.MR.dlybcs = opt->delay*(pba_hz/1000000UL);
u_avr32_spi_mr.MR.pcs = (1 << AVR32_SPI_MR_PCS_SIZE) - 1;
u_avr32_spi_mr.MR.llb = 0;
//u_avr32_spi_mr.MR.llb = 0;
u_avr32_spi_mr.MR.modfdis = opt->modfdis;
//u_avr32_spi_mr.MR.fdiv = 0;
u_avr32_spi_mr.MR.pcsdec = opt->pcs_decode;
u_avr32_spi_mr.MR.ps = 0;
//u_avr32_spi_mr.MR.ps = 0;
u_avr32_spi_mr.MR.mstr = 1;
spi->mr = u_avr32_spi_mr.mr;
@ -116,20 +105,29 @@ int spi_initMaster(volatile avr32_spi_t *spi, const spi_master_options_t *opt, U
return 0;
}
/*-----------------------------------------------------------*/
int spi_setupChipReg(volatile avr32_spi_t *spi,
// Changed for eLua not to set clock frequencies higher than requested
// and to return the actual baud rate that was set.
U32 spi_setupChipReg(volatile avr32_spi_t *spi,
unsigned char reg, const spi_options_t *options, U32 pba_hz)
{
u_avr32_spi_csr_t u_avr32_spi_csr;
U32 baudDiv;
if (options->mode > 3 ||
options->bits < 8 || options->bits > 16) {
return -1;
return 0;
}
int baudDiv = getBaudDiv(options, pba_hz);
if (baudDiv < 0)
return -1;
// Use a frequency less than or equal to that requested, not the nearest
// available one, to avoid driving devices over their maximum speeds.
// A frequency less than or equal needs a divisor greater than or equal,
// and this formula cannot give a result of 0, so no need to check for it.
// Well, unless pba_hz is passed as 0...
if (options->baudrate == 0) baudDiv = 255;
else {
baudDiv = (pba_hz + options->baudrate - 1) / options->baudrate;
if (baudDiv > 255) baudDiv = 255;
}
// Will use CSR0 offsets; these are the same for CSR0 to CSR3.
u_avr32_spi_csr.csr = 0;
@ -155,10 +153,11 @@ int spi_setupChipReg(volatile avr32_spi_t *spi,
spi->csr3 = u_avr32_spi_csr.csr;
break;
default:
return -1;
return 0; // Cannot happen in eLua
}
return 0;
// Return the nearest integer to the actual baud rate
return (pba_hz + baudDiv/2) / baudDiv;
}
/*-----------------------------------------------------------*/
int spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip)
@ -170,7 +169,7 @@ int spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip)
// The signal is decoded; allow up to 15 chips.
if (chip > 14) goto err;
spi->mr &= ~AVR32_SPI_MR_PCS_MASK | (chip << AVR32_SPI_MR_PCS_OFFSET);
}else {
} else {
if (chip > 3) goto err;
spi->mr &= ~(1 << (AVR32_SPI_MR_PCS_OFFSET + chip));
}

View File

@ -49,7 +49,7 @@ typedef struct
extern void spi_reset(volatile avr32_spi_t *spi);
extern int spi_initMaster(volatile avr32_spi_t *spi, const spi_master_options_t *, U32 pba_hz);
extern int spi_setupChipReg(volatile avr32_spi_t *spi, unsigned char chip, const spi_options_t *, U32 pba_hz);
extern U32 spi_setupChipReg(volatile avr32_spi_t *spi, unsigned char chip, const spi_options_t *, U32 pba_hz);
extern int spi_selectChip(volatile avr32_spi_t *spi, unsigned char chip);
extern int spi_unselectChip(volatile avr32_spi_t *spi, unsigned char chip);

View File

@ -130,8 +130,6 @@ typedef struct dhcpc_state uip_udp_appstate_t;
#define UIP_UDP_APPCALL elua_uip_udp_appcall
#endif
// Added for eLua: DHCP TIMER ID
#define ELUA_DHCP_TIMER_ID 1
#define CLOCK_SECOND 1000000UL
#endif // __UIP_CONF_H_

View File

@ -67,7 +67,7 @@ static void scr_write( int fd, char c )
monitor_put( c );
}
static int kb_read( s32 to )
static int kb_read( timer_data_type to )
{
int res;
@ -150,7 +150,7 @@ void platform_s_uart_send( unsigned id, u8 data )
{
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
return -1;
}
@ -163,11 +163,11 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
// ****************************************************************************
// "Dummy" timer functions
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
}
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 )
{
return 0;
}

View File

@ -46,7 +46,7 @@
#define NUM_ADC 0
#define NUM_CAN 0
// 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 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)

View File

@ -138,6 +138,10 @@ int platform_init()
usb_init();
#endif
// Setup system timer
cmn_systimer_set_base_freq( MAP_SysCtlClockGet() );
cmn_systimer_set_interrupt_freq( SYSTICKHZ );
// Setup ethernet (TCP/IP)
eth_init();
@ -496,7 +500,7 @@ void platform_s_uart_send( unsigned id, u8 data )
MAP_UARTCharPut( uart_base[ id ], data );
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
u32 base = uart_base[ id ];
@ -531,7 +535,7 @@ static void timers_init()
}
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
timer_data_type final;
u32 base = timer_base[ id ];
@ -541,7 +545,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( MAP_TimerValueGet( base, TIMER_A ) > 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;
u32 base = timer_base[ id ];
@ -572,10 +576,34 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
res = MAP_SysCtlClockGet();
break;
case PLATFORM_TIMER_OP_GET_MAX_CNT:
res = 0xFFFFFFFF;
break;
}
return res;
}
u64 platform_timer_sys_raw_read()
{
return MAP_SysTickPeriodGet() - 1 - MAP_SysTickValueGet();
}
void platform_timer_sys_disable_int()
{
MAP_SysTickIntDisable();
}
void platform_timer_sys_enable_int()
{
MAP_SysTickIntEnable();
}
timer_data_type platform_timer_read_sys()
{
return cmn_systimer_get();
}
// ****************************************************************************
// PWMs
// Similar on LM3S8962 and LM3S6965
@ -1063,16 +1091,15 @@ void SysTickIntHandler()
// Handle virtual timers
cmn_virtual_timer_cb();
#ifdef BUILD_MMCFS
disk_timerproc();
#endif
// 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();
// System timer handling
cmn_systimer_periodic();
}
void EthernetIntHandler()
@ -1093,9 +1120,8 @@ void SysTickIntHandler()
{
cmn_virtual_timer_cb();
#ifdef BUILD_MMCFS
disk_timerproc();
#endif
// System timer handling
cmn_systimer_periodic();
}
void EthernetIntHandler()

View File

@ -37,12 +37,13 @@
//#endif
#define BUILD_C_INT_HANDLERS
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
#define CON_UART_ID CDC_UART_ID
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -205,13 +206,8 @@
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// SD/MMC Filesystem Setup
#define MMCFS_TICK_HZ 4
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
#if defined( ELUA_BOARD_EKLM3S6965 )
// EK-LM3S6965
#define MMCFS_CS_PORT 3
@ -238,7 +234,7 @@
#endif
// 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 SysCtlClockGet()
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)

View File

@ -150,8 +150,6 @@ typedef struct dhcpc_state uip_udp_appstate_t;
#define UIP_UDP_APPCALL elua_uip_udp_appcall
#endif
// Added for eLua: DHCP TIMER ID
#define ELUA_DHCP_TIMER_ID 1
#define CLOCK_SECOND 1000000UL
#endif // __UIP_CONF_H_

View File

@ -28,6 +28,8 @@
#include "lpc17xx_pwm.h"
#include "lpc17xx_adc.h"
#define SYSTICKHZ 10
// ****************************************************************************
// Platform initialization
@ -66,12 +68,35 @@ int platform_init()
platform_setup_adcs();
#endif
// System timer setup
cmn_systimer_set_base_freq( mbed_get_cpu_frequency() );
cmn_systimer_set_interrupt_freq( SYSTICKHZ );
// Enable SysTick
SysTick_Config( mbed_get_cpu_frequency() / SYSTICKHZ );
// Common platform initialization code
cmn_platform_init();
return PLATFORM_OK;
}
extern u32 SystemCoreClock;
u32 mbed_get_cpu_frequency()
{
return SystemCoreClock;
}
// SysTick interrupt handler
void SysTick_Handler()
{
// Handle virtual timers
cmn_virtual_timer_cb();
// Handle system timer call
cmn_systimer_periodic();
}
// ****************************************************************************
// PIO section
@ -79,7 +104,6 @@ int platform_init()
pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
{
pio_type retval = 1;
u32 idx = 0;
switch( op )
{
@ -134,11 +158,10 @@ pio_type platform_pio_op( unsigned port, pio_type pinmask, int op )
// The other UARTs have assignable Rx/Tx pins and thus have to be configured
// by the user
static LPC_UART_TypeDef *uart[] = { LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3 };
static LPC_UART_TypeDef* const uart[] = { LPC_UART0, LPC_UART1, LPC_UART2, LPC_UART3 };
u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int stopbits )
{
u32 temp;
// UART Configuration structure variable
UART_CFG_Type UARTConfigStruct;
// UART FIFO configuration Struct variable
@ -214,7 +237,7 @@ void platform_s_uart_send( unsigned id, u8 data )
UART_Send(uart[ id ], &data, 1, BLOCKING);
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
u8 buffer;
@ -279,7 +302,7 @@ static void platform_setup_timers()
platform_timer_set_clock( i, 1000000ULL );
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
u32 last;
@ -289,7 +312,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( tmr[ id ]->TC < last );
}
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;
@ -319,10 +342,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 = 0xFFFFFFFF;
break;
}
return res;
}
u64 platform_timer_sys_raw_read()
{
return SysTick->LOAD - SysTick->VAL;
}
void platform_timer_sys_disable_int()
{
SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}
void platform_timer_sys_enable_int()
{
SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}
timer_data_type platform_timer_read_sys()
{
return cmn_systimer_get();
}
// *****************************************************************************
// ADC specific functions and variables

View File

@ -5,6 +5,7 @@
#include "auxmods.h"
#include "stacks.h"
#include "type.h"
// *****************************************************************************
// Define here what components you want for this platform
@ -18,12 +19,13 @@
#define BUILD_SEMIFS
#define BUILD_RPC
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -102,10 +104,10 @@
// RPC
#define RPC_UART_ID CON_UART_ID
#define RPC_TIMER_ID CON_TIMER_ID
// CPU frequency (needed by the CPU module, 0 if not used)
#define CPU_FREQUENCY 100000000
u32 mbed_get_cpu_frequency();
#define CPU_FREQUENCY mbed_get_cpu_frequency()
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX '0'

View File

@ -387,7 +387,7 @@ void platform_s_uart_send( unsigned id, u8 data )
*UxTHR = data;
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
PREG UxLSR = ( PREG )uart_lsr[ id ];
PREG UxRBR = ( PREG )uart_rbr[ id ];
@ -452,14 +452,13 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
return Fpclk / div;
}
#if VTMR_NUM_TIMERS > 0
static void int_handler_tmr()
{
T3IR = 1; // clear interrupt
cmn_virtual_timer_cb();
cmn_virtual_timer_cb(); // handle virtual timers if they're present
cmn_systimer_periodic(); // handle the system timer
VICVectAddr = 0; // ACK interrupt
}
#endif
// Helper function: setup timers
static void platform_setup_timers()
@ -474,9 +473,13 @@ static void platform_setup_timers()
*TxTCR = 0;
platform_timer_set_clock( i, 1000000ULL );
}
#if VTMR_NUM_TIMERS > 0
// Setup virtual timers here
// Timer 3 is allocated for virtual timers and nothing else in this case
// Setup system timer
cmn_systimer_set_base_freq( 1000000 );
cmn_systimer_set_interrupt_freq( VTMR_FREQ_HZ );
// Setup virtual timers / system timer here
// Timer 3 is allocated for virtual timers and the system timer, nothing else
T3TCR = TMR_RESET;
T3MR0 = 1000000ULL / VTMR_FREQ_HZ - 1;
T3IR = 0xFF;
@ -486,10 +489,9 @@ static void platform_setup_timers()
platform_cpu_set_global_interrupts( PLATFORM_CPU_ENABLE );
// Start timer
T3TCR = TMR_ENABLE;
#endif
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
PREG TxTCR = ( PREG )tmr_tcr[ id ];
PREG TxTC = ( PREG )tmr_tc[ id ];
@ -501,7 +503,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( *TxTC < last );
}
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;
PREG TxTCR = ( PREG )tmr_tcr[ id ];
@ -533,15 +535,39 @@ 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 = 0xFFFFFFFF;
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;
}
u64 platform_timer_sys_raw_read()
{
return T3TC;
}
void platform_timer_sys_disable_int()
{
T3MCR = 0x02; // clear on match, no interrupt
}
void platform_timer_sys_enable_int()
{
T3MCR = 0x03; // interrupt on match with MR0 and clear on match
}
timer_data_type platform_timer_read_sys()
{
return cmn_systimer_get();
}
// *****************************************************************************
// ADC specific functions and variables

View File

@ -20,18 +20,19 @@
#define BUILD_CON_GENERIC
#define BUILD_ADC
#define BUILD_RPC
#define BUILD_RFS
#define BUILD_SERMUX
//#define BUILD_RFS
//#define BUILD_SERMUX
#define BUILD_LUA_INT_HANDLERS
#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
@ -75,6 +76,7 @@
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
// NOTE: DON'T define VTMR_FREQ_HZ as 0!
#define VTMR_FREQ_HZ 4
// Number of resources (0 if not available/not implemented)
@ -108,10 +110,9 @@
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// 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 Fcclk
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
@ -123,9 +124,9 @@
#define PIO_PINS_PER_PORT 32
// Remote file system data
/*
#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
@ -133,6 +134,7 @@
#define SERMUX_PHYS_SPEED 115200
#define SERMUX_NUM_VUART 2
#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
*/
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)

View File

@ -118,7 +118,7 @@ void platform_s_uart_send( unsigned id, u8 data )
uart_write( data );
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
if( timeout == 0 )
{
@ -160,7 +160,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
return MAIN_CLOCK / tmr_prescale[ mini ];
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
u32 freq;
u64 final;
@ -177,7 +177,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( ( INT_PENDING & mask ) == 0 );
}
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;
@ -209,6 +209,10 @@ 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 = 0xFFFFFFFF;
break;
}
return res;
}

View File

@ -46,7 +46,7 @@
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// 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 Fcclk
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)

View File

@ -1,11 +1,12 @@
#include "host.h"
#define __NR_read 3
#define __NR_write 4
#define __NR_mmap2 192
#define __NR_exit 1
#define __NR_open 5
#define __NR_close 6
#define __NR_read 3
#define __NR_write 4
#define __NR_mmap2 192
#define __NR_exit 1
#define __NR_open 5
#define __NR_close 6
#define __NR_gettimeofday 78
int host_errno = 0;
@ -27,6 +28,16 @@ __asm__ volatile ("int $0x80" \
__syscall_return(type,__res); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
type host_##name(type1 arg1,type2 arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
__syscall_return(type,__res); \
}
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
type host_##name(type1 arg1,type2 arg2,type3 arg3) \
@ -58,4 +69,5 @@ _syscall3(int, open, const char*, pathname, int, flags, mode_t, mode);
_syscall6(void *,mmap2, void *,addr, size_t, length, int, prot, int, flags, int, fd, off_t, offset);
_syscall1(void, exit, int, status);
_syscall1(int, close, int, status);
_syscall2(int, gettimeofday, struct timeval*, tv, struct timezone*, tz);

View File

@ -5,6 +5,7 @@
#include <stddef.h>
#include <sys/types.h>
#include <sys/time.h>
extern int host_errno;
@ -30,6 +31,7 @@ int host_close( int fd );
#define MAP_FAILED (void *)(-1)
void *host_mmap2(void *addr, size_t length, int prot, int flags, int fd, off_t pgoffset);
int host_gettimeofday( struct timeval *tv, struct timezone *tz );
void host_exit(int status);
#endif // _HOST_H

View File

@ -3,6 +3,8 @@
#ifndef __HOSTIO_H__
#define __HOSTIO_H__
#include "type.h"
// Write a single character out to the screen.
void hostif_putc(char c);
@ -30,5 +32,8 @@ int hostif_write( int fd, const void *buf, unsigned count );
// Close
int hostif_close( int fd );
// Get time
s64 hostif_gettime();
#endif // __HOSTIO_H__

View File

@ -3,6 +3,7 @@
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include "term.h"
#include "host.h"
#include "hostif.h"
@ -64,3 +65,11 @@ int hostif_close( int fd )
return host_close( fd );
}
s64 hostif_gettime()
{
struct timeval tv;
host_gettimeofday( &tv, NULL );
return ( s64 )tv.tv_sec * 1000000 + tv.tv_usec;
}

View File

@ -69,7 +69,7 @@ static void scr_write( int fd, char c )
hostif_putc( c );
}
static int kb_read( s32 to )
static int kb_read( timer_data_type to )
{
int res;
@ -132,7 +132,7 @@ void platform_s_uart_send( unsigned id, u8 data )
{
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
return -1;
}
@ -145,15 +145,20 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
// ****************************************************************************
// "Dummy" timer functions
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
}
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 )
{
return 0;
}
timer_data_type platform_timer_read_sys()
{
return hostif_gettime();
}
// ****************************************************************************
// "Dummy" CPU functions

View File

@ -20,6 +20,8 @@
#define TERM_LINES 25
#define TERM_COLS 80
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// Auxiliary libraries that will be compiled for this platform
@ -27,12 +29,12 @@
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
// Bogus defines for common.c
#define CON_UART_ID 0
#define CON_UART_SPEED 0
#define CON_TIMER_ID 0
// *****************************************************************************
// Configuration data
@ -49,7 +51,7 @@
#define NUM_ADC 0
#define NUM_CAN 0
// 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 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)

View File

@ -82,6 +82,10 @@ int platform_init()
// Setup CANs
cans_init();
// Setup system timer
cmn_systimer_set_base_freq( HCLK );
cmn_systimer_set_interrupt_freq( SYSTICKHZ );
// Enable SysTick
if ( SysTick_Config( HCLK / SYSTICKHZ ) )
@ -638,7 +642,7 @@ void platform_s_uart_send( unsigned id, u8 data )
USART_SendData(stm32_usart[id], data);
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
if( timeout == 0 )
{
@ -695,7 +699,7 @@ int platform_s_uart_set_flow_control( unsigned id, int type )
u8 stm32_timer_int_periodic_flag[ NUM_PHYS_TIMER ];
// We leave out TIM6/TIM for now, as they are dedicated
const TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
TIM_TypeDef * const timer[] = { TIM1, TIM2, TIM3, TIM4, TIM5 };
#define TIM_GET_PRESCALE( id ) ( ( id ) == 0 || ( id ) == 5 ? ( PCLK2_DIV ) : ( PCLK1_DIV ) )
#define TIM_GET_BASE_CLK( id ) ( TIM_GET_PRESCALE( id ) == 1 ? ( HCLK / TIM_GET_PRESCALE( id ) ) : ( HCLK / ( TIM_GET_PRESCALE( id ) / 2 ) ) )
#define TIM_STARTUP_CLOCK 50000
@ -707,9 +711,8 @@ void SysTick_Handler( void )
// Handle virtual timers
cmn_virtual_timer_cb();
#ifdef BUILD_MMCFS
disk_timerproc();
#endif
// Handle system timer call
cmn_systimer_periodic();
}
static void timers_init()
@ -752,7 +755,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
return TIM_GET_BASE_CLK( id ) / ( pre + 1 );
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
TIM_TypeDef *ptimer = timer[ id ];
volatile unsigned dummy;
@ -764,7 +767,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( TIM_GetCounter( ptimer ) < 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;
TIM_TypeDef *ptimer = timer[ id ];
@ -798,11 +801,14 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
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 )
{
TIM_TypeDef* base = ( TIM_TypeDef* )timer[ id ];
u32 period, prescaler, freq;
@ -854,6 +860,26 @@ int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type )
return PLATFORM_TIMER_INT_OK;
}
u64 platform_timer_sys_raw_read()
{
return SysTick->LOAD - SysTick->VAL;
}
void platform_timer_sys_disable_int()
{
SysTick->CTRL &= ~( 1 << SYSTICK_TICKINT );
}
void platform_timer_sys_enable_int()
{
SysTick->CTRL |= 1 << SYSTICK_TICKINT;
}
timer_data_type platform_timer_read_sys()
{
return cmn_systimer_get();
}
// ****************************************************************************
// Quadrature Encoder Support (uses timers)
// No pin configuration, many of the timers should work with default config if

View File

@ -31,12 +31,13 @@
#define BUILD_LUA_INT_HANDLERS
#define ENABLE_ENC
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -132,7 +133,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
@ -140,8 +140,6 @@
// MMCFS Support (FatFs on SD/MMC)
// For STM32F103RET6 - PA5 = CLK, PA6 = MISO, PA7 = MOSI, PA8 = CS
#define MMCFS_TICK_HZ 10
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
#define MMCFS_CS_PORT 0
#define MMCFS_CS_PIN 8
#define MMCFS_SPI_NUM 0
@ -161,7 +159,6 @@ u32 platform_s_cpu_get_frequency();
// Remote file system data
#define RFS_BUFFER_SIZE BUF_SIZE_512
#define RFS_UART_ID 0
#define RFS_TIMER_ID 0
#define RFS_TIMEOUT 100000
#define RFS_UART_SPEED 115200

View File

@ -150,8 +150,6 @@ typedef struct dhcpc_state uip_udp_appstate_t;
#define UIP_UDP_APPCALL elua_uip_udp_appcall
#endif
// Added for eLua: DHCP TIMER ID
#define ELUA_DHCP_TIMER_ID 1
#define CLOCK_SECOND 1000000UL
#endif // __UIP_CONF_H_

View File

@ -180,7 +180,7 @@ void platform_s_uart_send( unsigned id, u8 data )
UART_ByteSend( pport, &data );
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
UART_TypeDef* pport = ( UART_TypeDef* )uart_periph[ id ];
@ -232,7 +232,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
return baseclk / bestdiv;
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
TIM_TypeDef* ptimer = ( TIM_TypeDef* )tim_periph[ id ];
u32 freq;
@ -253,7 +253,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( TIM_CounterValue( ptimer ) < 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;
TIM_TypeDef* ptimer = ( TIM_TypeDef* )tim_periph[ id ];
@ -290,6 +290,10 @@ 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;
}
@ -338,7 +342,5 @@ void platform_pwm_start( unsigned id )
void platform_pwm_stop( unsigned id )
{
TIM_TypeDef *ptimer = ( TIM_TypeDef* )tim_periph[ id + 1 ];
platform_pio_op( pwm_ports[ id ], pwm_pins[ id ], PLATFORM_IO_PIN_DIR_INPUT );
}

View File

@ -73,7 +73,7 @@
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// 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 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)

View File

@ -93,6 +93,8 @@ void ARMRX_IRQHandler(void)
void ARMTX_IRQHandler(void)
{
}
#if 0
/*******************************************************************************
* Function Name : TIM0_IRQHandler
* Description : This function handles the TIM0 interrupt request
@ -121,6 +123,8 @@ void TIM2_IRQHandler(void)
void TIM3_IRQHandler(void)
{
}
#endif
/*******************************************************************************
* Function Name : USBHP_IRQHandler
* Description : This function handles the USBHP interrupt request

View File

@ -30,8 +30,16 @@
// ****************************************************************************
// Platform initialization
const GPIO_TypeDef* port_data[] = { GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7, GPIO8, GPIO9 };
#ifndef VTMR_TIMER_ID
#error Define VTMR_TIMER_ID to the ID of the timer used for the system timer
#endif
const TIM_TypeDef* str9_timer_data[] = { TIM0, TIM1, TIM2, TIM3 };
// System timer implementation on STR9 uses one of the physical timers (defined by
// VTMR_TIMER_ID). This is the same timer used for VTMR implementation. Its base
// frequency is set to 1MHz in platform_s_timer_set_match_int. It runs at 16Hz
// since this gives an exact number of microseconds (62500) before its overflow.
static void platform_setup_adcs();
static void platform_config_scu()
@ -158,10 +166,11 @@ int platform_init()
// Setup ADCs
platform_setup_adcs();
#endif
#ifdef VTMR_TIMER_ID
// Initialize system timer
cmn_systimer_set_base_freq( 1000000 );
cmn_systimer_set_interrupt_freq( VTMR_FREQ_HZ );
platform_s_timer_set_match_int( VTMR_TIMER_ID, 1000000 / VTMR_FREQ_HZ, PLATFORM_TIMER_INT_CYCLIC );
#endif
return PLATFORM_OK;
}
@ -280,7 +289,7 @@ void platform_s_uart_send( unsigned id, u8 data )
while( UART_GetFlagStatus( p_uart, UART_FLAG_TxFIFOFull ) != RESET );
}
int platform_s_uart_recv( unsigned id, s32 timeout )
int platform_s_uart_recv( unsigned id, timer_data_type timeout )
{
UART_TypeDef* p_uart = ( UART_TypeDef* )uarts[ id ];
@ -329,7 +338,7 @@ static u32 platform_timer_set_clock( unsigned id, u32 clock )
return baseclk / bestdiv;
}
void platform_s_timer_delay( unsigned id, u32 delay_us )
void platform_s_timer_delay( unsigned id, timer_data_type delay_us )
{
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ id ];
u32 freq;
@ -350,7 +359,7 @@ void platform_s_timer_delay( unsigned id, u32 delay_us )
while( TIM_GetCounterValue( base ) < 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;
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ id ];
@ -383,11 +392,15 @@ 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 )
{
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ id ];
u32 freq;
@ -428,6 +441,32 @@ int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type )
return PLATFORM_TIMER_INT_OK;
}
u64 platform_timer_sys_raw_read()
{
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ VTMR_TIMER_ID ];
return TIM_GetCounterValue( base );
}
void platform_timer_sys_enable_int()
{
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ VTMR_TIMER_ID ];
TIM_ITConfig( base, TIM_IT_OC1, ENABLE );
}
void platform_timer_sys_disable_int()
{
TIM_TypeDef* base = ( TIM_TypeDef* )str9_timer_data[ VTMR_TIMER_ID ];
TIM_ITConfig( base, TIM_IT_OC1, DISABLE );
}
timer_data_type platform_timer_read_sys()
{
return cmn_systimer_get();
}
// *****************************************************************************
// ADC specific functions and variables
@ -830,36 +869,79 @@ u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigne
divider = temp / prescaler;
}
// GPIO setup
// Fixed assignment:
// P5.4 - SCLK
// P5.5 - MOSI
// P5.6 - MISO
// P5.7 - CS (not explicitly handled by the SPI module)
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2 ;
GPIO_Init(GPIO5, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1 ;
GPIO_Init(GPIO5, &GPIO_InitStructure);
if ( id == 0 )
{
// GPIO setup
// Fixed assignment:
// P5.4 - SCLK
// P5.5 - MOSI
// P5.6 - MISO
// P5.7 - CS
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2;
GPIO_Init(GPIO5, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1 ;
GPIO_Init(GPIO5, &GPIO_InitStructure);
// Actual SPI setup
SSP_DeInit(SSP0);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPOL = cpol == 0 ? SSP_CPOL_Low : SSP_CPOL_High;
SSP_InitStructure.SSP_CPHA = cpha == 0 ? SSP_CPHA_1Edge : SSP_CPHA_2Edge;
SSP_InitStructure.SSP_DataSize = databits - 1;
SSP_InitStructure.SSP_ClockRate = divider - 1;
SSP_InitStructure.SSP_ClockPrescaler = prescaler;
SSP_Init(SSP0, &SSP_InitStructure);
// Actual SPI setup
SSP_DeInit(SSP0);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPOL = cpol == 0 ? SSP_CPOL_Low : SSP_CPOL_High;
SSP_InitStructure.SSP_CPHA = cpha == 0 ? SSP_CPHA_1Edge : SSP_CPHA_2Edge;
SSP_InitStructure.SSP_DataSize = databits - 1;
SSP_InitStructure.SSP_ClockRate = divider - 1;
SSP_InitStructure.SSP_ClockPrescaler = prescaler;
SSP_Init(SSP0, &SSP_InitStructure);
// Enable peripheral
SSP_Cmd(SSP0, ENABLE);
// Enable peripheral
SSP_Cmd(SSP0, ENABLE);
}
else if ( id == 1 )
{
// GPIO setup
// Fixed assignment:
// P1.0 - SCLK
// P1.1 - MOSI
// P1.2 - MISO
// P1.3 - CS
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt3;
GPIO_Init(GPIO1, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt3;
GPIO_Init(GPIO1, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init(GPIO1, &GPIO_InitStructure);
// Actual SPI setup
SSP_DeInit(SSP1);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPOL = cpol == 0 ? SSP_CPOL_Low : SSP_CPOL_High;
SSP_InitStructure.SSP_CPHA = cpha == 0 ? SSP_CPHA_1Edge : SSP_CPHA_2Edge;
SSP_InitStructure.SSP_DataSize = databits - 1;
SSP_InitStructure.SSP_ClockRate = divider - 1;
SSP_InitStructure.SSP_ClockPrescaler = prescaler;
SSP_Init(SSP1, &SSP_InitStructure);
// Enable peripheral
SSP_Cmd(SSP1, ENABLE);
}
// All done
return basefreq / ( prescaler * divider );
@ -867,14 +949,28 @@ u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigne
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
{
// Send byte through the SSP0 peripheral
SSP0->DR = data;
// Loop while Transmit FIFO is full
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_TxFifoEmpty) == RESET);
// Loop while Receive FIFO is empty
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_RxFifoNotEmpty) == RESET);
// Return the byte read from the SSP bus
return SSP0->DR;
if (id == 0)
{
// Send byte through the SSP0 peripheral
SSP0->DR = data;
// Loop while Transmit FIFO is full
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_TxFifoEmpty) == RESET);
// Loop while Receive FIFO is empty
while(SSP_GetFlagStatus(SSP0, SSP_FLAG_RxFifoNotEmpty) == RESET);
// Return the byte read from the SSP bus
return SSP0->DR;
}
else
{
// Send byte through the SSP1 peripheral
SSP1->DR = data;
// Loop while Transmit FIFO is full
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) == RESET);
// Loop while Receive FIFO is empty
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_RxFifoNotEmpty) == RESET);
// Return the byte read from the SSP bus
return SSP1->DR;
}
}
void platform_spi_select( unsigned id, int is_select )

View File

@ -22,6 +22,8 @@
#define BUILD_LUA_INT_HANDLERS
#define BUILD_C_INT_HANDLERS
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
@ -32,7 +34,6 @@
#endif
#define CON_UART_SPEED 115200
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@ -41,23 +42,20 @@
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
#define VTMR_FREQ_HZ 10
#define VTMR_TIMER_ID 2
#define VTMR_FREQ_HZ 16
#define VTMR_TIMER_ID 3
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 10
#define NUM_SPI 1
#define NUM_SPI 2
#define NUM_UART 3
#define NUM_PWM 4
#define NUM_ADC 8
#define NUM_CAN 0
#define NUM_I2C 2
#ifdef VTMR_TIMER_ID
// One timer is reserved for the system timer / vtimers
#define NUM_TIMER 3
#else
#define NUM_TIMER 4
#endif
#define NUM_PHYS_TIMER 4
// ADC Configuration Params
@ -71,13 +69,12 @@
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// Interrupt queue configuration
#define PLATFORM_INT_QUEUE_LOG_SIZE BUF_SIZE_32
// 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)
u32 SCU_GetMCLKFreqValue();
#define CPU_FREQUENCY ( SCU_GetMCLKFreqValue() * 1000 )

View File

@ -121,7 +121,10 @@ static void tmr_int_handler( int id )
TIM_ClearFlag( base, TIM_FLAG_OC1 );
TIM_CounterCmd( base, TIM_CLEAR );
if( id == VTMR_TIMER_ID )
{
cmn_virtual_timer_cb();
cmn_systimer_periodic();
}
else
cmn_int_handler( INT_TMR_MATCH, id );
if( str9_timer_int_periodic_flag[ id ] != PLATFORM_TIMER_INT_CYCLIC )

View File

@ -5,7 +5,7 @@
#include "client.h"
#include "os_io.h"
#include "eluarpc.h"
#include "platform.h"
#include <stdio.h>
#include "platform_conf.h"
#include "buf.h"
@ -26,7 +26,7 @@ void RFSDEBUG( const char* dummy, ... )
static u8 *rfsc_buffer;
static p_rfsc_send rfsc_send;
static p_rfsc_recv rfsc_recv;
static u32 rfsc_timeout;
static timer_data_type rfsc_timeout;
// ****************************************************************************
// Client helpers
@ -76,7 +76,7 @@ static int rfsch_send_request_read_response()
// ****************************************************************************
// Client public interface
void rfsc_setup( u8 *pbuf, p_rfsc_send rfsc_send_func, p_rfsc_recv rfsc_recv_func, u32 timeout )
void rfsc_setup( u8 *pbuf, p_rfsc_send rfsc_send_func, p_rfsc_recv rfsc_recv_func, timer_data_type timeout )
{
rfsc_buffer = pbuf;
rfsc_send = rfsc_send_func;
@ -84,7 +84,7 @@ void rfsc_setup( u8 *pbuf, p_rfsc_send rfsc_send_func, p_rfsc_recv rfsc_recv_fun
rfsc_timeout = timeout;
}
void rfsc_set_timeout( u32 timeout )
void rfsc_set_timeout( timer_data_type timeout )
{
rfsc_timeout = timeout;
}

View File

@ -19,7 +19,11 @@
// [TODO] the new builder should automatically do this
#ifndef RFS_FLOW_TYPE
#define RFS_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#define RFS_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#endif
#ifndef RFS_TIMER_ID
#define RFS_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
// Our RFS buffer
@ -131,7 +135,7 @@ static u32 rfs_send( const u8 *p, u32 size )
return size;
}
static u32 rfs_recv( u8 *p, u32 size, s32 timeout )
static u32 rfs_recv( u8 *p, u32 size, timer_data_type timeout )
{
u32 cnt = 0;
int data;
@ -157,7 +161,7 @@ static u32 rfs_send( const u8 *p, u32 size )
return ( u32 )hostif_write( rfs_write_fd, p, size );
}
static u32 rfs_recv( u8 *p, u32 size, s32 timeout )
static u32 rfs_recv( u8 *p, u32 size, timer_data_type timeout )
{
timeout = timeout;
return ( u32 )hostif_read( rfs_read_fd, p, size );

View File

@ -48,6 +48,10 @@
#define HOSTNAME "elua"
#ifndef ELUA_DHCP_TIMER_ID
#define ELUA_DHCP_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
static struct dhcpc_state s;
struct __attribute((packed)) dhcp_msg {

View File

@ -40,7 +40,7 @@ struct dhcpc_state {
struct pt pt;
char state;
struct uip_udp_conn *conn;
u32 timer_init, ticks;
u64 timer_init, ticks;
const void *mac_addr;
int mac_len;

View File

@ -685,7 +685,12 @@ builder.create_compile_targets = function( self, ftable, res )
target:set_pre_build_function( function( t, _ )
if not self.clean_mode then
local fres = self:read_depends( ftable[ i ] )
t:set_dependencies( fres[ ftable[ i ] ] or ftable[ i ] )
local fdeps = fres[ ftable[ i ] ]
if #fdeps:gsub( "%s+", "" ) == 0 then fdeps = ftable[ i ] end
t:set_dependencies( fdeps )
else
io.write( sf( "[builder] Removing %s ... ", deps ) )
if os.remove( deps ) then print "done." else print "failed!" end
end
end )
end