From d2a4f8dbaf567fb3b7211e836215f6fe50f25cfc Mon Sep 17 00:00:00 2001
From: "naves.thiago"
(the send function gets an additional fd parameter that you can use to differentiate between the standard C stdout and stderr output streams).
-To set them, use std_set_send_func and std_set_get_func, both are defined in inc/newlib/getstd.h. Usually they are called from src/common.c and configured to work +
To set them, use std_set_send_func and std_set_get_func, both are defined in inc/newlib/genstd.h. Usually they are called from src/common.c and configured to work over the UART by default:
// *****************************************************************************
// std functions and platform initialization
From 4b6096a8dc8f5f07d9781d8263e40f1dae4f1015 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Wed, 5 Oct 2011 16:08:45 +0200
Subject: [PATCH 15/80] Sort out declarations of ADC commons and
platform-specific functions
---
inc/platform.h | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/inc/platform.h b/inc/platform.h
index 34f7a4eb..e126d7d8 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -230,21 +230,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
From f386633ec05434ba1830046783bbd6ac6b50a094 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Wed, 5 Oct 2011 23:36:41 +0200
Subject: [PATCH 16/80] Put LUAI_MAXUPVALUES back to Lua 5.1.4 default of 60.
THe MAXUPVALUES was reduced to reduce stack and RAM usage, but turns out
to create incomprehensible erorrs for beginners when they use more than
10 global variables ina function.
This change puts is back tot eh Lua defualt, which uses 100 bytes more
RAM when parsnig functions, or 200 if they have nested functions.
This seems less bad than throwing incomprehensible errors when beginners
code the sort of things that beginners always code.
---
src/lua/luaconf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/lua/luaconf.h b/src/lua/luaconf.h
index 15ad5f90..cad3a2cc 100644
--- a/src/lua/luaconf.h
+++ b/src/lua/luaconf.h
@@ -518,7 +518,7 @@
@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function
@* (must be smaller than 250).
*/
-#define LUAI_MAXUPVALUES 10
+#define LUAI_MAXUPVALUES 60
/*
From f400a45c2f813db5041f3b172f5ca7f7a7383c00 Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Thu, 6 Oct 2011 18:53:43 -0500
Subject: [PATCH 17/80] make adispatch compatible with new model for readable
function
---
src/modules/luarpc.c | 43 +++++--------------------------------------
1 file changed, 5 insertions(+), 38 deletions(-)
diff --git a/src/modules/luarpc.c b/src/modules/luarpc.c
index 3e934343..c2ab891b 100644
--- a/src/modules/luarpc.c
+++ b/src/modules/luarpc.c
@@ -1448,7 +1448,7 @@ static int rpc_peek( lua_State *L )
if ( transport_is_open( &handle->ltpt ) )
{
if ( transport_readable( &handle->ltpt ) )
- lua_pushnumber ( L, 2 ); // testing, was 1
+ lua_pushnumber ( L, 1 );
else
lua_pushnil( L );
@@ -1573,43 +1573,10 @@ static int rpc_dispatch( lua_State *L )
static int rpc_adispatch_helper( lua_State *L, ServerHandle * handle )
{
- int c;
- char connect = 0;
- Transport * t;
-
- t = &handle->atpt;
-
- if ( ! transport_is_open( t ) )
- {
- // if accepting transport is not open, accept a new connection from the
- // listening transport
- transport_accept( &handle->ltpt, &handle->atpt );
- connect = 1;
- }
-
- c = transport_get_char( t );
-
- if ( c < 0 )
- {
- if ( connect ) // Are we connecting ?
- // No connection avaliable, undo accept
- (&handle->atpt)->fd = INVALID_TRANSPORT;
-
- return 0;
- }
-
- if ( connect ) // Are we connecting ?
- {
- // We got a connection
- set_adispatch_buff( c );
- if ( transport_read_u8( &handle->atpt ) == RPC_CMD_CON )
- server_negotiate( &handle->atpt );
-
- return 0;
- }
-
- set_adispatch_buff( c );
- rpc_dispatch_helper( L, 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 ) )
+ rpc_dispatch_helper( L, handle );
return 0;
}
From cc1cda9109bbbc60a50d0be0dec04f7154b06463 Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Thu, 6 Oct 2011 18:59:44 -0500
Subject: [PATCH 18/80] remove some unneeded API extensions, cleanup
---
inc/luarpc_rpc.h | 6 ------
src/luarpc_desktop_serial.c | 18 ------------------
src/luarpc_elua_uart.c | 1 +
src/modules/luarpc.c | 2 --
4 files changed, 1 insertion(+), 26 deletions(-)
diff --git a/inc/luarpc_rpc.h b/inc/luarpc_rpc.h
index 019c1e52..c38c4c28 100644
--- a/inc/luarpc_rpc.h
+++ b/inc/luarpc_rpc.h
@@ -165,9 +165,3 @@ int transport_is_open (Transport *tpt);
// Shut down connection
void transport_close (Transport *tpt);
-
-// Buffer for async dispatch
-void set_adispatch_buff( int i );
-
-// Read a char from serial buffer
-int transport_get_char(Transport *t);
diff --git a/src/luarpc_desktop_serial.c b/src/luarpc_desktop_serial.c
index 5dbc1158..3d8de2fd 100644
--- a/src/luarpc_desktop_serial.c
+++ b/src/luarpc_desktop_serial.c
@@ -21,14 +21,6 @@ void transport_open( Transport *tpt, const char *path );
#ifdef LUARPC_ENABLE_SERIAL
-// Buffer for async dispatch
-int adispatch_buff = -1;
-
-void set_adispatch_buff( int i )
-{
- adispatch_buff = i;
-}
-
// Setup Transport
void transport_init (Transport *tpt)
{
@@ -86,16 +78,6 @@ void transport_accept (Transport *tpt, Transport *atpt)
atpt->fd = tpt->fd;
}
-// Read a char from serial buffer
-int transport_get_char(Transport *t)
-{
- u8 n;
-
- if ( ser_read( t->fd, &n, 1 ) == 0 )
- return 0;
- else
- return (int)n;
-}
// Read & Write to Transport
void transport_read_buffer (Transport *tpt, u8 *buffer, int length)
diff --git a/src/luarpc_elua_uart.c b/src/luarpc_elua_uart.c
index b072d360..bd3c5648 100644
--- a/src/luarpc_elua_uart.c
+++ b/src/luarpc_elua_uart.c
@@ -76,6 +76,7 @@ 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;
diff --git a/src/modules/luarpc.c b/src/modules/luarpc.c
index c2ab891b..483a5bc9 100644
--- a/src/modules/luarpc.c
+++ b/src/modules/luarpc.c
@@ -1143,8 +1143,6 @@ static int rpc_connect( lua_State *L )
handle = handle_create ( L );
transport_open_connection( L, handle );
- set_adispatch_buff( -1 );
-
transport_write_u8( &handle->tpt, RPC_CMD_CON );
client_negotiate( &handle->tpt );
}
From 1892bec9c5529f2b0c395da7e836622e7d72e72d Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Thu, 6 Oct 2011 19:48:37 -0500
Subject: [PATCH 19/80] Correct adispatch functionality when new connection is
needed.
---
src/modules/luarpc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/luarpc.c b/src/modules/luarpc.c
index 483a5bc9..5ddd571b 100644
--- a/src/modules/luarpc.c
+++ b/src/modules/luarpc.c
@@ -1573,7 +1573,7 @@ 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 ) )
+ if( transport_readable( &handle->atpt ) || transport_readable( &handle->ltpt ) )
rpc_dispatch_helper( L, handle );
return 0;
From 64d93f2171df15d291bbd17bfeece5e67f11cccc Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Fri, 7 Oct 2011 01:26:40 -0500
Subject: [PATCH 20/80] Fix typo in adc.getsamples. Should now return table of
values.
---
src/modules/adc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/adc.c b/src/modules/adc.c
index da814671..1c96c9ca 100644
--- a/src/modules/adc.c
+++ b/src/modules/adc.c
@@ -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;
}
From 2fcba014519ab1ecdd94e24fcf390dc3a76539e4 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 7 Oct 2011 13:20:29 +0300
Subject: [PATCH 21/80] Added timer with microsecond resolution in 'sim'
backend
Microsecond-resolution timer for the 'sim' backend using 'gettimeofday'.
Will be used to test the new timer system.
---
src/platform/sim/host.c | 24 ++++++++++++++++++------
src/platform/sim/host.h | 2 ++
src/platform/sim/hostif.h | 5 +++++
src/platform/sim/hostif_linux.c | 9 +++++++++
4 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/src/platform/sim/host.c b/src/platform/sim/host.c
index 561c784c..85403ff0 100644
--- a/src/platform/sim/host.c
+++ b/src/platform/sim/host.c
@@ -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);
diff --git a/src/platform/sim/host.h b/src/platform/sim/host.h
index 7913677d..62369136 100644
--- a/src/platform/sim/host.h
+++ b/src/platform/sim/host.h
@@ -5,6 +5,7 @@
#include
#include
+#include
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
diff --git a/src/platform/sim/hostif.h b/src/platform/sim/hostif.h
index 9b0d0e45..8397748e 100644
--- a/src/platform/sim/hostif.h
+++ b/src/platform/sim/hostif.h
@@ -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__
diff --git a/src/platform/sim/hostif_linux.c b/src/platform/sim/hostif_linux.c
index 2b385f2a..4e797a2d 100644
--- a/src/platform/sim/hostif_linux.c
+++ b/src/platform/sim/hostif_linux.c
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#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 * 1000 + tv.tv_usec;
+}
+
From 7ba13aaf7ebb3a348870d80cc2e17e12087618db Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 7 Oct 2011 17:19:48 +0300
Subject: [PATCH 22/80] build system dependency fix
---
utils/build.lua | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/utils/build.lua b/utils/build.lua
index 08226e38..cd9e2c81 100644
--- a/utils/build.lua
+++ b/utils/build.lua
@@ -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
From a6a9829ff1d29e533589632866c21cdf3b7ab36d Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 7 Oct 2011 17:19:51 +0300
Subject: [PATCH 23/80] Started to modify the timer infrastructure
- added explicit support for the system timer in common_tmr.c
- all the functions in the tmr module will now use the system timer
by default (if no id is specified)
- infinite timeout will be specified by using a special timer ID
rather than using negative timeout values (this allows the timer
data type to be unsigned and increases the timer range)
---
inc/common.h | 1 +
inc/platform.h | 42 +++++++++---
src/common.c | 19 ++++++
src/common_tmr.c | 112 +++++++++++++++++++++++--------
src/modules/tmr.c | 62 ++++++++---------
src/platform/sim/hostif_linux.c | 2 +-
src/platform/sim/platform.c | 9 ++-
src/platform/sim/platform_conf.h | 3 +-
8 files changed, 175 insertions(+), 75 deletions(-)
diff --git a/inc/common.h b/inc/common.h
index e6479535..90f800c6 100644
--- a/inc/common.h
+++ b/inc/common.h
@@ -21,6 +21,7 @@ int cmn_tmr_int_get_flag( elua_int_resnum resnum, int clear );
void cmn_uart_setup_sermux();
unsigned int intlog2( unsigned int v );
+const char* cmn_str64( u64 x );
#endif // #ifndef __COMMON_H__
diff --git a/inc/platform.h b/inc/platform.h
index e126d7d8..26aed7b0 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -155,11 +155,29 @@ 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
+// The ID of the system timer
+#define PLATFORM_TIMER_SYS_ID 0xFFFF
-// Data types
+// The ID of the timer which will be used for infinite timeouts
+// Specifying this timer ID always implies "infinite timeout"
+// This is just a convention, it doesn't have an associated timer
+// (not even a virtual one)
+#define PLATFORM_TIMER_INF_TIMEOUT_ID 0xFFFE
+
+#if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
+// Maximum values of the system timer
+#define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 32 ) - 1 )
+// Timer data type
typedef u32 timer_data_type;
+#else
+// Maximum values of the system timer
+ #define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 52 ) - 1 )
+// Timer data type
+typedef u64 timer_data_type;
+#endif // #if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
+
+// System timer frequency
+#define PLATFORM_TIMER_SYS_FREQ 1000000
// Interrupt types
#define PLATFORM_TIMER_INT_ONESHOT 1
@@ -179,18 +197,20 @@ 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
};
// 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 );
+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 );
+timer_data_type platform_timer_read_sys();
// *****************************************************************************
// PWM subsection
diff --git a/src/common.c b/src/common.c
index 87386d6b..f65d6de3 100644
--- a/src/common.c
+++ b/src/common.c
@@ -8,6 +8,7 @@
#include "buf.h"
#include
#include
+#include
#include
#include "math.h"
#include "elua_adc.h"
@@ -445,3 +446,21 @@ 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;
+}
+
diff --git a/src/common_tmr.c b/src/common_tmr.c
index 5e7b0b7c..9ab7b4d7 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -6,6 +6,7 @@
#include "type.h"
#include "common.h"
#include "elua_int.h"
+#include "utils.h"
#include
// [TODO] when the new build system is ready, automatically add the
@@ -30,6 +31,8 @@ extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ];
#if VTMR_NUM_TIMERS > 0
+#define VTMR_MAX_PERIOD ( ( 1LL << 32 ) - 1 )
+
// ============================================================================
// VTMR functions
@@ -87,23 +90,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;
@@ -173,23 +181,67 @@ 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;
}
-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( 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
+ {
+ 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;
+ break;
+
+ case PLATFORM_TIMER_OP_GET_MAX_CNT:
+ res = PLATFORM_TIMER_SYS_MAX;
+ break;
+
+ case PLATFORM_TIMER_OP_GET_MIN_DELAY:
+ res = 0;
+ 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 +263,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 = VTMX_MAX_PERIOD;
+ break;
case PLATFORM_TIMER_OP_SET_CLOCK:
case PLATFORM_TIMER_OP_GET_CLOCK:
@@ -221,28 +277,17 @@ 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;
+ timer_data_type res;
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;
-
+ if( tstart > tend )
+ tend += platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_CNT, 0 ) + 1;
+ tstart = ( ( tend - tstart ) * 1000000 ) / freq;
+ res = UMIN( tstart, PLATFORM_TIMER_SYS_MAX );
return res;
}
@@ -254,16 +299,21 @@ int platform_timer_set_match_int( unsigned id, u32 period_us, int type )
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 +321,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 +335,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 +349,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;
diff --git a/src/modules/tmr.c b/src/modules/tmr.c
index 1827a40b..574613ad 100644
--- a/src/modules/tmr.c
+++ b/src/modules/tmr.c
@@ -21,100 +21,100 @@ static int tmrh_timer_op( lua_State* L, int op )
unsigned id;
timer_data_type res;
- id = luaL_checkinteger( L, 1 );
+ id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( 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 );
+ period = ( timer_data_type )luaL_checknumber( L, 1 );
+ id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( timer, id );
- period = luaL_checkinteger( L, 2 );
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 );
+ id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( timer, id );
- end = ( timer_data_type )luaL_checkinteger( L, 2 );
- start = ( timer_data_type )luaL_checkinteger( L, 3 );
+ 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: res = getmindelay( [id] )
static int tmr_getmindelay( lua_State* L )
{
- u32 res;
+ timer_data_type res;
unsigned id;
- id = luaL_checkinteger( L, 1 );
+ id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( 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 );
+ id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( 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 );
+ id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( timer, id );
- clock = ( u32 )luaL_checkinteger( L, 2 );
+ 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 );
+ id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( timer, id );
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_CLOCK, 0 );
lua_pushinteger( L, res );
@@ -122,15 +122,15 @@ static int tmr_getclock( lua_State* L )
}
#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 );
+ id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
MOD_CHECK_ID( timer, id );
- res = platform_timer_set_match_int( id, ( u32 )luaL_checknumber( L, 2 ), ( int )luaL_checkinteger( L, 3 ) );
+ res = platform_timer_set_match_int( id, ( timer_data_type )luaL_checknumber( L, 1 ), ( int )luaL_checkinteger( L, 3 ) );
if( res == PLATFORM_TIMER_INT_TOO_SHORT )
return luaL_error( L, "timer interval too small" );
else if( res == PLATFORM_TIMER_INT_TOO_LONG )
diff --git a/src/platform/sim/hostif_linux.c b/src/platform/sim/hostif_linux.c
index 4e797a2d..d12f7907 100644
--- a/src/platform/sim/hostif_linux.c
+++ b/src/platform/sim/hostif_linux.c
@@ -70,6 +70,6 @@ s64 hostif_gettime()
struct timeval tv;
host_gettimeofday( &tv, NULL );
- return ( s64 )tv.tv_sec * 1000 + tv.tv_usec;
+ return ( s64 )tv.tv_sec * 1000000 + tv.tv_usec;
}
diff --git a/src/platform/sim/platform.c b/src/platform/sim/platform.c
index 1132fc96..5d576dd0 100644
--- a/src/platform/sim/platform.c
+++ b/src/platform/sim/platform.c
@@ -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
diff --git a/src/platform/sim/platform_conf.h b/src/platform/sim/platform_conf.h
index ba85a67c..cac38a9b 100644
--- a/src/platform/sim/platform_conf.h
+++ b/src/platform/sim/platform_conf.h
@@ -27,7 +27,8 @@
_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
From f1d105cbb82a7fc4134aecf15e21f0d2225e7c52 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sat, 8 Oct 2011 02:13:53 +0300
Subject: [PATCH 24/80] DHCP timer now defaults to the system timer if not
specified
---
src/platform/avr32/uip-conf.h | 2 --
src/platform/lm3s/uip-conf.h | 2 --
src/platform/stm32/uip-conf.h | 2 --
src/uip/dhcpc.c | 12 ++++++++----
src/uip/dhcpc.h | 2 +-
5 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/platform/avr32/uip-conf.h b/src/platform/avr32/uip-conf.h
index b7a78f0b..87251af5 100644
--- a/src/platform/avr32/uip-conf.h
+++ b/src/platform/avr32/uip-conf.h
@@ -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_
diff --git a/src/platform/lm3s/uip-conf.h b/src/platform/lm3s/uip-conf.h
index 79a14929..32dcb927 100644
--- a/src/platform/lm3s/uip-conf.h
+++ b/src/platform/lm3s/uip-conf.h
@@ -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_
diff --git a/src/platform/stm32/uip-conf.h b/src/platform/stm32/uip-conf.h
index 79a14929..32dcb927 100755
--- a/src/platform/stm32/uip-conf.h
+++ b/src/platform/stm32/uip-conf.h
@@ -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_
diff --git a/src/uip/dhcpc.c b/src/uip/dhcpc.c
index a9df6e4d..189d20c5 100644
--- a/src/uip/dhcpc.c
+++ b/src/uip/dhcpc.c
@@ -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 {
@@ -273,8 +277,8 @@ PT_THREAD(handle_dhcp(void))
do {
send_discover();
- s.timer_init = platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_START, 0 );
- PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_us( ELUA_DHCP_TIMER_ID, s.timer_init, platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_READ, 0 ) ) >= s.ticks );
+ s.timer_init = platform_timer_read( ELUA_DHCP_TIMER_ID );
+ PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_crt( ELUA_DHCP_TIMER_ID, s.timer_init ) >= s.ticks );
if(uip_newdata() && parse_msg() == DHCPOFFER) {
uip_flags &= ~UIP_NEWDATA;
s.state = STATE_OFFER_RECEIVED;
@@ -293,8 +297,8 @@ PT_THREAD(handle_dhcp(void))
do {
send_request();
- s.timer_init = platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_START, 0 );
- PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_us( ELUA_DHCP_TIMER_ID, s.timer_init, platform_timer_op( ELUA_DHCP_TIMER_ID, PLATFORM_TIMER_OP_READ, 0 ) ) >= s.ticks );
+ s.timer_init = platform_timer_read( ELUA_DHCP_TIMER_ID );
+ PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_crt( ELUA_DHCP_TIMER_ID, s.timer_init ) >= s.ticks );
if(uip_newdata() && parse_msg() == DHCPACK) {
uip_flags &= ~UIP_NEWDATA;
diff --git a/src/uip/dhcpc.h b/src/uip/dhcpc.h
index aa8629f5..ee6febff 100644
--- a/src/uip/dhcpc.h
+++ b/src/uip/dhcpc.h
@@ -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;
From ccd3a9bdab395d1ebc4d9617e2445e86c0a8e48e Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sat, 8 Oct 2011 02:40:48 +0300
Subject: [PATCH 25/80] update code to match std_get_func's new signature
---
inc/newlib/genstd.h | 4 ++--
src/common.c | 39 +++++++++++++++++++++++++++++++++---
src/platform/i386/platform.c | 2 +-
src/platform/sim/platform.c | 4 ++--
4 files changed, 41 insertions(+), 8 deletions(-)
diff --git a/inc/newlib/genstd.h b/inc/newlib/genstd.h
index 0c0d2816..5adfade7 100644
--- a/inc/newlib/genstd.h
+++ b/inc/newlib/genstd.h
@@ -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 );
diff --git a/src/common.c b/src/common.c
index f65d6de3..1e64525a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -16,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 )
@@ -46,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
// ****************************************************************************
@@ -83,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 )
@@ -177,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 );
}
@@ -464,3 +472,28 @@ const char* cmn_str64( u64 x )
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 = 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" );
+ if( tempn != PLATFORM_TIMER_INF_TIMEOUT )
+ {
+ *ptimeout = ( timer_data_type )tempn;
+ *pid = ( unsigned )luaL_optinteger( L, pidx + 1, PLATFORM_TIMER_SYS_ID );
+ }
+ }
+}
+
diff --git a/src/platform/i386/platform.c b/src/platform/i386/platform.c
index fce2c3f8..ff7d4cbc 100644
--- a/src/platform/i386/platform.c
+++ b/src/platform/i386/platform.c
@@ -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;
diff --git a/src/platform/sim/platform.c b/src/platform/sim/platform.c
index 5d576dd0..fee8f3c8 100644
--- a/src/platform/sim/platform.c
+++ b/src/platform/sim/platform.c
@@ -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;
}
From e6b20231b4eea4054070b1f6a4e36216e80d2d1d Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 8 Oct 2011 02:53:33 +0200
Subject: [PATCH 26/80] Add bounds checking for duty < 0 and freq < 1 in
pwm.setup()
Previously, you could ask for a PWM frequency of 0 and negative
duty cycles, and each platform would do a different thing: failing
or setting some random values. This change replaces such values
with the minimum, the same way that duty is bounded to 100.
---
src/modules/pwm.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/modules/pwm.c b/src/modules/pwm.c
index d38eace0..d62580d1 100644
--- a/src/modules/pwm.c
+++ b/src/modules/pwm.c
@@ -19,6 +19,10 @@ static int pwm_setup( lua_State* L )
duty = luaL_checkinteger( L, 3 );
if( duty > 100 )
duty = 100;
+ if( duty < 0 )
+ duty = 0;
+ if ( freq < 0 )
+ freq = 1;
freq = platform_pwm_setup( id, freq, duty );
lua_pushinteger( L, freq );
return 1;
From e1973504c03fb154ca150067e8eff9ac12e6d94f Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 8 Oct 2011 03:09:07 +0200
Subject: [PATCH 27/80] AVR32 PWM: Improve frequency precision and reporting
Previously, pwm.setup() would set a frequency equal to or less
than the one asked for, and report an integer less than or equal
to the actual frequency set. This change makes it set the closest
available frequency and report the closest integer to that.
---
src/platform/avr32/platform.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index e7c99e51..350ecef2 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -885,16 +885,15 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
// Unfortunately we mustn't use floating point because that would pull
// the whole FP subsystem into the integer-only executable.
- period = pwmclk / frequency;
- duty_cycle = (period * duty) / 100;
+ period = (pwmclk + frequency/2) / frequency;
+ 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.
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;
}
/*
From b3db818b9739814ce89dd07b4437a995cba38d75 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 8 Oct 2011 03:17:10 +0200
Subject: [PATCH 28/80] Fix AVR32 PWM rturning -1 for very large values of
frequency
Previously, if you set a frequency value ten times the PWM clock
frequency, it would calculate a period of 0 and return foo/0, which
gives -1 on AVR32. With this change, everything > pwmclk sets and
returns a frequency of pwmclk.
---
src/platform/avr32/platform.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 350ecef2..17f6c761 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -886,6 +886,7 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
// the whole FP subsystem into the integer-only executable.
period = (pwmclk + frequency/2) / frequency;
+ if (period == 0) period = 1;
duty_cycle = (period * duty + 50) / 100;
// The AVR32 PWM duty cycle is upside down:
From 9ded6db852f370869550ae841dae5c8e47c3b667 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sat, 8 Oct 2011 20:07:14 +0300
Subject: [PATCH 29/80] Implementing system timer capabilities
- the infinite timeout value is again represented by a special value
(not a special timer ID), but this time it's a non-negative value
- all timers in the UART module default to the system timer
- all timers in the TMR module default to the system timer
- implemented a generic system timer mechanism that can be used in
conjunction with a timer interrupt.
- implemented system timers on LM3S (tested) and STM32 (not tested).
Both are based on the Cortex M3 SysTick timer.
---
inc/common.h | 12 ++-
inc/platform.h | 135 +++++++++++++++--------------
inc/xmodem.h | 3 +-
src/common.c | 10 +--
src/common_tmr.c | 56 ++++++++++--
src/common_uart.c | 11 ++-
src/luarpc_elua_uart.c | 2 +-
src/main.c | 2 +-
src/modules/uart.c | 35 +++-----
src/platform/lm3s/platform.c | 40 ++++++++-
src/platform/lm3s/platform_conf.h | 1 -
src/platform/sim/platform_conf.h | 1 -
src/platform/stm32/platform.c | 40 +++++++--
src/platform/stm32/platform_conf.h | 1 -
14 files changed, 226 insertions(+), 123 deletions(-)
diff --git a/inc/common.h b/inc/common.h
index 90f800c6..4d230e50 100644
--- a/inc/common.h
+++ b/inc/common.h
@@ -4,9 +4,12 @@
#define __COMMON_H__
#include "elua_int.h"
+#include "lua.h"
+#include "platform.h"
// Virtual timers data
-#define VTMR_FIRST_ID ( 32 )
+// VTMR_FIRST_ID must be LARGER than PLATFORM_TIMER_SYS_ID (as declared in platform.h)
+#define VTMR_FIRST_ID ( 0x200 )
#define VTMR_GET_ID( x ) ( ( x ) - VTMR_FIRST_ID )
#define TIMER_IS_VIRTUAL( x ) ( ( VTMR_NUM_TIMERS > 0 ) && ( ( x ) >= VTMR_FIRST_ID ) && ( ( x ) < VTMR_NUM_TIMERS + VTMR_FIRST_ID ) )
@@ -18,10 +21,17 @@ 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_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__
diff --git a/inc/platform.h b/inc/platform.h
index 26aed7b0..8159c8ca 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -68,6 +68,74 @@ 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();
+// 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_stop();
+void platform_timer_sys_start();
+
+// 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 )
+
// *****************************************************************************
// CAN subsection
@@ -133,9 +201,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,71 +212,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
-
-// The ID of the system timer
-#define PLATFORM_TIMER_SYS_ID 0xFFFF
-
-// The ID of the timer which will be used for infinite timeouts
-// Specifying this timer ID always implies "infinite timeout"
-// This is just a convention, it doesn't have an associated timer
-// (not even a virtual one)
-#define PLATFORM_TIMER_INF_TIMEOUT_ID 0xFFFE
-
-#if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
-// Maximum values of the system timer
-#define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 32 ) - 1 )
-// Timer data type
-typedef u32 timer_data_type;
-#else
-// Maximum values of the system timer
- #define PLATFORM_TIMER_SYS_MAX ( ( 1LL << 52 ) - 1 )
-// Timer data type
-typedef u64 timer_data_type;
-#endif // #if defined( LUA_NUMBER_INTEGRAL ) && !defined( LUA_INTEGRAL_LONGLONG )
-
-// 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 );
-timer_data_type platform_timer_read_sys();
-
// *****************************************************************************
// PWM subsection
diff --git a/inc/xmodem.h b/inc/xmodem.h
index 53fe14e1..e31ca9f9 100644
--- a/inc/xmodem.h
+++ b/inc/xmodem.h
@@ -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 );
diff --git a/src/common.c b/src/common.c
index 1e64525a..1587b260 100644
--- a/src/common.c
+++ b/src/common.c
@@ -67,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 );
}
@@ -483,17 +483,13 @@ void cmn_get_timeout_data( lua_State *L, int pidx, timer_data_type *ptimeout, un
lua_Number tempn;
*ptimeout = PLATFORM_TIMER_INF_TIMEOUT;
- *pid = PLATFORM_TIMER_SYS_ID;
+ *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" );
- if( tempn != PLATFORM_TIMER_INF_TIMEOUT )
- {
- *ptimeout = ( timer_data_type )tempn;
- *pid = ( unsigned )luaL_optinteger( L, pidx + 1, PLATFORM_TIMER_SYS_ID );
- }
+ *ptimeout = ( timer_data_type )tempn;
}
}
diff --git a/src/common_tmr.c b/src/common_tmr.c
index 9ab7b4d7..285d8063 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -228,7 +228,7 @@ timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data )
break;
case PLATFORM_TIMER_OP_GET_MAX_DELAY:
- res = PLATFORM_TIMER_SYS_MAX;
+ res = PLATFORM_TIMER_SYS_MAX + 1;
break;
case PLATFORM_TIMER_OP_GET_MAX_CNT:
@@ -236,7 +236,7 @@ timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data )
break;
case PLATFORM_TIMER_OP_GET_MIN_DELAY:
- res = 0;
+ res = 1;
break;
}
@@ -265,7 +265,7 @@ timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data )
break;
case PLATFORM_TIMER_OP_GET_MAX_CNT:
- res = VTMX_MAX_PERIOD;
+ res = VTMR_MAX_PERIOD;
break;
case PLATFORM_TIMER_OP_SET_CLOCK:
@@ -281,18 +281,16 @@ timer_data_type platform_timer_get_diff_us( unsigned id, timer_data_type end, ti
{
u32 freq;
u64 tstart = ( u64 )start, tend = ( u64 )end;
- timer_data_type res;
freq = platform_timer_op( id, PLATFORM_TIMER_OP_GET_CLOCK, 0 );
if( tstart > tend )
tend += platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_CNT, 0 ) + 1;
tstart = ( ( tend - tstart ) * 1000000 ) / freq;
- res = UMIN( tstart, PLATFORM_TIMER_SYS_MAX );
- return res;
+ 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 ) )
@@ -357,3 +355,47 @@ int platform_timer_set_match_int( unsigned id, timer_data_type period_us, int ty
#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_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();
+ crtsys = tempsys;
+ }
+ crtsys += tempcnt / cmn_systimer_ticks_for_us;
+ if( crtsys > PLATFORM_TIMER_SYS_MAX ) // timer overflow
+ {
+ crtsys %= PLATFORM_TIMER_SYS_MAX;
+ platform_timer_sys_stop();
+ cmn_systimer_counter = 0;
+ platform_timer_sys_start();
+ }
+ return ( timer_data_type )crtsys;
+}
+
diff --git a/src/common_uart.c b/src/common_uart.c
index 0de329e8..f97c90be 100644
--- a/src/common_uart.c
+++ b/src/common_uart.c
@@ -54,25 +54,24 @@ static int cmn_recv_helper( unsigned id, s32 timeout )
return platform_s_uart_recv( id, timeout );
}
-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_read( 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;
diff --git a/src/luarpc_elua_uart.c b/src/luarpc_elua_uart.c
index bd3c5648..fab41de3 100644
--- a/src/luarpc_elua_uart.c
+++ b/src/luarpc_elua_uart.c
@@ -100,7 +100,7 @@ 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 )
diff --git a/src/main.c b/src/main.c
index cc72966c..4ef1c1cb 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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
diff --git a/src/modules/uart.c b/src/modules/uart.c
index b9138a11..bf5fe606 100644
--- a/src/modules/uart.c
+++ b/src/modules/uart.c
@@ -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,7 +241,7 @@ 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 ) },
@@ -281,7 +270,7 @@ 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 );
// Add the UART flow constants
MOD_REG_NUMBER( L, "FLOW_RTS", PLATFORM_UART_FLOW_RTS );
diff --git a/src/platform/lm3s/platform.c b/src/platform/lm3s/platform.c
index f91744c5..0e9ea5f7 100644
--- a/src/platform/lm3s/platform.c
+++ b/src/platform/lm3s/platform.c
@@ -120,6 +120,10 @@ int platform_init()
cans_init();
#endif
+ // Setup system timer
+ cmn_systimer_set_base_freq( MAP_SysCtlClockGet() );
+ cmn_systimer_set_interrupt_freq( SYSTICKHZ );
+
// Setup ethernet (TCP/IP)
eth_init();
@@ -476,7 +480,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 ];
@@ -510,7 +514,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 ];
@@ -520,7 +524,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 ];
@@ -551,10 +555,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_stop()
+{
+ MAP_SysTickDisable();
+}
+
+void platform_timer_sys_start()
+{
+ MAP_SysTickEnable();
+}
+
+timer_data_type platform_timer_read_sys()
+{
+ return cmn_systimer_get();
+}
+
// ****************************************************************************
// PWMs
// Similar on LM3S8962 and LM3S6965
@@ -1026,6 +1054,9 @@ void SysTickIntHandler()
// 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()
@@ -1049,6 +1080,9 @@ void SysTickIntHandler()
#ifdef BUILD_MMCFS
disk_timerproc();
#endif
+
+ // System timer handling
+ cmn_systimer_periodic();
}
void EthernetIntHandler()
diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h
index d1e0a8cf..8d0dc6f0 100644
--- a/src/platform/lm3s/platform_conf.h
+++ b/src/platform/lm3s/platform_conf.h
@@ -41,7 +41,6 @@
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
-#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
diff --git a/src/platform/sim/platform_conf.h b/src/platform/sim/platform_conf.h
index cac38a9b..8009f248 100644
--- a/src/platform/sim/platform_conf.h
+++ b/src/platform/sim/platform_conf.h
@@ -33,7 +33,6 @@
// Bogus defines for common.c
#define CON_UART_ID 0
#define CON_UART_SPEED 0
-#define CON_TIMER_ID 0
// *****************************************************************************
// Configuration data
diff --git a/src/platform/stm32/platform.c b/src/platform/stm32/platform.c
index c0017bb1..6a565a78 100755
--- a/src/platform/stm32/platform.c
+++ b/src/platform/stm32/platform.c
@@ -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
@@ -710,6 +714,9 @@ void SysTick_Handler( void )
#ifdef BUILD_MMCFS
disk_timerproc();
#endif
+
+ // Handle system timer call
+ cmn_systimer_periodic();
}
static void timers_init()
@@ -752,7 +759,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 +771,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 +805,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 +864,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_stop()
+{
+ SysTick->CTRL &= ~( 1 << SYSTICK_ENABLE );
+}
+
+void platform_timer_sys_start()
+{
+ SysTick->CTRL |= 1 << SYSTICK_ENABLE;
+}
+
+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
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index 48ede866..e7ecb9dd 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -36,7 +36,6 @@
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
-#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
From 57b27d05fb110a9f0deaf610c5b7c576dbf0a1a7 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sat, 8 Oct 2011 22:02:41 +0300
Subject: [PATCH 30/80] System timer support - WIP
1. System timer support for MBED using the Cortex M3 SysTick interrupt
2. Bugfix in the generic system timer implementation
---
src/common_tmr.c | 2 +-
src/platform/lpc17xx/platform.c | 63 +++++++++++++++++++++++++---
src/platform/lpc17xx/platform_conf.h | 5 ++-
3 files changed, 61 insertions(+), 9 deletions(-)
diff --git a/src/common_tmr.c b/src/common_tmr.c
index 285d8063..c3dadf39 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -386,7 +386,7 @@ timer_data_type cmn_systimer_get()
while( ( crtsys = cmn_systimer_counter ) != tempsys )
{
tempcnt = platform_timer_sys_raw_read();
- crtsys = tempsys;
+ tempsys = crtsys;
}
crtsys += tempcnt / cmn_systimer_ticks_for_us;
if( crtsys > PLATFORM_TIMER_SYS_MAX ) // timer overflow
diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c
index 3e672ce8..489dfc7a 100644
--- a/src/platform/lpc17xx/platform.c
+++ b/src/platform/lpc17xx/platform.c
@@ -28,6 +28,8 @@
#include "lpc17xx_pwm.h"
#include "lpc17xx_adc.h"
+#define SYSTICKHZ 10
+
// ****************************************************************************
// Platform initialization
@@ -66,12 +68,39 @@ 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();
+
+#ifdef BUILD_MMCFS
+ disk_timerproc();
+#endif
+
+ // Handle system timer call
+ cmn_systimer_periodic();
+}
+
// ****************************************************************************
// PIO section
@@ -79,7 +108,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 +162,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 +241,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 +306,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 +316,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 +346,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_stop()
+{
+ SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+}
+
+void platform_timer_sys_start()
+{
+ SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+}
+
+timer_data_type platform_timer_read_sys()
+{
+ return cmn_systimer_get();
+}
+
// *****************************************************************************
// ADC specific functions and variables
diff --git a/src/platform/lpc17xx/platform_conf.h b/src/platform/lpc17xx/platform_conf.h
index 0cd935be..56d732aa 100644
--- a/src/platform/lpc17xx/platform_conf.h
+++ b/src/platform/lpc17xx/platform_conf.h
@@ -5,6 +5,7 @@
#include "auxmods.h"
#include "stacks.h"
+#include "type.h"
// *****************************************************************************
// Define here what components you want for this platform
@@ -23,7 +24,6 @@
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
-#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@@ -105,7 +105,8 @@
#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'
From a9e69c72d43cd9bd4f1a1dfa0aa55c19c51b3701 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sat, 8 Oct 2011 23:24:19 +0300
Subject: [PATCH 31/80] Update net module with the new timer infrastructure
- change timeouts in elua_uip.c to the timer data type
- make all timer IDs in the net module default to the system timer
---
inc/elua_net.h | 7 ++++---
src/elua_uip.c | 20 ++++++++++----------
src/modules/net.c | 27 ++++++++++-----------------
3 files changed, 24 insertions(+), 30 deletions(-)
diff --git a/inc/elua_net.h b/inc/elua_net.h
index 28b5fb12..96db308b 100644
--- a/inc/elua_net.h
+++ b/inc/elua_net.h
@@ -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 );
diff --git a/src/elua_uip.c b/src/elua_uip.c
index ace6604c..173a74ba 100644
--- a/src/elua_uip.c
+++ b/src/elua_uip.c
@@ -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_read( 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_read( 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;
diff --git a/src/modules/net.c b/src/modules/net.c
index c72c4609..2d3be833 100644
--- a/src/modules/net.c
+++ b/src/modules/net.c
@@ -6,6 +6,7 @@
#include "platform.h"
#include "auxmods.h"
#include "elua_net.h"
+#include "common.h"
#include
#include
#include
@@ -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 );
From 720d62909ed3a84ded4bb33e3a096a3a5ca271ef Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sun, 9 Oct 2011 19:41:30 +0300
Subject: [PATCH 32/80] new timer convenience function
---
inc/platform.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/inc/platform.h b/inc/platform.h
index 8159c8ca..f3fb634c 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -135,6 +135,7 @@ void platform_timer_sys_start();
#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
From 356e683e3a56b059f994559ce5756f5bbf1597b1 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sun, 9 Oct 2011 19:48:37 +0300
Subject: [PATCH 33/80] fixed invalid platform_timer_read call
---
src/common_uart.c | 4 ++--
src/elua_uip.c | 4 ++--
src/uip/dhcpc.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/common_uart.c b/src/common_uart.c
index f97c90be..014e4fc6 100644
--- a/src/common_uart.c
+++ b/src/common_uart.c
@@ -31,7 +31,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;
@@ -66,7 +66,7 @@ int platform_uart_recv( unsigned id, unsigned timer_id, timer_data_type timeout
else
{
// Receive char with the specified timeout
- tmr_start = platform_timer_read( timer_id );
+ tmr_start = platform_timer_start( timer_id );
while( 1 )
{
if( ( res = cmn_recv_helper( id, 0 ) ) >= 0 )
diff --git a/src/elua_uip.c b/src/elua_uip.c
index 173a74ba..c5e42d46 100644
--- a/src/elua_uip.c
+++ b/src/elua_uip.c
@@ -557,7 +557,7 @@ 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_read( timer_id );
+ tmrstart = platform_timer_start( timer_id );
while( 1 )
{
if( pstate->state == ELUA_UIP_STATE_IDLE )
@@ -645,7 +645,7 @@ int elua_accept( u16 port, unsigned timer_id, timer_data_type to_us, elua_net_ip
elua_uip_accept_sock = -1;
elua_uip_accept_request = 1;
if( to_us > 0 )
- tmrstart = platform_timer_read( timer_id );
+ tmrstart = platform_timer_start( timer_id );
while( 1 )
{
if( elua_uip_accept_request == 0 )
diff --git a/src/uip/dhcpc.c b/src/uip/dhcpc.c
index 189d20c5..7939f4d4 100644
--- a/src/uip/dhcpc.c
+++ b/src/uip/dhcpc.c
@@ -277,7 +277,7 @@ PT_THREAD(handle_dhcp(void))
do {
send_discover();
- s.timer_init = platform_timer_read( ELUA_DHCP_TIMER_ID );
+ s.timer_init = platform_timer_start( ELUA_DHCP_TIMER_ID );
PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_crt( ELUA_DHCP_TIMER_ID, s.timer_init ) >= s.ticks );
if(uip_newdata() && parse_msg() == DHCPOFFER) {
uip_flags &= ~UIP_NEWDATA;
@@ -297,7 +297,7 @@ PT_THREAD(handle_dhcp(void))
do {
send_request();
- s.timer_init = platform_timer_read( ELUA_DHCP_TIMER_ID );
+ s.timer_init = platform_timer_start( ELUA_DHCP_TIMER_ID );
PT_WAIT_UNTIL(&s.pt, uip_newdata() || platform_timer_get_diff_crt( ELUA_DHCP_TIMER_ID, s.timer_init ) >= s.ticks );
if(uip_newdata() && parse_msg() == DHCPACK) {
From bed235ccdd253f209fbba9d8c55afd0ce025bd90 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Sun, 9 Oct 2011 20:42:03 +0300
Subject: [PATCH 34/80] AVR32 system timer implementation
---
src/platform/avr32/EVK1100/evk1100_conf.h | 3 +-
src/platform/avr32/EVK1101/evk1101_conf.h | 3 +-
src/platform/avr32/MIZAR32/mizar32_conf.h | 3 +-
src/platform/avr32/platform.c | 99 ++++++++++++++++++++---
4 files changed, 93 insertions(+), 15 deletions(-)
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index cedb122e..807de99b 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -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,7 +115,7 @@
#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
diff --git a/src/platform/avr32/EVK1101/evk1101_conf.h b/src/platform/avr32/EVK1101/evk1101_conf.h
index c62860cb..76e1146b 100644
--- a/src/platform/avr32/EVK1101/evk1101_conf.h
+++ b/src/platform/avr32/EVK1101/evk1101_conf.h
@@ -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,7 +85,7 @@
#else
#define NUM_TIMER 3
#endif
-#define NUM_PWM 7
+#define NUM_PWM 6
#define NUM_ADC 8
#define NUM_CAN 0
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index 6b588f68..31fe2238 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -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
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index e7c99e51..e5d72b3b 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -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
@@ -233,7 +281,6 @@ int platform_init()
pwm_init();
#endif
-
#ifdef BUILD_UIP
platform_ethernet_setup();
#endif
@@ -248,6 +295,12 @@ 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();
+
cmn_platform_init();
// All done
@@ -399,7 +452,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;
@@ -529,7 +582,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 +600,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,15 +633,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 = 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;
}
+u64 platform_timer_sys_raw_read()
+{
+ return AVR32_PWM.channel[ SYSTIMER_PWM_CH ].ccnt;
+}
+
+void platform_timer_sys_stop()
+{
+ AVR32_PWM.dis = 1 << SYSTIMER_PWM_CH;
+}
+
+void platform_timer_sys_start()
+{
+ AVR32_PWM.ena = 1 << SYSTIMER_PWM_CH;
+}
+
+timer_data_type platform_timer_read_sys()
+{
+ return cmn_systimer_get();
+}
+
// ****************************************************************************
// SPI functions
@@ -829,6 +906,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 +920,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 +928,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
};
@@ -915,7 +997,7 @@ static void find_clock_configuration( u32 frequency,
#define prescalers( n ) ( 1 << n )
const unsigned nprescalers = 11;
- unsigned prescaler; // Select a prescaler
+ unsigned prescaler = 0; // Select a prescaler
unsigned divisor = 0;
if ( frequency > REQ_PBA_FREQ )
@@ -945,7 +1027,6 @@ static void find_clock_configuration( u32 frequency,
}
#undef prescalers
-
u32 platform_pwm_set_clock( unsigned id, u32 freq )
{
unsigned pre, div;
From 06f73e485c9d010c0c8f48f97a836e4a2d957d9b Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sun, 9 Oct 2011 19:45:45 +0200
Subject: [PATCH 35/80] Add checks for invalid parameters in Lua i2c.*() and
pwm.*() functions
Instead of "correcting" or ignoring bad parameter values in i2c and pwm
(see commit e6b20231b4eea4054070b1f6a4e36216e80d2d1d)
apply the eLua policy of signalling the error on the console and aborting.
All "clock" and "frequency" errors here use the same message ("frequency")
so as to reduce the firmware bloat from extra message strings.
---
src/modules/i2c.c | 18 +++++++++++-------
src/modules/pwm.c | 24 +++++++++++++-----------
2 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/src/modules/i2c.c b/src/modules/i2c.c
index b950763d..5ea44a6e 100644
--- a/src/modules/i2c.c
+++ b/src/modules/i2c.c
@@ -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;
}
diff --git a/src/modules/pwm.c b/src/modules/pwm.c
index d62580d1..fc065270 100644
--- a/src/modules/pwm.c
+++ b/src/modules/pwm.c
@@ -10,20 +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;
- if( duty < 0 )
- duty = 0;
- if ( freq < 0 )
- freq = 1;
- 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;
}
@@ -54,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;
}
From 25a517d66a5e17944e9cdaa645f5d3c7bc613fbc Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sun, 9 Oct 2011 21:14:13 +0200
Subject: [PATCH 36/80] Fix two bugs in AVR32 PWM code
- Very low frequencies with very high clock rates (ratio > 1048576)
selected random requencies (overflow of 20-bit period register was
not checked
- initialization of prescaler selector to 0 was missing.
It just happened to get 0 off the stack every time by chance (!).
---
src/platform/avr32/platform.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 17f6c761..afe5584d 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -887,6 +887,7 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
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:
@@ -905,18 +906,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 +927,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 ) );
@@ -950,7 +952,7 @@ 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();
From 7f94e898e178ac74cd1143a80ba6376977d222dc Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Mon, 10 Oct 2011 01:22:56 +0300
Subject: [PATCH 37/80] Added a function to directly specify the interrupt
period
---
inc/common.h | 1 +
src/common_tmr.c | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/inc/common.h b/inc/common.h
index 4d230e50..9aebffe7 100644
--- a/inc/common.h
+++ b/inc/common.h
@@ -24,6 +24,7 @@ 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();
diff --git a/src/common_tmr.c b/src/common_tmr.c
index c3dadf39..e637e209 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -372,6 +372,11 @@ 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;
From 94cd84a5b68201c597cf78c9b5d7817afd0b937d Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Mon, 10 Oct 2011 01:24:29 +0300
Subject: [PATCH 38/80] added systimer support for AT91SAM7X
---
src/platform/at91sam7x/conf.lua | 2 +-
src/platform/at91sam7x/conf.py | 2 +-
src/platform/at91sam7x/pit.c | 129 +++++++++++++++++++++++++
src/platform/at91sam7x/pit.h | 79 +++++++++++++++
src/platform/at91sam7x/platform.c | 75 +++++++++++++-
src/platform/at91sam7x/platform_conf.h | 11 ++-
6 files changed, 286 insertions(+), 12 deletions(-)
create mode 100644 src/platform/at91sam7x/pit.c
create mode 100644 src/platform/at91sam7x/pit.h
diff --git a/src/platform/at91sam7x/conf.lua b/src/platform/at91sam7x/conf.lua
index f03ddb43..53834b12 100644
--- a/src/platform/at91sam7x/conf.lua
+++ b/src/platform/at91sam7x/conf.lua
@@ -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"
diff --git a/src/platform/at91sam7x/conf.py b/src/platform/at91sam7x/conf.py
index 26607164..eaaec673 100644
--- a/src/platform/at91sam7x/conf.py
+++ b/src/platform/at91sam7x/conf.py
@@ -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')
diff --git a/src/platform/at91sam7x/pit.c b/src/platform/at91sam7x/pit.c
new file mode 100644
index 00000000..7d45324d
--- /dev/null
+++ b/src/platform/at91sam7x/pit.c
@@ -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
+
+//------------------------------------------------------------------------------
+// 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 µ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;
+}
diff --git a/src/platform/at91sam7x/pit.h b/src/platform/at91sam7x/pit.h
new file mode 100644
index 00000000..13cf0eea
--- /dev/null
+++ b/src/platform/at91sam7x/pit.h
@@ -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
+
diff --git a/src/platform/at91sam7x/platform.c b/src/platform/at91sam7x/platform.c
index 90a72b20..5b030d9e 100644
--- a/src/platform/at91sam7x/platform.c
+++ b/src/platform/at91sam7x/platform.c
@@ -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_stop()
+{
+ PIT_Disable();
+}
+
+void platform_timer_sys_start()
+{
+ PIT_Enable();
+}
+
+timer_data_type platform_timer_read_sys()
+{
+ return cmn_systimer_get();
+}
+
// ****************************************************************************
// PWMs
diff --git a/src/platform/at91sam7x/platform_conf.h b/src/platform/at91sam7x/platform_conf.h
index ae8c9441..c857eb51 100644
--- a/src/platform/at91sam7x/platform_conf.h
+++ b/src/platform/at91sam7x/platform_conf.h
@@ -19,17 +19,16 @@
#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
// *****************************************************************************
// 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
@@ -111,6 +110,7 @@
#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
@@ -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
From eea769be29e9f21e4af0b2f08ed1e4310082ea3c Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Sun, 9 Oct 2011 19:06:59 -0500
Subject: [PATCH 39/80] Initial fix for AVR32 ADC sequencer issues
---
src/platform/avr32/platform.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index afe5584d..75a2d657 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -716,6 +716,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;
@@ -758,9 +760,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 +779,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 );
From 8fe7d5ca9a791ea5e977ff9c777fc350bd3f0230 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Mon, 10 Oct 2011 04:23:19 +0200
Subject: [PATCH 40/80] Fix bug in AVR32 ADC code: reading write-only register
adc->chdr
---
src/platform/avr32/adc.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/src/platform/avr32/adc.c b/src/platform/avr32/adc.c
index e3d0e296..fc1b2e4e 100644
--- a/src/platform/avr32/adc.c
+++ b/src/platform/avr32/adc.c
@@ -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)
From b1b82b127ec846bd5d5c59d2465102af642e43c6 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 00:44:06 +0300
Subject: [PATCH 41/80] Change systimer overflow handling from timer stop to
interrupt disable
When a systimer timer overflow is detected, handle it by temporarily disabling
the systimer interrupt rather than disabling the systimer completely. It gives
better accuracy and fixes some hardware-related issues on some platforms.
---
inc/platform.h | 4 ++--
src/common_tmr.c | 4 ++--
src/platform/at91sam7x/platform.c | 8 ++++----
src/platform/avr32/platform.c | 8 ++++----
src/platform/lm3s/platform.c | 8 ++++----
src/platform/lpc17xx/platform.c | 8 ++++----
src/platform/stm32/platform.c | 8 ++++----
7 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/inc/platform.h b/inc/platform.h
index f3fb634c..4036ae35 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -128,8 +128,8 @@ timer_data_type platform_timer_read_sys();
// 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_stop();
-void platform_timer_sys_start();
+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 )
diff --git a/src/common_tmr.c b/src/common_tmr.c
index e637e209..6a0f25b1 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -397,9 +397,9 @@ timer_data_type cmn_systimer_get()
if( crtsys > PLATFORM_TIMER_SYS_MAX ) // timer overflow
{
crtsys %= PLATFORM_TIMER_SYS_MAX;
- platform_timer_sys_stop();
+ platform_timer_sys_disable_int();
cmn_systimer_counter = 0;
- platform_timer_sys_start();
+ platform_timer_sys_enable_int();
}
return ( timer_data_type )crtsys;
}
diff --git a/src/platform/at91sam7x/platform.c b/src/platform/at91sam7x/platform.c
index 5b030d9e..efb6dd63 100644
--- a/src/platform/at91sam7x/platform.c
+++ b/src/platform/at91sam7x/platform.c
@@ -379,14 +379,14 @@ u64 platform_timer_sys_raw_read()
return PIT_GetPIIR() & SYSTIMER_MASK;
}
-void platform_timer_sys_stop()
+void platform_timer_sys_disable_int()
{
- PIT_Disable();
+ PIT_DisableIT();
}
-void platform_timer_sys_start()
+void platform_timer_sys_enable_int()
{
- PIT_Enable();
+ PIT_EnableIT();
}
timer_data_type platform_timer_read_sys()
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index e5d72b3b..c7aa6de9 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -651,14 +651,14 @@ u64 platform_timer_sys_raw_read()
return AVR32_PWM.channel[ SYSTIMER_PWM_CH ].ccnt;
}
-void platform_timer_sys_stop()
+void platform_timer_sys_disable_int()
{
- AVR32_PWM.dis = 1 << SYSTIMER_PWM_CH;
+ AVR32_PWM.idr = 1 << SYSTIMER_PWM_CH;
}
-void platform_timer_sys_start()
+void platform_timer_sys_enable_int()
{
- AVR32_PWM.ena = 1 << SYSTIMER_PWM_CH;
+ AVR32_PWM.ier = 1 << SYSTIMER_PWM_CH;
}
timer_data_type platform_timer_read_sys()
diff --git a/src/platform/lm3s/platform.c b/src/platform/lm3s/platform.c
index 0e9ea5f7..c0f67d34 100644
--- a/src/platform/lm3s/platform.c
+++ b/src/platform/lm3s/platform.c
@@ -568,14 +568,14 @@ u64 platform_timer_sys_raw_read()
return MAP_SysTickPeriodGet() - 1 - MAP_SysTickValueGet();
}
-void platform_timer_sys_stop()
+void platform_timer_sys_disable_int()
{
- MAP_SysTickDisable();
+ MAP_SysTickIntDisable();
}
-void platform_timer_sys_start()
+void platform_timer_sys_enable_int()
{
- MAP_SysTickEnable();
+ MAP_SysTickIntEnable();
}
timer_data_type platform_timer_read_sys()
diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c
index 489dfc7a..75b06b2a 100644
--- a/src/platform/lpc17xx/platform.c
+++ b/src/platform/lpc17xx/platform.c
@@ -359,14 +359,14 @@ u64 platform_timer_sys_raw_read()
return SysTick->LOAD - SysTick->VAL;
}
-void platform_timer_sys_stop()
+void platform_timer_sys_disable_int()
{
- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
+ SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}
-void platform_timer_sys_start()
+void platform_timer_sys_enable_int()
{
- SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
+ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}
timer_data_type platform_timer_read_sys()
diff --git a/src/platform/stm32/platform.c b/src/platform/stm32/platform.c
index 6a565a78..d5ddf3c2 100755
--- a/src/platform/stm32/platform.c
+++ b/src/platform/stm32/platform.c
@@ -869,14 +869,14 @@ u64 platform_timer_sys_raw_read()
return SysTick->LOAD - SysTick->VAL;
}
-void platform_timer_sys_stop()
+void platform_timer_sys_disable_int()
{
- SysTick->CTRL &= ~( 1 << SYSTICK_ENABLE );
+ SysTick->CTRL &= ~( 1 << SYSTICK_TICKINT );
}
-void platform_timer_sys_start()
+void platform_timer_sys_enable_int()
{
- SysTick->CTRL |= 1 << SYSTICK_ENABLE;
+ SysTick->CTRL |= 1 << SYSTICK_TICKINT;
}
timer_data_type platform_timer_read_sys()
From acba13b16f658b66855a85f98081dbf6250e5e49 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 01:41:14 +0300
Subject: [PATCH 42/80] systimer support for LPC24xx
---
src/platform/lpc24xx/platform.c | 48 +++++++++++++++++++++-------
src/platform/lpc24xx/platform_conf.h | 12 ++++---
2 files changed, 44 insertions(+), 16 deletions(-)
diff --git a/src/platform/lpc24xx/platform.c b/src/platform/lpc24xx/platform.c
index e0368b65..ed8738d5 100644
--- a/src/platform/lpc24xx/platform.c
+++ b/src/platform/lpc24xx/platform.c
@@ -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
diff --git a/src/platform/lpc24xx/platform_conf.h b/src/platform/lpc24xx/platform_conf.h
index 56f97328..b7473ab8 100644
--- a/src/platform/lpc24xx/platform_conf.h
+++ b/src/platform/lpc24xx/platform_conf.h
@@ -20,18 +20,17 @@
#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
// *****************************************************************************
// 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 +74,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)
@@ -123,6 +123,7 @@
#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
@@ -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)
From 026f72dd46c38fa5597ecfa3251be9675d6fda94 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 13:59:02 +0300
Subject: [PATCH 43/80] System timer support is now optional
Since the system timer might be too demanding for some platforms
(although this isn't currently the case for any eLua plarform) it
is now optional. Any platform that implements it must define the
PLATFORM_HAS_SYSTIMER macro in its platform_conf.h
---
inc/platform.h | 1 +
src/common.c | 2 ++
src/common_tmr.c | 25 ++++++++++++++++++++++++-
src/modules/auxmods.h | 6 ++++++
src/modules/tmr.c | 17 +++++++++--------
src/platform/at91sam7x/platform_conf.h | 2 ++
src/platform/avr32/platform_conf.h | 2 ++
src/platform/lm3s/platform_conf.h | 2 ++
src/platform/lpc17xx/platform_conf.h | 2 ++
src/platform/lpc24xx/platform_conf.h | 2 ++
src/platform/sim/platform_conf.h | 2 ++
src/platform/stm32/platform_conf.h | 2 ++
12 files changed, 56 insertions(+), 9 deletions(-)
diff --git a/inc/platform.h b/inc/platform.h
index 4036ae35..1990211e 100644
--- a/inc/platform.h
+++ b/inc/platform.h
@@ -125,6 +125,7 @@ int platform_s_timer_set_match_int( unsigned id, timer_data_type period_us, int
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();
diff --git a/src/common.c b/src/common.c
index 1587b260..1aa14a1d 100644
--- a/src/common.c
+++ b/src/common.c
@@ -491,5 +491,7 @@ void cmn_get_timeout_data( lua_State *L, int pidx, timer_data_type *ptimeout, un
luaL_error( L, "invalid timeout value" );
*ptimeout = ( timer_data_type )tempn;
}
+ if( *pid == PLATFORM_TIMER_SYS_ID && !platform_timer_sys_available() )
+ return luaL_error( L, "the system timer is not implemented on this platform" );
}
diff --git a/src/common_tmr.c b/src/common_tmr.c
index 6a0f25b1..435d0c1f 100644
--- a/src/common_tmr.c
+++ b/src/common_tmr.c
@@ -26,6 +26,13 @@ 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
@@ -174,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
@@ -181,7 +200,7 @@ int platform_timer_exists( unsigned id )
return TIMER_IS_VIRTUAL( id );
else
#endif
- return id < NUM_TIMER || id == PLATFORM_TIMER_SYS_ID;
+ return id < NUM_TIMER || ( id == PLATFORM_TIMER_SYS_ID && SYSTIMER_SUPPORT );
}
void platform_timer_delay( unsigned id, timer_data_type delay_us )
@@ -193,6 +212,8 @@ void platform_timer_delay( unsigned id, timer_data_type delay_us )
#endif
if( id == PLATFORM_TIMER_SYS_ID )
{
+ if( !SYSTIMER_SUPPORT )
+ return;
if( delay_us > 0 )
{
u64 tstart = platform_timer_read_sys(), tend;
@@ -215,6 +236,8 @@ timer_data_type platform_timer_op( unsigned id, int op, timer_data_type data )
if( id == PLATFORM_TIMER_SYS_ID ) // the system timer gets special treatment
{
+ if( !SYSTIMER_SUPPORT )
+ return 0;
switch( op )
{
case PLATFORM_TIMER_OP_START:
diff --git a/src/modules/auxmods.h b/src/modules/auxmods.h
index d59fb6a4..0db5560d 100644
--- a/src/modules/auxmods.h
+++ b/src/modules/auxmods.h
@@ -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 )
diff --git a/src/modules/tmr.c b/src/modules/tmr.c
index 574613ad..2e2f7529 100644
--- a/src/modules/tmr.c
+++ b/src/modules/tmr.c
@@ -22,7 +22,7 @@ static int tmrh_timer_op( lua_State* L, int op )
timer_data_type res;
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
res = platform_timer_op( id, op, 0 );
lua_pushnumber( L, ( lua_Number )res );
return 1;
@@ -36,7 +36,7 @@ static int tmr_delay( lua_State* L )
period = ( timer_data_type )luaL_checknumber( L, 1 );
id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
platform_timer_delay( id, period );
return 0;
}
@@ -60,7 +60,7 @@ static int tmr_gettimediff( lua_State* L )
unsigned id;
id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, 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 );
@@ -75,7 +75,7 @@ static int tmr_getmindelay( lua_State* L )
unsigned id;
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_MIN_DELAY, 0 );
lua_pushnumber( L, ( lua_Number )res );
return 1;
@@ -88,7 +88,7 @@ static int tmr_getmaxdelay( lua_State* L )
unsigned id;
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_MAX_DELAY, 0 );
lua_pushnumber( L, ( lua_Number )res );
return 1;
@@ -101,7 +101,7 @@ static int tmr_setclock( lua_State* L )
unsigned id;
id = ( unsigned )luaL_optinteger( L, 2, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, 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 );
@@ -115,7 +115,7 @@ static int tmr_getclock( lua_State* L )
unsigned id;
id = ( unsigned )luaL_optinteger( L, 1, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
res = platform_timer_op( id, PLATFORM_TIMER_OP_GET_CLOCK, 0 );
lua_pushinteger( L, res );
return 1;
@@ -129,7 +129,7 @@ static int tmr_set_match_int( lua_State *L )
u32 res;
id = ( unsigned )luaL_optinteger( L, 3, PLATFORM_TIMER_SYS_ID );
- MOD_CHECK_ID( timer, id );
+ MOD_CHECK_TIMER( id );
res = platform_timer_set_match_int( id, ( timer_data_type )luaL_checknumber( L, 1 ), ( int )luaL_checkinteger( L, 3 ) );
if( res == PLATFORM_TIMER_INT_TOO_SHORT )
return luaL_error( L, "timer interval too small" );
@@ -189,6 +189,7 @@ const LUA_REG_TYPE tmr_map[] =
#if LUA_OPTIMIZE_MEMORY > 0 && defined( BUILD_LUA_INT_HANDLERS )
{ LSTRKEY( "INT_ONESHOT" ), LNUMVAL( PLATFORM_TIMER_INT_ONESHOT ) },
{ LSTRKEY( "INT_CYCLIC" ), LNUMVAL( PLATFORM_TIMER_INT_CYCLIC ) },
+ { LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) },
#endif
{ LNILKEY, LNILVAL }
};
diff --git a/src/platform/at91sam7x/platform_conf.h b/src/platform/at91sam7x/platform_conf.h
index c857eb51..44152739 100644
--- a/src/platform/at91sam7x/platform_conf.h
+++ b/src/platform/at91sam7x/platform_conf.h
@@ -23,6 +23,8 @@
//#define BUILD_SERMUX
#define BUILD_C_INT_HANDLERS
+#define PLATFORM_HAS_SYSTIMER
+
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
diff --git a/src/platform/avr32/platform_conf.h b/src/platform/avr32/platform_conf.h
index 3583a0b4..ab66d30d 100644
--- a/src/platform/avr32/platform_conf.h
+++ b/src/platform/avr32/platform_conf.h
@@ -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
diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h
index 8d0dc6f0..5322a4b0 100644
--- a/src/platform/lm3s/platform_conf.h
+++ b/src/platform/lm3s/platform_conf.h
@@ -36,6 +36,8 @@
#endif
#define BUILD_C_INT_HANDLERS
+#define PLATFORM_HAS_SYSTIMER
+
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
diff --git a/src/platform/lpc17xx/platform_conf.h b/src/platform/lpc17xx/platform_conf.h
index 56d732aa..362b1e49 100644
--- a/src/platform/lpc17xx/platform_conf.h
+++ b/src/platform/lpc17xx/platform_conf.h
@@ -19,6 +19,8 @@
#define BUILD_SEMIFS
#define BUILD_RPC
+#define PLATFORM_HAS_SYSTIMER
+
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
diff --git a/src/platform/lpc24xx/platform_conf.h b/src/platform/lpc24xx/platform_conf.h
index b7473ab8..7de1711b 100644
--- a/src/platform/lpc24xx/platform_conf.h
+++ b/src/platform/lpc24xx/platform_conf.h
@@ -25,6 +25,8 @@
#define BUILD_LUA_INT_HANDLERS
#define BUILD_C_INT_HANDLERS
+#define PLATFORM_HAS_SYSTIMER
+
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
diff --git a/src/platform/sim/platform_conf.h b/src/platform/sim/platform_conf.h
index 8009f248..76a4ce90 100644
--- a/src/platform/sim/platform_conf.h
+++ b/src/platform/sim/platform_conf.h
@@ -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
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index e7ecb9dd..7972d5a2 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -31,6 +31,8 @@
#define BUILD_LUA_INT_HANDLERS
#define ENABLE_ENC
+#define PLATFORM_HAS_SYSTIMER
+
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
From 17684b1da2311ade011ec3d4fb8b32e272e63ef7 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 15:45:56 +0300
Subject: [PATCH 44/80] Fix compilation errors for platform that won't get a
system timer
There are some platform that will not get a system timer implementation
(mainly because they don't really have a user base). These are i386,
lpc288x and str7. They will continue to work without a system timer.
---
src/platform/i386/platform.c | 6 +++---
src/platform/lpc288x/platform.c | 6 +++---
src/platform/str7/platform.c | 8 +++-----
3 files changed, 9 insertions(+), 11 deletions(-)
diff --git a/src/platform/i386/platform.c b/src/platform/i386/platform.c
index ff7d4cbc..b43b2ab1 100644
--- a/src/platform/i386/platform.c
+++ b/src/platform/i386/platform.c
@@ -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;
}
diff --git a/src/platform/lpc288x/platform.c b/src/platform/lpc288x/platform.c
index c65a037a..d1e30d9a 100644
--- a/src/platform/lpc288x/platform.c
+++ b/src/platform/lpc288x/platform.c
@@ -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;
diff --git a/src/platform/str7/platform.c b/src/platform/str7/platform.c
index 7e285c8d..63e1fe18 100644
--- a/src/platform/str7/platform.c
+++ b/src/platform/str7/platform.c
@@ -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 ];
@@ -338,7 +338,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 );
}
From 72080c34fc3f362e5daf25e44d60980ea2985278 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 17:28:41 +0300
Subject: [PATCH 45/80] system timer support for STR9 (not yet tested)
---
src/common.c | 2 +-
src/platform/str9/platform.c | 53 +++++++++++++++++++++++++++----
src/platform/str9/platform_conf.h | 9 +++---
src/platform/str9/platform_int.c | 3 ++
4 files changed, 54 insertions(+), 13 deletions(-)
diff --git a/src/common.c b/src/common.c
index 1aa14a1d..8b6c3769 100644
--- a/src/common.c
+++ b/src/common.c
@@ -492,6 +492,6 @@ void cmn_get_timeout_data( lua_State *L, int pidx, timer_data_type *ptimeout, un
*ptimeout = ( timer_data_type )tempn;
}
if( *pid == PLATFORM_TIMER_SYS_ID && !platform_timer_sys_available() )
- return luaL_error( L, "the system timer is not implemented on this platform" );
+ luaL_error( L, "the system timer is not implemented on this platform" );
}
diff --git a/src/platform/str9/platform.c b/src/platform/str9/platform.c
index 4417818f..43e6c7e8 100644
--- a/src/platform/str9/platform.c
+++ b/src/platform/str9/platform.c
@@ -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
diff --git a/src/platform/str9/platform_conf.h b/src/platform/str9/platform_conf.h
index 3c02dd47..f391d9e4 100644
--- a/src/platform/str9/platform_conf.h
+++ b/src/platform/str9/platform_conf.h
@@ -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)
@@ -41,7 +43,7 @@
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
-#define VTMR_FREQ_HZ 10
+#define VTMR_FREQ_HZ 16
#define VTMR_TIMER_ID 2
// Number of resources (0 if not available/not implemented)
@@ -53,11 +55,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
diff --git a/src/platform/str9/platform_int.c b/src/platform/str9/platform_int.c
index a1aca1b6..dc735d10 100644
--- a/src/platform/str9/platform_int.c
+++ b/src/platform/str9/platform_int.c
@@ -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 )
From cc99b2d7a2f21cd37bc3aafd799e9d8f83f77ecb Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 11 Oct 2011 17:31:59 +0300
Subject: [PATCH 46/80] added missing operations for some platforms
---
src/platform/lpc288x/platform.c | 4 ++++
src/platform/str7/platform.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/src/platform/lpc288x/platform.c b/src/platform/lpc288x/platform.c
index d1e30d9a..9c673361 100644
--- a/src/platform/lpc288x/platform.c
+++ b/src/platform/lpc288x/platform.c
@@ -209,6 +209,10 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type 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;
}
diff --git a/src/platform/str7/platform.c b/src/platform/str7/platform.c
index 63e1fe18..34442d0d 100644
--- a/src/platform/str7/platform.c
+++ b/src/platform/str7/platform.c
@@ -290,6 +290,10 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type 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;
}
From 77d543c53a5d2e19af1749e66fe8c72181458981 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Wed, 12 Oct 2011 01:31:29 +0300
Subject: [PATCH 47/80] fixed STR9 systimer implementation (tested)
---
src/platform/str9/interrupt.c | 4 ++++
src/platform/str9/platform_conf.h | 3 +--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/platform/str9/interrupt.c b/src/platform/str9/interrupt.c
index c37bd52e..ebab95b8 100644
--- a/src/platform/str9/interrupt.c
+++ b/src/platform/str9/interrupt.c
@@ -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
diff --git a/src/platform/str9/platform_conf.h b/src/platform/str9/platform_conf.h
index f391d9e4..8fff9040 100644
--- a/src/platform/str9/platform_conf.h
+++ b/src/platform/str9/platform_conf.h
@@ -34,7 +34,6 @@
#endif
#define CON_UART_SPEED 115200
-#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
@@ -44,7 +43,7 @@
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
#define VTMR_FREQ_HZ 16
-#define VTMR_TIMER_ID 2
+#define VTMR_TIMER_ID 3
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 10
From 55e0b9ec9e553275b2fa1ba2672a3928f9f47078 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 13 Oct 2011 13:37:46 +0300
Subject: [PATCH 48/80] RPC_TIMER_ID now defaults to the system timer on
supported platforms
---
src/platform/at91sam7x/platform_conf.h | 1 -
src/platform/avr32/EVK1100/evk1100_conf.h | 1 -
src/platform/avr32/EVK1101/evk1101_conf.h | 1 -
src/platform/avr32/MIZAR32/mizar32_conf.h | 1 -
src/platform/lm3s/platform_conf.h | 1 -
src/platform/lpc17xx/platform_conf.h | 1 -
src/platform/lpc24xx/platform_conf.h | 1 -
src/platform/stm32/platform_conf.h | 1 -
src/platform/str9/platform_conf.h | 1 -
9 files changed, 9 deletions(-)
diff --git a/src/platform/at91sam7x/platform_conf.h b/src/platform/at91sam7x/platform_conf.h
index 44152739..23c92ff2 100644
--- a/src/platform/at91sam7x/platform_conf.h
+++ b/src/platform/at91sam7x/platform_conf.h
@@ -83,7 +83,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
// Enable RX buffering on UART
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index 807de99b..289ce5db 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -122,7 +122,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
// Enable RX buffering on UART
diff --git a/src/platform/avr32/EVK1101/evk1101_conf.h b/src/platform/avr32/EVK1101/evk1101_conf.h
index 76e1146b..7ac27ea1 100644
--- a/src/platform/avr32/EVK1101/evk1101_conf.h
+++ b/src/platform/avr32/EVK1101/evk1101_conf.h
@@ -91,7 +91,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
// Enable RX buffering on UART
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index 31fe2238..ea949e72 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -175,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
diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h
index 5322a4b0..ec225883 100644
--- a/src/platform/lm3s/platform_conf.h
+++ b/src/platform/lm3s/platform_conf.h
@@ -199,7 +199,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
// SD/MMC Filesystem Setup
diff --git a/src/platform/lpc17xx/platform_conf.h b/src/platform/lpc17xx/platform_conf.h
index 362b1e49..1e96b75a 100644
--- a/src/platform/lpc17xx/platform_conf.h
+++ b/src/platform/lpc17xx/platform_conf.h
@@ -104,7 +104,6 @@
// 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)
u32 mbed_get_cpu_frequency();
diff --git a/src/platform/lpc24xx/platform_conf.h b/src/platform/lpc24xx/platform_conf.h
index 7de1711b..85c44408 100644
--- a/src/platform/lpc24xx/platform_conf.h
+++ b/src/platform/lpc24xx/platform_conf.h
@@ -110,7 +110,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
// CPU frequency (needed by the CPU module, 0 if not used)
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index 7972d5a2..771f197e 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -133,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
diff --git a/src/platform/str9/platform_conf.h b/src/platform/str9/platform_conf.h
index 8fff9040..085b6536 100644
--- a/src/platform/str9/platform_conf.h
+++ b/src/platform/str9/platform_conf.h
@@ -69,7 +69,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
// Interrupt queue configuration
From 1a1ae155c994a9cd11b2c31d5874394779e12c4b Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 13 Oct 2011 13:42:49 +0300
Subject: [PATCH 49/80] RFS_TIMER_ID now defaults to the system timer on
supported platforms
---
src/platform/at91sam7x/platform_conf.h | 1 -
src/platform/avr32/EVK1100/evk1100_conf.h | 1 -
src/platform/avr32/MIZAR32/mizar32_conf.h | 1 -
src/platform/lpc24xx/platform_conf.h | 1 -
src/platform/stm32/platform_conf.h | 1 -
src/remotefs/elua_rfs.c | 6 +++++-
6 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/platform/at91sam7x/platform_conf.h b/src/platform/at91sam7x/platform_conf.h
index 23c92ff2..b3d57c15 100644
--- a/src/platform/at91sam7x/platform_conf.h
+++ b/src/platform/at91sam7x/platform_conf.h
@@ -114,7 +114,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
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index 289ce5db..e320307f 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -162,7 +162,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
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index ea949e72..d218e1a6 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -220,7 +220,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
diff --git a/src/platform/lpc24xx/platform_conf.h b/src/platform/lpc24xx/platform_conf.h
index 85c44408..1f5b216b 100644
--- a/src/platform/lpc24xx/platform_conf.h
+++ b/src/platform/lpc24xx/platform_conf.h
@@ -127,7 +127,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
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index 771f197e..ad7aa9db 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -161,7 +161,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
diff --git a/src/remotefs/elua_rfs.c b/src/remotefs/elua_rfs.c
index bf511814..07036318 100644
--- a/src/remotefs/elua_rfs.c
+++ b/src/remotefs/elua_rfs.c
@@ -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
From a46cc203c88d4b9905f4eadc6d8a199d45fda999 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 13 Oct 2011 14:12:05 +0300
Subject: [PATCH 50/80] fix timeout data type in the RFS implementation
---
inc/remotefs/client.h | 7 ++++---
src/remotefs/client.c | 8 ++++----
src/remotefs/elua_rfs.c | 2 +-
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/inc/remotefs/client.h b/inc/remotefs/client.h
index 7bd67f59..f647e31f 100644
--- a/inc/remotefs/client.h
+++ b/inc/remotefs/client.h
@@ -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 );
diff --git a/src/remotefs/client.c b/src/remotefs/client.c
index 210014d3..3bf03c64 100644
--- a/src/remotefs/client.c
+++ b/src/remotefs/client.c
@@ -5,7 +5,7 @@
#include "client.h"
#include "os_io.h"
#include "eluarpc.h"
-
+#include "platform.h"
#include
#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;
}
diff --git a/src/remotefs/elua_rfs.c b/src/remotefs/elua_rfs.c
index 07036318..b7205f84 100644
--- a/src/remotefs/elua_rfs.c
+++ b/src/remotefs/elua_rfs.c
@@ -135,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;
From b12ba2194edf5f8e8e2aece546c0987f56079a4b Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 13 Oct 2011 14:22:27 +0300
Subject: [PATCH 51/80] added new convenience function to the timer module
---
src/modules/tmr.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/src/modules/tmr.c b/src/modules/tmr.c
index 2e2f7529..53170541 100644
--- a/src/modules/tmr.c
+++ b/src/modules/tmr.c
@@ -68,6 +68,20 @@ static int tmr_gettimediff( lua_State* L )
return 1;
}
+// 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 )
{
@@ -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 ) },
From 537cf8da51286047d224ec36fb34145da7d9c608 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 14 Oct 2011 00:07:16 +0300
Subject: [PATCH 52/80] added the system timer as an explicit constant in a few
modules
---
src/modules/net.c | 2 ++
src/modules/tmr.c | 7 ++++++-
src/modules/uart.c | 3 +++
3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/modules/net.c b/src/modules/net.c
index 2d3be833..81ad2c88 100644
--- a/src/modules/net.c
+++ b/src/modules/net.c
@@ -199,6 +199,7 @@ 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 ) },
#endif
{ LNILKEY, LNILVAL }
};
@@ -218,6 +219,7 @@ 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 );
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
diff --git a/src/modules/tmr.c b/src/modules/tmr.c
index 53170541..5f78cdb6 100644
--- a/src/modules/tmr.c
+++ b/src/modules/tmr.c
@@ -200,11 +200,11 @@ 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 ) },
{ LSTRKEY( "INT_CYCLIC" ), LNUMVAL( PLATFORM_TIMER_INT_CYCLIC ) },
- { LSTRKEY( "SYS_TIMER" ), LNUMVAL( PLATFORM_TIMER_SYS_ID ) },
#endif
{ LNILKEY, LNILVAL }
};
@@ -220,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
}
diff --git a/src/modules/uart.c b/src/modules/uart.c
index bf5fe606..febea5a9 100644
--- a/src/modules/uart.c
+++ b/src/modules/uart.c
@@ -245,6 +245,7 @@ const LUA_REG_TYPE uart_map[] =
{ 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 ) },
@@ -271,6 +272,8 @@ 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", 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 );
From c9127c889315c11eade7ee86afbefe0e94c55334 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 14 Oct 2011 14:21:16 +0300
Subject: [PATCH 53/80] another timeout type fix
---
src/remotefs/elua_rfs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/remotefs/elua_rfs.c b/src/remotefs/elua_rfs.c
index b7205f84..38a6a170 100644
--- a/src/remotefs/elua_rfs.c
+++ b/src/remotefs/elua_rfs.c
@@ -161,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 );
From 66798da84b9f0d85a817b4683171c059a66acba8 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Fri, 14 Oct 2011 13:28:12 +0200
Subject: [PATCH 54/80] Fix PWM clock select commentary
---
src/platform/avr32/platform.c | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 75a2d657..79e7fad1 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -869,16 +869,9 @@ 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/2) / frequency;
if (period == 0) period = 1;
@@ -888,6 +881,7 @@ u32 platform_pwm_setup( unsigned id, u32 frequency, unsigned duty )
// 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/2) / period;
From f17b2a3bb22aa0af8372a8702269b3514c9ea561 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Tue, 18 Oct 2011 15:52:37 +0300
Subject: [PATCH 55/80] Lua long long preliminary support
---
SConstruct | 11 ++++++++---
build_elua.lua | 9 +++++++--
run_elua_sim.sh | 2 +-
src/lua/luaconf.h | 32 ++++++++++++++++++++++----------
4 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/SConstruct b/SConstruct
index 86477206..ce5ab3ac 100644
--- a/SConstruct
+++ b/SConstruct
@@ -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 ) } )
diff --git a/build_elua.lua b/build_elua.lua
index ef31d102..e26358a1 100755
--- a/build_elua.lua
+++ b/build_elua.lua
@@ -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
diff --git a/run_elua_sim.sh b/run_elua_sim.sh
index a9cc6c86..0bd80940 100755
--- a/run_elua_sim.sh
+++ b/run_elua_sim.sh
@@ -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
diff --git a/src/lua/luaconf.h b/src/lua/luaconf.h
index cad3a2cc..5e9dca21 100644
--- a/src/lua/luaconf.h
+++ b/src/lua/luaconf.h
@@ -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.
@@ -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
From 447c98a233ff74e38e34d8cd78565dfe52bf7d09 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Wed, 19 Oct 2011 00:57:20 +0300
Subject: [PATCH 56/80] added more timeout related constants to the 'net'
module
---
src/modules/net.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/modules/net.c b/src/modules/net.c
index 81ad2c88..b158d553 100644
--- a/src/modules/net.c
+++ b/src/modules/net.c
@@ -200,6 +200,8 @@ const LUA_REG_TYPE net_map[] =
{ 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 }
};
@@ -220,6 +222,8 @@ LUALIB_API int luaopen_net( lua_State *L )
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
From 6525e399600d541b00da0b263c1adfdb48dc512c Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Wed, 19 Oct 2011 00:57:33 +0300
Subject: [PATCH 57/80] start to document the changes
---
doc/eluadoc/arch_platform_timers.lua | 63 ++++++++++++++++++++++++++--
doc/eluadoc/refman_gen_uart.lua | 17 ++++----
doc/en/asciidoc.conf | 2 +
3 files changed, 69 insertions(+), 13 deletions(-)
diff --git a/doc/eluadoc/arch_platform_timers.lua b/doc/eluadoc/arch_platform_timers.lua
index 47e7f9e6..ea3cef3b 100644
--- a/doc/eluadoc/arch_platform_timers.lua
+++ b/doc/eluadoc/arch_platform_timers.lua
@@ -15,9 +15,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
@@ -199,8 +200,64 @@ $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.
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:
+
+ - 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.
+ - 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.
+ - the timers might be shared with other hardware resources (for example PWMs or ADC triggers) so using them might have unexpected side effects.
+ - 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.
+
+ The ^#virtual_timers^virtual timers^ can fix some of the above problems, but their resolution is fairly low and they still require manual management.
+ 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:
+
+ - if eLua is compiled in floating point mode (default) the counter is 52 bits wide. It will overflow after more than 142 %years%.
+ - if eLua is compiled in 32 bit integer-only mode (lualong) the counter is 32 bits wide. It will overflow after about one hour.
+ - 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.
+
+ The eLua API was partially modified to take full advantage of this new timer:
+
+ - 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.
+ - 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.
+ - timeouts are specified in a more unified manner across the eLua modules as a $[timeout], [timer_id]$ pair:
+
+
+
+ timeout
+ timer_id
+ Result
+
+
+ not specified
+ any value
+ infinite timeout (the function blocks until it completes).
+
+
+ 0
+ any value
+ no timeout (the function returns immediately)./td>
+
+
+ a positive value
+ not specified
+ the system timer will be used to measure the function's timeout.
+
+
+ a positive value
+ a timer ID
+ the specified timer will be used to measure the function's timeout.
+
+
+
+
+
+ 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.]]
}
+ }
}
diff --git a/doc/eluadoc/refman_gen_uart.lua b/doc/eluadoc/refman_gen_uart.lua
index 1d0eaf33..6b670a59 100644
--- a/doc/eluadoc/refman_gen_uart.lua
+++ b/doc/eluadoc/refman_gen_uart.lua
@@ -53,21 +53,19 @@ to the IDs of the virtual UARTs in the system.]]
}
},
- { sig = "str = #uart.getchar#( id, [timeout], [timer_id] )",
+ { sig = "str = #uart.getchar#( id, [timer_id], [timeout] )",
desc = "Read a single character from the serial port",
args =
{
- "$id$ - the ID of the serial port",
+ "$id$ - the ID of the serial port",
+ [[$timer_id (optional)$ - the ID of the timer for the receive operation. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
[[$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$).]]
+blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $uart.INF_TIMEOUT$.]]
},
ret = "The character read from the serial port as a string, or the empty string it timeout occured while waiting for the character."
},
- { sig = "str = #uart.read#( id, format, [timeout], [timer_id] )",
+ { sig = "str = #uart.read#( id, format, [timer_id], [timeout] )",
desc = "Reads one or more characters from the serial port according to a format specifier",
args =
{
@@ -79,10 +77,9 @@ $timeout$ is neither $uart.NO_TIMEOUT$, nor $uart.INF_TIMEOUT$).]]
$'*s'$ - read until a spacing character (like a space or a TAB) is found (the spacing character is not returned) or a timeout occurs.
$a positive number$ - read at most this many characters before returning (reading can stop earlier if a timeout occurs).
]],
+ [[$timer_id (optional)$ - the ID of the timer for the receive operation. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
[[$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$).]]
+blocking operation, or a positive number that specifies the timeout in microseconds. The default value of this argument is $uart.INF_TIMEOUT$.]]
},
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]]
},
diff --git a/doc/en/asciidoc.conf b/doc/en/asciidoc.conf
index ca100c16..ca597de5 100644
--- a/doc/en/asciidoc.conf
+++ b/doc/en/asciidoc.conf
@@ -101,3 +101,5 @@ _mmbedpio=link:refman_ps_mbed_pio.html[mbed.pio]
# Miscellaneous
_br=
+_systmr=link:arch_platform_timers.html#the_system_timer[system timer]
+_virttmr=link:arch_platform_timers.html#virtual_timers[virtual timers]
From 43724385b33c4cc98e7454b033d2495ab9b52da0 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Wed, 19 Oct 2011 15:09:59 +0300
Subject: [PATCH 58/80] finished documenting the timer platform interface and
the 'tmr' module
---
doc/eluadoc/arch_platform_timers.lua | 132 ++++++++++++++++++++++-----
doc/eluadoc/refman_gen_tmr.lua | 68 ++++++++------
2 files changed, 151 insertions(+), 49 deletions(-)
diff --git a/doc/eluadoc/arch_platform_timers.lua b/doc/eluadoc/arch_platform_timers.lua
index ea3cef3b..b006bfd7 100644
--- a/doc/eluadoc/arch_platform_timers.lua
+++ b/doc/eluadoc/arch_platform_timers.lua
@@ -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
@@ -29,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."
@@ -47,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.
IMPORTANT NOTE: 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
@@ -63,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",
@@ -73,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 =
@@ -88,6 +97,7 @@ enum
$PLATFORM_TIMER_GET_CLOCK$: get the clock of the specified timer.
$PLATFORM_TIMER_OP_GET_MAX_DELAY$: get the maximum achievable timeout on the specified timer (in us).
$PLATFORM_TIMER_OP_GET_MIN_DELAY$: get the minimum achievable timeout on the specified timer (in us).
+ $PLATFORM_TIMER_OP_GET_MAX_CNT$: get the maximum value of the timer's counter register.
]],
"$data$ - used to specify the timer clock value when $op = PLATFORM_TIMER_SET_CLOCK$, ignored otherwise",
},
@@ -98,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",
@@ -116,6 +127,7 @@ enum
$PLATFORM_TIMER_GET_CLOCK$: get the clock of the specified timer.
$PLATFORM_TIMER_OP_GET_MAX_DELAY$: get the maximum achievable timeout on the specified timer (in us).
$PLATFORM_TIMER_OP_GET_MIN_DELAY$: get the minimum achievable timeout on the specified timer (in us).
+ $PLATFORM_TIMER_OP_GET_MAX_CNT$: get the maximum value of the timer's counter register.
]],
"$data$ - used to specify the timer clock value when $op = PLATFORM_TIMER_SET_CLOCK$, ignored otherwise",
},
@@ -126,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%. NOTE: 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. NOTE: the @#the_system_timer@system timer@ can't
+generate interrupts.]],
args =
{
"$id$ - the timer ID",
@@ -154,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",
@@ -255,7 +324,26 @@ will default to the system timer is a timer ID is not specified explicitly.
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.]]
+$PLATFORM_TIMER_SYS_ID$ as the timer ID.
+ 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:
+
+ - define the $PLATFORM_HAS_SYSTIMER$ macro in your %platform_conf.h% file.
+ - 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@.
+ - include the %common.h% header.
+ - setup your hardware timer and its associated interrupt. This should happen an initialization time (for example in %platform_init%).
+ - call %cmn_systimer_set_base_freq% with the base frequency of your timer in Hz.
+ - 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.
+ - call %cmn_systimer_periodic% from your timer's overflow interrupt handler.
+ - use this implementation for @#platform_timer_read_sys@platform_timer_read_sys@:
+ ~timer_data_type platform_timer_read_sys()
+{
+ return cmn_systimer_get();
+}~
+ 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.
+]]
}
}
}
diff --git a/doc/eluadoc/refman_gen_tmr.lua b/doc/eluadoc/refman_gen_tmr.lua
index 4d8a4713..1405bb1a 100644
--- a/doc/eluadoc/refman_gen_tmr.lua
+++ b/doc/eluadoc/refman_gen_tmr.lua
@@ -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.
+ 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$.
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@). NOTE: 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).]],
}
}
From 0e9a3c30431eb6f2766d08d82a07ba5dd5b7ff83 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Wed, 19 Oct 2011 22:58:40 +0300
Subject: [PATCH 59/80] fixed documentation for 'uart' and 'net'
---
doc/eluadoc/refman_gen_net.lua | 18 +++++++++---------
doc/eluadoc/refman_gen_uart.lua | 18 +++++++++---------
2 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/doc/eluadoc/refman_gen_net.lua b/doc/eluadoc/refman_gen_net.lua
index 3f254f8c..2d7859d9 100644
--- a/doc/eluadoc/refman_gen_net.lua
+++ b/doc/eluadoc/refman_gen_net.lua
@@ -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.]],
$"*l"$: read a line (until the next '\n' character).
$an integer$: read up to that many bytes.
]],
- [[$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
diff --git a/doc/eluadoc/refman_gen_uart.lua b/doc/eluadoc/refman_gen_uart.lua
index 6b670a59..297d4067 100644
--- a/doc/eluadoc/refman_gen_uart.lua
+++ b/doc/eluadoc/refman_gen_uart.lua
@@ -53,19 +53,19 @@ to the IDs of the virtual UARTs in the system.]]
}
},
- { sig = "str = #uart.getchar#( id, [timer_id], [timeout] )",
+ { sig = "str = #uart.getchar#( id, [timeout], [timer_id] )",
desc = "Read a single character from the serial port",
args =
{
- "$id$ - the ID of the serial port",
- [[$timer_id (optional)$ - the ID of the timer for the receive operation. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
- [[$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. The default value of this argument is $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."
},
- { sig = "str = #uart.read#( id, format, [timer_id], [timeout] )",
+ { sig = "str = #uart.read#( id, format, [timeout], [timer_id] )",
desc = "Reads one or more characters from the serial port according to a format specifier",
args =
{
@@ -77,9 +77,9 @@ blocking operation, or a positive number that specifies the timeout in microseco
$'*s'$ - read until a spacing character (like a space or a TAB) is found (the spacing character is not returned) or a timeout occurs.
$a positive number$ - read at most this many characters before returning (reading can stop earlier if a timeout occurs).
]],
- [[$timer_id (optional)$ - the ID of the timer for the receive operation. If not specified it defaults to the @arch_platform_timers.html#the_system_timer@system timer@.]],
- [[$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. The default value of this argument is $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]]
},
From c1937777556876648d6229e5c09b497ab8cfb5cf Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 21 Oct 2011 11:55:00 +0300
Subject: [PATCH 60/80] fixed documentation of the UART platform interface
---
doc/eluadoc/arch_platform_uart.lua | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/doc/eluadoc/arch_platform_uart.lua b/doc/eluadoc/arch_platform_uart.lua
index 51896b72..cc85e57f 100644
--- a/doc/eluadoc/arch_platform_uart.lua
+++ b/doc/eluadoc/arch_platform_uart.lua
@@ -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).
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
- $timeout > 0$: the timer with the specified $timer_id$ will be used to timeout the receive operation after $timeout$ microseconds.
- $timeout = 0$: the function returns immediately regardless of data being available or not. $timer_id$ is ignored.
- - $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
+
- $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.
]],
},
@@ -129,11 +123,11 @@ enum
{
"if $timeout > 0$ and data from the UART is available in $timeout$ microseconds of less it is returned, otherwise -1 is returned",
"if $timeout = 0$ and data from the UART is available when the function is called it is returned, otherwise -1 is returned",
- "if $timeout$ = @#uart_timeout@PLATFORM_UART_INIFINITE_TIMEOUT@ it returns the data read from the UART after it becomes available"
+ "if $timeout = PLATFORM_TIMER_INF_TIMEOUT$ it returns the data read from the UART after it becomes available"
}
},
- { sig = "int #platform_s_uart_recv#( unsigned id, s32 timeout );",
+ { sig = "int #platform_s_uart_recv#( unsigned id, timer_data_type timeout );",
link = "platform_s_uart_recv",
desc = [[This is the platform-dependent part of the UART receive function @#platform_uart_recv@platform_uart_recv@ and is in fact a "subset" of the full function
(thus being easier to implement by each platform in part). In particular, it never needs to deal with the $timeout > 0$ case, which is handled by @#platform_uart_recv@platform_uart_recv@.]],
@@ -143,7 +137,7 @@ enum
[[$timeout$ - specifies a timeout for the receive operation as follows:
- $timeout = 0$: the function returns immediately regardless of data being available or not.
- - $timeout$ = @#uart_timeout@PLATFORM_UART_INFINITE_TIMEOUT@: the function waits indefinitely for UART data to be available and returns it.
+ - $timeout = PLATFORM_TIMER_INF_TIMEOUT$: the function waits indefinitely for UART data to be available and returns it.
]],
},
ret =
From 93fdf7b4a6a48d74d514cef896665ca833db44a1 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 21 Oct 2011 13:18:18 +0300
Subject: [PATCH 61/80] updated information about default timer IDs
---
doc/eluadoc/arch_platform_uart.lua | 2 +-
doc/en/arch_rfs.txt | 2 +-
doc/en/arch_tcpip.html | 4 ++--
doc/en/building.txt | 6 ++++--
4 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/doc/eluadoc/arch_platform_uart.lua b/doc/eluadoc/arch_platform_uart.lua
index cc85e57f..4acf4727 100644
--- a/doc/eluadoc/arch_platform_uart.lua
+++ b/doc/eluadoc/arch_platform_uart.lua
@@ -143,7 +143,7 @@ enum
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"
}
},
diff --git a/doc/en/arch_rfs.txt b/doc/en/arch_rfs.txt
index 583dba5c..adbb1479 100644
--- a/doc/en/arch_rfs.txt
+++ b/doc/en/arch_rfs.txt
@@ -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
diff --git a/doc/en/arch_tcpip.html b/doc/en/arch_tcpip.html
index e4393e77..ec3e1f05 100644
--- a/doc/en/arch_tcpip.html
+++ b/doc/en/arch_tcpip.html
@@ -48,8 +48,8 @@ you have a list of parameters that you might want to change:
but doing so when you have to transfer large amounts of data will slow the transfer speed. 1k seems to be a good compromise.
UIP_CONF_UDP: turn off UDP support. While eLua doesn't have support for UDP via its net module at this time, UDP can still
be used (for example by DNS/DHCP), so be careful if you disable this.
- ELUA_DHCP_TIMER_ID: 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).
+ ELUA_DHCP_TIMER_ID: 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 not used, please note that this should be a dedicated timer, not available to the rest of the system (or available in "read-only" mode).
diff --git a/doc/en/building.txt b/doc/en/building.txt
index 10c10cbc..0bd34dc0 100644
--- a/doc/en/building.txt
+++ b/doc/en/building.txt
@@ -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.
@@ -265,6 +266,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 +286,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
From 43f0f2711eb4b64ef01f5474dafda1df5a89c130 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 21 Oct 2011 15:39:44 +0300
Subject: [PATCH 62/80] updated information about the new 'lualonglong' mode
---
doc/en/arch_romfs.html | 4 ++--
doc/en/building.txt | 7 ++++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/doc/en/arch_romfs.html b/doc/en/arch_romfs.html
index e0400ca5..c32489e0 100644
--- a/doc/en/arch_romfs.html
+++ b/doc/en/arch_romfs.html
@@ -68,8 +68,8 @@ $$HEADER$$
(see here for details on cross compilation and its benefits) and the result is written in the eLua binary image. This option
might decrease or increase the physical size of the ROMFS image, but its real benefits are increased speed (because eLua 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).
+ hard to find bugs). NOTE: this option is not available if eLua is compiled in 64-bit integer only mode (lualonglong).
See here for instructions on how to specify the ROMFS compilation mode.
$$FOOTER$$
-
\ No newline at end of file
+
diff --git a/doc/en/building.txt b/doc/en/building.txt
index 0bd34dc0..8ec4b8c2 100644
--- a/doc/en/building.txt
+++ b/doc/en/building.txt
@@ -317,7 +317,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=]
[board=]
[cpumode=arm | thumb]
@@ -338,8 +338,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.
From 3bdb0c9c93a9b54b29517be41e4c93538c45b40f Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Fri, 21 Oct 2011 16:04:15 +0200
Subject: [PATCH 63/80] Pass the right clock to spi_initMaster() - PBA freq not
CPU freq
The AVR32 SPI setup code passed the wrong clock to the SDK's SPI
init function. The result should have been that it set one quarter
of the required frequency.
This change is "obvious" but untested, since the spi.*() module
interface seems not to work yet on AVR32. The MMC card on SPI1
continues to work as it did before, presumably at full speed
instead of quarter speed.
---
src/platform/avr32/platform.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 79e7fad1..bb1c1e9a 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -213,10 +213,10 @@ int platform_init()
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
@@ -637,7 +637,7 @@ 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);
+ spi_setupChipReg((volatile avr32_spi_t *) spireg[id >> 2], id % 4, &opt, REQ_PBA_FREQ);
// TODO: return the actual baudrate.
return clock;
From 854e4f5cfa48f6a13ae427d8fc22f1886d4036d8 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Fri, 21 Oct 2011 16:12:23 +0200
Subject: [PATCH 64/80] aAdd commentary about second use of CPU_FREQUENCY macro
---
src/platform/at91sam7x/platform_conf.h | 2 +-
src/platform/avr32/EVK1100/evk1100_conf.h | 2 +-
src/platform/avr32/EVK1101/evk1101_conf.h | 2 +-
src/platform/avr32/MIZAR32/mizar32_conf.h | 2 +-
src/platform/i386/platform_conf.h | 2 +-
src/platform/lm3s/platform_conf.h | 2 +-
src/platform/lpc17xx/platform_conf.h | 2 +-
src/platform/lpc24xx/platform_conf.h | 2 +-
src/platform/lpc288x/platform_conf.h | 2 +-
src/platform/sim/platform_conf.h | 2 +-
src/platform/stm32/platform_conf.h | 2 +-
src/platform/str7/platform_conf.h | 2 +-
src/platform/str9/platform_conf.h | 2 +-
13 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/platform/at91sam7x/platform_conf.h b/src/platform/at91sam7x/platform_conf.h
index ae8c9441..aca56157 100644
--- a/src/platform/at91sam7x/platform_conf.h
+++ b/src/platform/at91sam7x/platform_conf.h
@@ -89,7 +89,7 @@
#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, ...)
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index cedb122e..e9731601 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -146,7 +146,7 @@
#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, ...)
diff --git a/src/platform/avr32/EVK1101/evk1101_conf.h b/src/platform/avr32/EVK1101/evk1101_conf.h
index c62860cb..896f8190 100644
--- a/src/platform/avr32/EVK1101/evk1101_conf.h
+++ b/src/platform/avr32/EVK1101/evk1101_conf.h
@@ -111,7 +111,7 @@
#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, ...)
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index 6b588f68..ecdaa68b 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -195,7 +195,7 @@
#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, ...)
diff --git a/src/platform/i386/platform_conf.h b/src/platform/i386/platform_conf.h
index 2098a4cf..aa7c1373 100644
--- a/src/platform/i386/platform_conf.h
+++ b/src/platform/i386/platform_conf.h
@@ -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, ...)
diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h
index d1e0a8cf..62b4f510 100644
--- a/src/platform/lm3s/platform_conf.h
+++ b/src/platform/lm3s/platform_conf.h
@@ -231,7 +231,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, ...)
diff --git a/src/platform/lpc17xx/platform_conf.h b/src/platform/lpc17xx/platform_conf.h
index 0cd935be..645a95a2 100644
--- a/src/platform/lpc17xx/platform_conf.h
+++ b/src/platform/lpc17xx/platform_conf.h
@@ -104,7 +104,7 @@
#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)
+// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY 100000000
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
diff --git a/src/platform/lpc24xx/platform_conf.h b/src/platform/lpc24xx/platform_conf.h
index 56f97328..c73fafff 100644
--- a/src/platform/lpc24xx/platform_conf.h
+++ b/src/platform/lpc24xx/platform_conf.h
@@ -111,7 +111,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, ...)
diff --git a/src/platform/lpc288x/platform_conf.h b/src/platform/lpc288x/platform_conf.h
index 773fb22c..a559c1bc 100644
--- a/src/platform/lpc288x/platform_conf.h
+++ b/src/platform/lpc288x/platform_conf.h
@@ -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, ...)
diff --git a/src/platform/sim/platform_conf.h b/src/platform/sim/platform_conf.h
index ba85a67c..90b62d53 100644
--- a/src/platform/sim/platform_conf.h
+++ b/src/platform/sim/platform_conf.h
@@ -49,7 +49,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, ...)
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index 48ede866..3b151d40 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -146,7 +146,7 @@
#define MMCFS_CS_PIN 8
#define MMCFS_SPI_NUM 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)
u32 platform_s_cpu_get_frequency();
#define CPU_FREQUENCY platform_s_cpu_get_frequency()
diff --git a/src/platform/str7/platform_conf.h b/src/platform/str7/platform_conf.h
index e40bffc8..fd095e94 100644
--- a/src/platform/str7/platform_conf.h
+++ b/src/platform/str7/platform_conf.h
@@ -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, ...)
diff --git a/src/platform/str9/platform_conf.h b/src/platform/str9/platform_conf.h
index 3c02dd47..e657afdf 100644
--- a/src/platform/str9/platform_conf.h
+++ b/src/platform/str9/platform_conf.h
@@ -77,7 +77,7 @@
// 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 )
From c98474e357bfc1eb253a456cbd1526c0446a93e0 Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 21 Oct 2011 21:08:33 +0300
Subject: [PATCH 65/80] added per platform information about system timer
support
---
doc/docdata.lua | 1 +
doc/eluadoc/arch_platform_timers.lua | 5 +++++
doc/en/status.txt | 21 +++++++++++++++++++++
3 files changed, 27 insertions(+)
diff --git a/doc/docdata.lua b/doc/docdata.lua
index 2d53e872..f9b1e398 100644
--- a/doc/docdata.lua
+++ b/doc/docdata.lua
@@ -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" }
diff --git a/doc/eluadoc/arch_platform_timers.lua b/doc/eluadoc/arch_platform_timers.lua
index b006bfd7..4b11e79f 100644
--- a/doc/eluadoc/arch_platform_timers.lua
+++ b/doc/eluadoc/arch_platform_timers.lua
@@ -343,6 +343,11 @@ interrupt %period% (in microseconds) instead of its frequency. Use the latter fo
return cmn_systimer_get();
}~
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.
+ IMPORTANT NOTE: 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:
+ ~#warning This platform does not have a system timer. Your eLua image might not work as expected.~
]]
}
}
diff --git a/doc/en/status.txt b/doc/en/status.txt
index 56ff447b..d9a39c38 100644
--- a/doc/en/status.txt
+++ b/doc/en/status.txt
@@ -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
-------------------
From 1486c515081981d1dee3ef23e2ac6e89d6e9fc0b Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Fri, 21 Oct 2011 21:22:16 +0300
Subject: [PATCH 66/80] started to update CHANGELOG for the new release
---
CHANGELOG | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index a8a25517..6ce25e1f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+xx.yy.zzzz Bogdan Marinescu
+ Dado Sutter
+ James Snyder
+
+ * Official release 0.9
+ * New feature: system timer ([TODO] add link)
+
02.02.2011 Bogdan Marinescu
Dado Sutter
James Snyder
From c4f7fe94c13b138cba516503a1e7e3b5126082e1 Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Fri, 21 Oct 2011 18:08:43 -0500
Subject: [PATCH 67/80] Adjust MMCFS to use the system timer
---
doc/en/building.txt | 6 +--
inc/validate.h | 10 ----
src/elua_mmc.c | 64 ++++++-----------------
src/fatfs/diskio.h | 1 -
src/platform/avr32/EVK1100/evk1100_conf.h | 2 -
src/platform/avr32/EVK1101/evk1101_conf.h | 2 -
src/platform/avr32/MIZAR32/mizar32_conf.h | 2 -
src/platform/avr32/platform.c | 4 --
src/platform/lm3s/platform.c | 8 ---
src/platform/lm3s/platform_conf.h | 4 --
src/platform/lpc17xx/platform.c | 4 --
src/platform/stm32/platform.c | 4 --
src/platform/stm32/platform_conf.h | 4 +-
13 files changed, 18 insertions(+), 97 deletions(-)
diff --git a/doc/en/building.txt b/doc/en/building.txt
index 8ec4b8c2..39178df3 100644
--- a/doc/en/building.txt
+++ b/doc/en/building.txt
@@ -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.
@@ -230,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.
diff --git a/inc/validate.h b/inc/validate.h
index bbd6e45d..0e7d3889 100644
--- a/inc/validate.h
+++ b/inc/validate.h
@@ -74,16 +74,6 @@
#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"
-#endif
-
// CON_BUF_SIZE needs BUF_ENABLE_UART and CON_UART_ID
#if defined( CON_BUF_SIZE )
#if !defined( BUF_ENABLE_UART )
diff --git a/src/elua_mmc.c b/src/elua_mmc.c
index 2208682a..7c97e6d3 100644
--- a/src/elua_mmc.c
+++ b/src/elua_mmc.c
@@ -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, Timer1 ) < 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 */
/*---------------------------------------------------------*/
diff --git a/src/fatfs/diskio.h b/src/fatfs/diskio.h
index 4e21e529..6fde2dde 100644
--- a/src/fatfs/diskio.h
+++ b/src/fatfs/diskio.h
@@ -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);
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index 6f934ccd..64228112 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -138,8 +138,6 @@
#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
diff --git a/src/platform/avr32/EVK1101/evk1101_conf.h b/src/platform/avr32/EVK1101/evk1101_conf.h
index e0263c3e..574b0d8a 100644
--- a/src/platform/avr32/EVK1101/evk1101_conf.h
+++ b/src/platform/avr32/EVK1101/evk1101_conf.h
@@ -103,8 +103,6 @@
#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
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index 9177e383..bb9a58e9 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -187,8 +187,6 @@
#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
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index b1fbd4da..a6769ab1 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -130,10 +130,6 @@ __attribute__((__interrupt__)) static void tmr_int_handler()
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;
diff --git a/src/platform/lm3s/platform.c b/src/platform/lm3s/platform.c
index c0f67d34..90f9a0c4 100644
--- a/src/platform/lm3s/platform.c
+++ b/src/platform/lm3s/platform.c
@@ -1044,10 +1044,6 @@ 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;
@@ -1077,10 +1073,6 @@ void SysTickIntHandler()
{
cmn_virtual_timer_cb();
-#ifdef BUILD_MMCFS
- disk_timerproc();
-#endif
-
// System timer handling
cmn_systimer_periodic();
}
diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h
index 4e90c9e7..1b142057 100644
--- a/src/platform/lm3s/platform_conf.h
+++ b/src/platform/lm3s/platform_conf.h
@@ -201,10 +201,6 @@
#define RPC_UART_ID CON_UART_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
diff --git a/src/platform/lpc17xx/platform.c b/src/platform/lpc17xx/platform.c
index 75b06b2a..33a15c8a 100644
--- a/src/platform/lpc17xx/platform.c
+++ b/src/platform/lpc17xx/platform.c
@@ -93,10 +93,6 @@ void SysTick_Handler()
// Handle virtual timers
cmn_virtual_timer_cb();
-#ifdef BUILD_MMCFS
- disk_timerproc();
-#endif
-
// Handle system timer call
cmn_systimer_periodic();
}
diff --git a/src/platform/stm32/platform.c b/src/platform/stm32/platform.c
index d5ddf3c2..2dd8de07 100755
--- a/src/platform/stm32/platform.c
+++ b/src/platform/stm32/platform.c
@@ -711,10 +711,6 @@ void SysTick_Handler( void )
// Handle virtual timers
cmn_virtual_timer_cb();
-#ifdef BUILD_MMCFS
- disk_timerproc();
-#endif
-
// Handle system timer call
cmn_systimer_periodic();
}
diff --git a/src/platform/stm32/platform_conf.h b/src/platform/stm32/platform_conf.h
index 17503a6a..198141cc 100755
--- a/src/platform/stm32/platform_conf.h
+++ b/src/platform/stm32/platform_conf.h
@@ -140,13 +140,11 @@
// 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
-// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
+// CPU frequency (needed by the CPU module, 0 if not used)
u32 platform_s_cpu_get_frequency();
#define CPU_FREQUENCY platform_s_cpu_get_frequency()
From b7b6a6e7ebd5deb1a4d0323ec0d8e463827487a9 Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Fri, 21 Oct 2011 18:15:14 -0500
Subject: [PATCH 68/80] Add build-time check for system timer for MMCFS
---
inc/validate.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/inc/validate.h b/inc/validate.h
index 0e7d3889..e94b0347 100644
--- a/inc/validate.h
+++ b/inc/validate.h
@@ -74,6 +74,10 @@
#endif
#endif
+#if defined( BUILD_MMCFS ) && !defined( PLATFORM_HAS_SYSTIMER )
+ #error "BUILD_MMCFS needs system timer support. Ensure your platform has this implemented and PLATFORM_HAS_SYSTIMER is defined"
+#endif
+
// CON_BUF_SIZE needs BUF_ENABLE_UART and CON_UART_ID
#if defined( CON_BUF_SIZE )
#if !defined( BUF_ENABLE_UART )
From ced77664e953b0693dd6bc3744512b461cfca02a Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 22 Oct 2011 17:00:31 +0200
Subject: [PATCH 69/80] Revert "Pass the right clock to spi_initMaster() - PBA
freq not CPU freq"
This reverts commit 3bdb0c9c93a9b54b29517be41e4c93538c45b40f.
which stopped the MMC card working on Mizar32.
---
src/platform/avr32/platform.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index a6769ab1..4ab124fe 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -257,10 +257,10 @@ int platform_init()
spiopt.modfdis = TRUE;
spiopt.pcs_decode = FALSE;
spiopt.delay = 0;
- spi_initMaster(&AVR32_SPI0, &spiopt, REQ_PBA_FREQ);
+ spi_initMaster(&AVR32_SPI0, &spiopt, REQ_CPU_FREQ);
#if NUM_SPI > 4
- spi_initMaster(&AVR32_SPI1, &spiopt, REQ_PBA_FREQ);
+ spi_initMaster(&AVR32_SPI1, &spiopt, REQ_CPU_FREQ);
#endif
#endif
@@ -710,7 +710,7 @@ 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_PBA_FREQ);
+ spi_setupChipReg((volatile avr32_spi_t *) spireg[id >> 2], id % 4, &opt, REQ_CPU_FREQ);
// TODO: return the actual baudrate.
return clock;
From 024efa748554ebfd1f0e49489fb2b97850830067 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 22 Oct 2011 19:20:19 +0200
Subject: [PATCH 70/80] Fix AVR32 SPI initialization
This fixes the following AVR32 SPI clock setting bugs:
- it used to set the SPI frequency at a quarter of what you asked for
(by calculating it from the wrong clock)
- it did not report what actual frequency it had set
- spi.setup() always seemed to succeed even if it failed
- it used to set the nearest frequency instead of the next lowest available
so half the time would drive devices at higher than their maximum speed.
This was hidden by it always setting a quarter of what you asked for (!)
- it would set a junk frequency if you asked for a clock lower than its minimum
- asking for a baud rate of zero made it divide by zero, which went undetected
and set a random baud rate instead of the minimum available
- Now, if you ask for an invalid number of data bits (< 8 or > 16),
spi.setup() returns zero.
This is still wrong and undocumented.
It should give an error message in platform-independent spi_setup() and stop
but unfortunately the current code structure does not allow this, since the
possible numbers of data bits is platform-specific.
---
src/platform/avr32/platform.c | 10 ++++----
src/platform/avr32/spi.c | 45 +++++++++++++++++------------------
src/platform/avr32/spi.h | 2 +-
3 files changed, 27 insertions(+), 30 deletions(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 4ab124fe..72486beb 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -257,10 +257,10 @@ int platform_init()
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
@@ -710,10 +710,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 )
diff --git a/src/platform/avr32/spi.c b/src/platform/avr32/spi.c
index 7c76ed19..329d1954 100644
--- a/src/platform/avr32/spi.c
+++ b/src/platform/avr32/spi.c
@@ -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));
}
diff --git a/src/platform/avr32/spi.h b/src/platform/avr32/spi.h
index 780aa1f5..e872c640 100644
--- a/src/platform/avr32/spi.h
+++ b/src/platform/avr32/spi.h
@@ -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);
From c36309d185f95629d49f5ec35530c1e1e07980d3 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 22 Oct 2011 19:38:37 +0200
Subject: [PATCH 71/80] Remove unused variable
---
src/platform/avr32/platform.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 72486beb..72ab8e70 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -817,7 +817,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;
From 6c655e6e5788766ad32f8ee951df8ad93acf6971 Mon Sep 17 00:00:00 2001
From: Martin Guy
Date: Sat, 22 Oct 2011 20:01:03 +0200
Subject: [PATCH 72/80] Raise Mizar32 CPU freq from 60 to 66MHz and PBA from 15
to 16.5
All derived frequencies (sdram, USB, tmr, VTMRs, SPI, UARTs, PWM, MMC,
and ethernet) compensate correctly for the different PBA freq and
tmr.getmaxdelay() is still just over 0.5 sec (by a hair!).
This may work for EVK110X too - the reason they chose 60MHz is unknown.
---
src/platform/avr32/board.h | 9 +++++++++
src/platform/avr32/ethernet.h | 2 +-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/platform/avr32/board.h b/src/platform/avr32/board.h
index b45a4c35..55bf0daa 100644
--- a/src/platform/avr32/board.h
+++ b/src/platform/avr32/board.h
@@ -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_
diff --git a/src/platform/avr32/ethernet.h b/src/platform/avr32/ethernet.h
index 7eeab831..a5aa4cff 100644
--- a/src/platform/avr32/ethernet.h
+++ b/src/platform/avr32/ethernet.h
@@ -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
From 8c0f82198f5371d40bc0f9526dbaaa6840450d5a Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Mon, 24 Oct 2011 19:11:35 -0500
Subject: [PATCH 73/80] Fix CRLF
---
inc/eluarpc.h | 130 ++--
src/eluarpc.c | 718 ++++++++++-----------
src/platform/avr32/ethernet.c | 1118 ++++++++++++++++-----------------
src/platform/avr32/ethernet.h | 20 +-
4 files changed, 993 insertions(+), 993 deletions(-)
diff --git a/inc/eluarpc.h b/inc/eluarpc.h
index 83aa0a20..8c4fc0da 100644
--- a/inc/eluarpc.h
+++ b/inc/eluarpc.h
@@ -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
diff --git a/src/eluarpc.c b/src/eluarpc.c
index b72ed920..3c0811bc 100644
--- a/src/eluarpc.c
+++ b/src/eluarpc.c
@@ -1,359 +1,359 @@
-// eLua RPC mechanism
-
-#include
-#include
-#include
-#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
+#include
+#include
+#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;
+}
diff --git a/src/platform/avr32/ethernet.c b/src/platform/avr32/ethernet.c
index 2cd139d8..a0d6fc44 100644
--- a/src/platform/avr32/ethernet.c
+++ b/src/platform/avr32/ethernet.c
@@ -62,588 +62,588 @@
#include "ethernet.h"
-/* Size of each receive buffer - DO NOT CHANGE. */
-#define RX_BUFFER_SIZE 128
-
-
-/* The buffer addresses written into the descriptors must be aligned so the
-last two bits are zero. These bits have special meaning for the MACB
-peripheral and cannot be used as part of the address. */
-#define ADDRESS_MASK ( ( unsigned long ) 0xFFFFFFFC )
-
-/* Bit used within the address stored in the descriptor to mark the last
-descriptor in the array. */
-#define RX_WRAP_BIT ( ( unsigned long ) 0x02 )
-
-/* A short delay is used to wait for a buffer to become available, should
-one not be immediately available when trying to transmit a frame. */
+/* Size of each receive buffer - DO NOT CHANGE. */
+#define RX_BUFFER_SIZE 128
+
+
+/* The buffer addresses written into the descriptors must be aligned so the
+last two bits are zero. These bits have special meaning for the MACB
+peripheral and cannot be used as part of the address. */
+#define ADDRESS_MASK ( ( unsigned long ) 0xFFFFFFFC )
+
+/* Bit used within the address stored in the descriptor to mark the last
+descriptor in the array. */
+#define RX_WRAP_BIT ( ( unsigned long ) 0x02 )
+
+/* A short delay is used to wait for a buffer to become available, should
+one not be immediately available when trying to transmit a frame. */
#define BUFFER_WAIT_DELAY ( 2 )
#include "ethernet.h"
#include "intc.h"
#include "elua_uip.h"
-#ifndef FREERTOS_USED
-#define portENTER_CRITICAL Disable_global_interrupt
-#define portEXIT_CRITICAL Enable_global_interrupt
-#define portENTER_SWITCHING_ISR()
-#define portEXIT_SWITCHING_ISR()
+#ifndef FREERTOS_USED
+#define portENTER_CRITICAL Disable_global_interrupt
+#define portEXIT_CRITICAL Enable_global_interrupt
+#define portENTER_SWITCHING_ISR()
+#define portEXIT_SWITCHING_ISR()
#endif
-
+
#define TIMEOUT 500
-/* Buffer written to by the MACB DMA. Must be aligned as described by the
+/* Buffer written to by the MACB DMA. Must be aligned as described by the
comment above the ADDRESS_MASK definition. */
static volatile char pcRxBuffer[ ETHERNET_CONF_NB_RX_BUFFERS * RX_BUFFER_SIZE ] __attribute__ ((aligned (4)));
-/* Buffer read by the MACB DMA. Must be aligned as described by the comment
+/* Buffer read by the MACB DMA. Must be aligned as described by the comment
above the ADDRESS_MASK definition. */
-
-static volatile char pcTxBuffer[ ETHERNET_CONF_NB_TX_BUFFERS * ETHERNET_CONF_TX_BUFFER_SIZE ] __attribute__ ((aligned (4)));
-/* Descriptors used to communicate between the program and the MACB peripheral.
-These descriptors hold the locations and state of the Rx and Tx buffers.
-Alignment value chosen from RBQP and TBQP registers description in datasheet. */
-
-static volatile AVR32_TxTdDescriptor xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS ] __attribute__ ((aligned (8)));
-static volatile AVR32_RxTdDescriptor xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS ] __attribute__ ((aligned (8)));
-
-/* The IP and Ethernet addresses are read from the header files. */
-unsigned char cMACAddress[ 6 ] = { ETHERNET_CONF_ETHADDR0,ETHERNET_CONF_ETHADDR1,ETHERNET_CONF_ETHADDR2,ETHERNET_CONF_ETHADDR3,ETHERNET_CONF_ETHADDR4,ETHERNET_CONF_ETHADDR5 };
-
-/*-----------------------------------------------------------*/
-
-/* See the header file for descriptions of public functions. */
-
-/*
- * Prototype for the MACB interrupt function - called by the asm wrapper.
+static volatile char pcTxBuffer[ ETHERNET_CONF_NB_TX_BUFFERS * ETHERNET_CONF_TX_BUFFER_SIZE ] __attribute__ ((aligned (4)));
+
+/* Descriptors used to communicate between the program and the MACB peripheral.
+These descriptors hold the locations and state of the Rx and Tx buffers.
+Alignment value chosen from RBQP and TBQP registers description in datasheet. */
+
+static volatile AVR32_TxTdDescriptor xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS ] __attribute__ ((aligned (8)));
+static volatile AVR32_RxTdDescriptor xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS ] __attribute__ ((aligned (8)));
+
+/* The IP and Ethernet addresses are read from the header files. */
+unsigned char cMACAddress[ 6 ] = { ETHERNET_CONF_ETHADDR0,ETHERNET_CONF_ETHADDR1,ETHERNET_CONF_ETHADDR2,ETHERNET_CONF_ETHADDR3,ETHERNET_CONF_ETHADDR4,ETHERNET_CONF_ETHADDR5 };
+
+/*-----------------------------------------------------------*/
+
+/* See the header file for descriptions of public functions. */
+
+/*
+ * Prototype for the MACB interrupt function - called by the asm wrapper.
*/
-__attribute__((__interrupt__)) void vMACB_ISR(void);
+__attribute__((__interrupt__)) void vMACB_ISR(void);
/*
* Initialise both the Tx and Rx descriptors used by the MACB.
*/
-static void prvSetupDescriptors(volatile avr32_macb_t *macb);
+static void prvSetupDescriptors(volatile avr32_macb_t *macb);
//
// Restore ownership of all Rx buffers to the MACB.
//
-static void vResetMacbRxFrames( void );
+static void vResetMacbRxFrames( void );
/*
* Write our MAC address into the MACB.
*/
-static void prvSetupMACAddress(volatile avr32_macb_t *macb);
+static void prvSetupMACAddress(volatile avr32_macb_t *macb);
/*
* Configure the MACB for interrupts.
*/
-static void prvSetupMACBInterrupt(volatile avr32_macb_t *macb);
+static void prvSetupMACBInterrupt(volatile avr32_macb_t *macb);
/*
* Some initialisation functions.
*/
-static Bool prvProbePHY(volatile avr32_macb_t *macb);
-static unsigned long ulReadMDIO(volatile avr32_macb_t *macb, unsigned short usAddress);
-static void vWriteMDIO(volatile avr32_macb_t *macb, unsigned short usAddress, unsigned short usValue);
+static Bool prvProbePHY(volatile avr32_macb_t *macb);
+static unsigned long ulReadMDIO(volatile avr32_macb_t *macb, unsigned short usAddress);
+static void vWriteMDIO(volatile avr32_macb_t *macb, unsigned short usAddress, unsigned short usValue);
+
-
/* Holds the index to the next buffer from which data will be read. */
volatile unsigned long ulNextRxBuffer = 0;
-
-long lMACBSend(volatile avr32_macb_t *macb, const void *pvFrom, unsigned long ulLength, long lEndOfFrame)
-{
- const unsigned char *pcFrom = pvFrom;
- static unsigned long uxTxBufferIndex = 0;
- void *pcBuffer;
- unsigned long ulLastBuffer, ulDataBuffered = 0, ulDataRemainingToSend, ulLengthToSend;
-
- /* If the length of data to be transmitted is greater than each individual
- transmit buffer then the data will be split into more than one buffer.
- Loop until the entire length has been buffered. */
- while( ulDataBuffered < ulLength )
- {
- // Is a buffer available ?
- while( !( xTxDescriptors[ uxTxBufferIndex ].U_Status.status & AVR32_TRANSMIT_OK ) )
- {
- // There is no room to write the Tx data to the Tx buffer.
- // Wait a short while, then try again.
- __asm__ __volatile__ ("nop");
- }
-
- portENTER_CRITICAL();
- {
- // Get the address of the buffer from the descriptor,
- // then copy the data into the buffer.
- pcBuffer = ( void * ) xTxDescriptors[ uxTxBufferIndex ].addr;
-
- // How much can we write to the buffer ?
- ulDataRemainingToSend = ulLength - ulDataBuffered;
- if( ulDataRemainingToSend <= ETHERNET_CONF_TX_BUFFER_SIZE )
- {
- // We can write all the remaining bytes.
- ulLengthToSend = ulDataRemainingToSend;
- }
- else
- {
- // We can't write more than ETH_TX_BUFFER_SIZE in one go.
- ulLengthToSend = ETHERNET_CONF_TX_BUFFER_SIZE;
- }
- // Copy the data into the buffer.
- memcpy( pcBuffer, &( pcFrom[ ulDataBuffered ] ), ulLengthToSend );
- ulDataBuffered += ulLengthToSend;
- // Is this the last data for the frame ?
- if( lEndOfFrame && ( ulDataBuffered >= ulLength ) )
- {
- // No more data remains for this frame so we can start the transmission.
- ulLastBuffer = AVR32_LAST_BUFFER;
- }
- else
- {
- // More data to come for this frame.
- ulLastBuffer = 0;
- }
- // Fill out the necessary in the descriptor to get the data sent,
- // then move to the next descriptor, wrapping if necessary.
- if( uxTxBufferIndex >= ( ETHERNET_CONF_NB_TX_BUFFERS - 1 ) )
- {
- xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
- | ulLastBuffer
- | AVR32_TRANSMIT_WRAP;
- uxTxBufferIndex = 0;
- } else
- {
- xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
- | ulLastBuffer;
- uxTxBufferIndex++;
- }
- /* If this is the last buffer to be sent for this frame we can
- start the transmission. */
- if( ulLastBuffer )
- macb->ncr |= AVR32_MACB_TSTART_MASK;
-
- }
- portEXIT_CRITICAL();
- }
-
- return PASS;
-}
-
-
-unsigned long ulMACBInputLength(void)
-{
- register unsigned long ulIndex , ulLength = 0;
- unsigned int uiTemp;
- volatile unsigned long ulEventStatus;
-
- // Check if the MACB encountered a problem.
- ulEventStatus = AVR32_MACB.rsr;
- if( ulEventStatus & AVR32_MACB_RSR_BNA_MASK )
- { // MACB couldn't get ownership of a buffer. This could typically
- // happen if the total numbers of Rx buffers is tailored too small
- // for a noisy network with big frames.
- // We might as well restore ownership of all buffers to the MACB to
- // restart from a clean state.
- vResetMacbRxFrames();
- return( ulLength );
- }
-
- // Skip any fragments. We are looking for the first buffer that contains
- // data and has the SOF (start of frame) bit set.
- while( ( xRxDescriptors[ ulNextRxBuffer ].addr & AVR32_OWNERSHIP_BIT )
- && !( xRxDescriptors[ ulNextRxBuffer ].U_Status.status & AVR32_SOF ) )
- {
- // Ignoring this buffer. Mark it as free again.
- uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
- xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
- ulNextRxBuffer++;
- if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
- {
- ulNextRxBuffer = 0;
- }
- }
-
- // We are going to walk through the descriptors that make up this frame,
- // but don't want to alter ulNextRxBuffer as this would prevent vMACBRead()
- // from finding the data. Therefore use a copy of ulNextRxBuffer instead.
- ulIndex = ulNextRxBuffer;
-
- // Walk through the descriptors until we find the last buffer for this frame.
- // The last buffer will give us the length of the entire frame.
- while ( xRxDescriptors[ ulIndex ].addr & AVR32_OWNERSHIP_BIT )
- {
- ulLength = xRxDescriptors[ ulIndex ].U_Status.status & AVR32_LENGTH_FRAME;
- if (ulLength) break; //return ulLength
-
- // Increment to the next buffer, wrapping if necessary.
- if( ++ulIndex >= ETHERNET_CONF_NB_RX_BUFFERS ) ulIndex = 0;
-
- // Is the descriptor valid?
- if (!(xRxDescriptors[ ulIndex ].addr & AVR32_OWNERSHIP_BIT)) break; //return 0
-
- // Is it a SOF? If so, the head packet is bad and should be discarded
- if (xRxDescriptors[ ulIndex ].U_Status.status & AVR32_SOF)
- {
- // Mark the buffers of the CURRENT, FAULTY packet available.
- unsigned int i = ulNextRxBuffer;
- do{
- // Ignore the faulty frame. Mark its buffers as owned by the MACB.
- uiTemp = xRxDescriptors[ i ].addr;
- xRxDescriptors[ i ].addr = uiTemp & ~(AVR32_OWNERSHIP_BIT);
- if (++i>=ETHERNET_CONF_NB_RX_BUFFERS) i=0;
- }while (i!=ulIndex);
- ulNextRxBuffer=ulIndex;
- // We have the start of a new packet, look at that one instead.
- }
- }
- return ulLength;
-}
-/*-----------------------------------------------------------*/
-
-void vMACBRead(void *pvTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength)
-{
- unsigned char *pcTo = pvTo;
- static unsigned long ulSectionBytesReadSoFar = 0, ulBufferPosition = 0, ulFrameBytesReadSoFar = 0;
- static const unsigned char *pcSource;
- register unsigned long ulBytesRemainingInBuffer, ulRemainingSectionBytes;
- unsigned int uiTemp;
-
- // Read ulSectionLength bytes from the Rx buffers.
- // This is not necessarily any correspondence between the length of our Rx buffers,
- // and the length of the data we are returning or the length of the data being requested.
- // Therefore, between calls we have to remember not only which buffer we are currently
- // processing, but our position within that buffer.
- // This would be greatly simplified if PBUF_POOL_BUFSIZE could be guaranteed to be greater
- // than the size of each Rx buffer, and that memory fragmentation did not occur.
-
- // This function should only be called after a call to ulMACBInputLength().
- // This will ensure ulNextRxBuffer is set to the correct buffer. */
-
- // vMACBRead is called with pcTo set to NULL to indicate that we are about
- // to read a new frame. Any fragments remaining in the frame we were
- // processing during the last call should be dropped.
- if( pcTo == NULL )
- {
- // How many bytes are indicated as being in this buffer?
- // If none then the buffer is completely full and the frame is contained within more
- // than one buffer.
- // Reset our state variables ready for the next read from this buffer.
- pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
- ulFrameBytesReadSoFar = ( unsigned long ) 0;
- ulBufferPosition = ( unsigned long ) 0;
- }
- else
- {
- // Loop until we have obtained the required amount of data.
- ulSectionBytesReadSoFar = 0;
- while( ulSectionBytesReadSoFar < ulSectionLength )
- {
- // We may have already read some data from this buffer.
- // How much data remains in the buffer?
- ulBytesRemainingInBuffer = ( RX_BUFFER_SIZE - ulBufferPosition );
-
- // How many more bytes do we need to read before we have the
- // required amount of data?
- ulRemainingSectionBytes = ulSectionLength - ulSectionBytesReadSoFar;
-
- // Do we want more data than remains in the buffer?
- if( ulRemainingSectionBytes > ulBytesRemainingInBuffer )
- {
- // We want more data than remains in the buffer so we can
- // write the remains of the buffer to the destination, then move
- // onto the next buffer to get the rest.
- memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulBytesRemainingInBuffer );
- ulSectionBytesReadSoFar += ulBytesRemainingInBuffer;
- ulFrameBytesReadSoFar += ulBytesRemainingInBuffer;
-
- // Mark the buffer as free again.
- uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
- xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
- // Move onto the next buffer.
- ulNextRxBuffer++;
-
- if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
- {
- ulNextRxBuffer = ( unsigned long ) 0;
- }
-
- // Reset the variables for the new buffer.
- pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
- ulBufferPosition = ( unsigned long ) 0;
- }
- else
- {
- // We have enough data in this buffer to send back.
- // Read out enough data and remember how far we read up to.
- memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulRemainingSectionBytes );
-
- // There may be more data in this buffer yet.
- // Increment our position in this buffer past the data we have just read.
- ulBufferPosition += ulRemainingSectionBytes;
- ulSectionBytesReadSoFar += ulRemainingSectionBytes;
- ulFrameBytesReadSoFar += ulRemainingSectionBytes;
-
- // Have we now finished with this buffer?
- if( ( ulBufferPosition >= RX_BUFFER_SIZE ) || ( ulFrameBytesReadSoFar >= ulTotalFrameLength ) )
- {
- // Mark the buffer as free again.
- uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
- xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
- // Move onto the next buffer.
- ulNextRxBuffer++;
-
- if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
- {
- ulNextRxBuffer = 0;
- }
-
- pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
- ulBufferPosition = 0;
- }
- }
- }
- }
-}
-
-/*-----------------------------------------------------------*/
-void vMACBFlushCurrentPacket(unsigned long ulTotalFrameLength)
-{
- unsigned int uiTemp;
- long int lTotalFrameLen = (long int)ulTotalFrameLength;
-
- while( lTotalFrameLen > 0 )
- {
- // Ignoring this buffer. Mark it as free again.
- uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
- xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
-
- // Move on to the next buffer.
- ulNextRxBuffer++;
- ulNextRxBuffer = ulNextRxBuffer%ETHERNET_CONF_NB_RX_BUFFERS;
-
- lTotalFrameLen -= RX_BUFFER_SIZE;
- }
-}
-
-
-/*-----------------------------------------------------------*/
-void vMACBSetMACAddress(const unsigned char *MACAddress)
-{
- memcpy(cMACAddress, MACAddress, sizeof(cMACAddress));
-}
-
-Bool xMACBInit(volatile avr32_macb_t *macb)
-{
- Bool global_interrupt_enabled = Is_global_interrupt_enabled();
- volatile unsigned long status;
+
+long lMACBSend(volatile avr32_macb_t *macb, const void *pvFrom, unsigned long ulLength, long lEndOfFrame)
+{
+ const unsigned char *pcFrom = pvFrom;
+ static unsigned long uxTxBufferIndex = 0;
+ void *pcBuffer;
+ unsigned long ulLastBuffer, ulDataBuffered = 0, ulDataRemainingToSend, ulLengthToSend;
+
+ /* If the length of data to be transmitted is greater than each individual
+ transmit buffer then the data will be split into more than one buffer.
+ Loop until the entire length has been buffered. */
+ while( ulDataBuffered < ulLength )
+ {
+ // Is a buffer available ?
+ while( !( xTxDescriptors[ uxTxBufferIndex ].U_Status.status & AVR32_TRANSMIT_OK ) )
+ {
+ // There is no room to write the Tx data to the Tx buffer.
+ // Wait a short while, then try again.
+ __asm__ __volatile__ ("nop");
+ }
+
+ portENTER_CRITICAL();
+ {
+ // Get the address of the buffer from the descriptor,
+ // then copy the data into the buffer.
+ pcBuffer = ( void * ) xTxDescriptors[ uxTxBufferIndex ].addr;
+
+ // How much can we write to the buffer ?
+ ulDataRemainingToSend = ulLength - ulDataBuffered;
+ if( ulDataRemainingToSend <= ETHERNET_CONF_TX_BUFFER_SIZE )
+ {
+ // We can write all the remaining bytes.
+ ulLengthToSend = ulDataRemainingToSend;
+ }
+ else
+ {
+ // We can't write more than ETH_TX_BUFFER_SIZE in one go.
+ ulLengthToSend = ETHERNET_CONF_TX_BUFFER_SIZE;
+ }
+ // Copy the data into the buffer.
+ memcpy( pcBuffer, &( pcFrom[ ulDataBuffered ] ), ulLengthToSend );
+ ulDataBuffered += ulLengthToSend;
+ // Is this the last data for the frame ?
+ if( lEndOfFrame && ( ulDataBuffered >= ulLength ) )
+ {
+ // No more data remains for this frame so we can start the transmission.
+ ulLastBuffer = AVR32_LAST_BUFFER;
+ }
+ else
+ {
+ // More data to come for this frame.
+ ulLastBuffer = 0;
+ }
+ // Fill out the necessary in the descriptor to get the data sent,
+ // then move to the next descriptor, wrapping if necessary.
+ if( uxTxBufferIndex >= ( ETHERNET_CONF_NB_TX_BUFFERS - 1 ) )
+ {
+ xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
+ | ulLastBuffer
+ | AVR32_TRANSMIT_WRAP;
+ uxTxBufferIndex = 0;
+ } else
+ {
+ xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
+ | ulLastBuffer;
+ uxTxBufferIndex++;
+ }
+ /* If this is the last buffer to be sent for this frame we can
+ start the transmission. */
+ if( ulLastBuffer )
+ macb->ncr |= AVR32_MACB_TSTART_MASK;
+
+ }
+ portEXIT_CRITICAL();
+ }
+
+ return PASS;
+}
+
+
+unsigned long ulMACBInputLength(void)
+{
+ register unsigned long ulIndex , ulLength = 0;
+ unsigned int uiTemp;
+ volatile unsigned long ulEventStatus;
+
+ // Check if the MACB encountered a problem.
+ ulEventStatus = AVR32_MACB.rsr;
+ if( ulEventStatus & AVR32_MACB_RSR_BNA_MASK )
+ { // MACB couldn't get ownership of a buffer. This could typically
+ // happen if the total numbers of Rx buffers is tailored too small
+ // for a noisy network with big frames.
+ // We might as well restore ownership of all buffers to the MACB to
+ // restart from a clean state.
+ vResetMacbRxFrames();
+ return( ulLength );
+ }
+
+ // Skip any fragments. We are looking for the first buffer that contains
+ // data and has the SOF (start of frame) bit set.
+ while( ( xRxDescriptors[ ulNextRxBuffer ].addr & AVR32_OWNERSHIP_BIT )
+ && !( xRxDescriptors[ ulNextRxBuffer ].U_Status.status & AVR32_SOF ) )
+ {
+ // Ignoring this buffer. Mark it as free again.
+ uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
+ xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
+ ulNextRxBuffer++;
+ if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
+ {
+ ulNextRxBuffer = 0;
+ }
+ }
+
+ // We are going to walk through the descriptors that make up this frame,
+ // but don't want to alter ulNextRxBuffer as this would prevent vMACBRead()
+ // from finding the data. Therefore use a copy of ulNextRxBuffer instead.
+ ulIndex = ulNextRxBuffer;
+
+ // Walk through the descriptors until we find the last buffer for this frame.
+ // The last buffer will give us the length of the entire frame.
+ while ( xRxDescriptors[ ulIndex ].addr & AVR32_OWNERSHIP_BIT )
+ {
+ ulLength = xRxDescriptors[ ulIndex ].U_Status.status & AVR32_LENGTH_FRAME;
+ if (ulLength) break; //return ulLength
+
+ // Increment to the next buffer, wrapping if necessary.
+ if( ++ulIndex >= ETHERNET_CONF_NB_RX_BUFFERS ) ulIndex = 0;
+
+ // Is the descriptor valid?
+ if (!(xRxDescriptors[ ulIndex ].addr & AVR32_OWNERSHIP_BIT)) break; //return 0
+
+ // Is it a SOF? If so, the head packet is bad and should be discarded
+ if (xRxDescriptors[ ulIndex ].U_Status.status & AVR32_SOF)
+ {
+ // Mark the buffers of the CURRENT, FAULTY packet available.
+ unsigned int i = ulNextRxBuffer;
+ do{
+ // Ignore the faulty frame. Mark its buffers as owned by the MACB.
+ uiTemp = xRxDescriptors[ i ].addr;
+ xRxDescriptors[ i ].addr = uiTemp & ~(AVR32_OWNERSHIP_BIT);
+ if (++i>=ETHERNET_CONF_NB_RX_BUFFERS) i=0;
+ }while (i!=ulIndex);
+ ulNextRxBuffer=ulIndex;
+ // We have the start of a new packet, look at that one instead.
+ }
+ }
+ return ulLength;
+}
+/*-----------------------------------------------------------*/
+
+void vMACBRead(void *pvTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength)
+{
+ unsigned char *pcTo = pvTo;
+ static unsigned long ulSectionBytesReadSoFar = 0, ulBufferPosition = 0, ulFrameBytesReadSoFar = 0;
+ static const unsigned char *pcSource;
+ register unsigned long ulBytesRemainingInBuffer, ulRemainingSectionBytes;
+ unsigned int uiTemp;
+
+ // Read ulSectionLength bytes from the Rx buffers.
+ // This is not necessarily any correspondence between the length of our Rx buffers,
+ // and the length of the data we are returning or the length of the data being requested.
+ // Therefore, between calls we have to remember not only which buffer we are currently
+ // processing, but our position within that buffer.
+ // This would be greatly simplified if PBUF_POOL_BUFSIZE could be guaranteed to be greater
+ // than the size of each Rx buffer, and that memory fragmentation did not occur.
+
+ // This function should only be called after a call to ulMACBInputLength().
+ // This will ensure ulNextRxBuffer is set to the correct buffer. */
+
+ // vMACBRead is called with pcTo set to NULL to indicate that we are about
+ // to read a new frame. Any fragments remaining in the frame we were
+ // processing during the last call should be dropped.
+ if( pcTo == NULL )
+ {
+ // How many bytes are indicated as being in this buffer?
+ // If none then the buffer is completely full and the frame is contained within more
+ // than one buffer.
+ // Reset our state variables ready for the next read from this buffer.
+ pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
+ ulFrameBytesReadSoFar = ( unsigned long ) 0;
+ ulBufferPosition = ( unsigned long ) 0;
+ }
+ else
+ {
+ // Loop until we have obtained the required amount of data.
+ ulSectionBytesReadSoFar = 0;
+ while( ulSectionBytesReadSoFar < ulSectionLength )
+ {
+ // We may have already read some data from this buffer.
+ // How much data remains in the buffer?
+ ulBytesRemainingInBuffer = ( RX_BUFFER_SIZE - ulBufferPosition );
+
+ // How many more bytes do we need to read before we have the
+ // required amount of data?
+ ulRemainingSectionBytes = ulSectionLength - ulSectionBytesReadSoFar;
+
+ // Do we want more data than remains in the buffer?
+ if( ulRemainingSectionBytes > ulBytesRemainingInBuffer )
+ {
+ // We want more data than remains in the buffer so we can
+ // write the remains of the buffer to the destination, then move
+ // onto the next buffer to get the rest.
+ memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulBytesRemainingInBuffer );
+ ulSectionBytesReadSoFar += ulBytesRemainingInBuffer;
+ ulFrameBytesReadSoFar += ulBytesRemainingInBuffer;
+
+ // Mark the buffer as free again.
+ uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
+ xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
+ // Move onto the next buffer.
+ ulNextRxBuffer++;
+
+ if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
+ {
+ ulNextRxBuffer = ( unsigned long ) 0;
+ }
+
+ // Reset the variables for the new buffer.
+ pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
+ ulBufferPosition = ( unsigned long ) 0;
+ }
+ else
+ {
+ // We have enough data in this buffer to send back.
+ // Read out enough data and remember how far we read up to.
+ memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulRemainingSectionBytes );
+
+ // There may be more data in this buffer yet.
+ // Increment our position in this buffer past the data we have just read.
+ ulBufferPosition += ulRemainingSectionBytes;
+ ulSectionBytesReadSoFar += ulRemainingSectionBytes;
+ ulFrameBytesReadSoFar += ulRemainingSectionBytes;
+
+ // Have we now finished with this buffer?
+ if( ( ulBufferPosition >= RX_BUFFER_SIZE ) || ( ulFrameBytesReadSoFar >= ulTotalFrameLength ) )
+ {
+ // Mark the buffer as free again.
+ uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
+ xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
+ // Move onto the next buffer.
+ ulNextRxBuffer++;
+
+ if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
+ {
+ ulNextRxBuffer = 0;
+ }
+
+ pcSource = ( unsigned char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
+ ulBufferPosition = 0;
+ }
+ }
+ }
+ }
+}
+
+/*-----------------------------------------------------------*/
+void vMACBFlushCurrentPacket(unsigned long ulTotalFrameLength)
+{
+ unsigned int uiTemp;
+ long int lTotalFrameLen = (long int)ulTotalFrameLength;
+
+ while( lTotalFrameLen > 0 )
+ {
+ // Ignoring this buffer. Mark it as free again.
+ uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
+ xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
+
+ // Move on to the next buffer.
+ ulNextRxBuffer++;
+ ulNextRxBuffer = ulNextRxBuffer%ETHERNET_CONF_NB_RX_BUFFERS;
+
+ lTotalFrameLen -= RX_BUFFER_SIZE;
+ }
+}
+
+
+/*-----------------------------------------------------------*/
+void vMACBSetMACAddress(const unsigned char *MACAddress)
+{
+ memcpy(cMACAddress, MACAddress, sizeof(cMACAddress));
+}
+
+Bool xMACBInit(volatile avr32_macb_t *macb)
+{
+ Bool global_interrupt_enabled = Is_global_interrupt_enabled();
+ volatile unsigned long status;
//vDisableMACBOperations(macb);
-
- // set up registers
- macb->ncr = 0;
- macb->tsr = ~0UL;
- macb->rsr = ~0UL;
-
- if (global_interrupt_enabled) Disable_global_interrupt();
- macb->idr = ~0UL;
- status = macb->isr;
- if (global_interrupt_enabled) Enable_global_interrupt();
-
- // RMII used, set 0 to the USRIO Register
- macb->usrio &= ~AVR32_MACB_RMII_MASK;
-
- // Load our MAC address into the MACB.
- prvSetupMACAddress(macb);
-
- // Setup the buffers and descriptors.
- prvSetupDescriptors(macb);
-
-#if ETHERNET_CONF_SYSTEM_CLOCK <= 20000000
- macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV8 << AVR32_MACB_NCFGR_CLK_OFFSET);
-#elif ETHERNET_CONF_SYSTEM_CLOCK <= 40000000
- macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV16 << AVR32_MACB_NCFGR_CLK_OFFSET);
-#elif ETHERNET_CONF_SYSTEM_CLOCK <= 80000000
- macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV32 << AVR32_MACB_NCFGR_CLK_OFFSET;
-#elif ETHERNET_CONF_SYSTEM_CLOCK <= 160000000
- macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV64 << AVR32_MACB_NCFGR_CLK_OFFSET;
-#else
-# error System clock too fast
-#endif
-
- // Are we connected?
- if( prvProbePHY(macb) == TRUE )
- {
- // Enable the interrupt!
- portENTER_CRITICAL();
- {
- prvSetupMACBInterrupt(macb);
- }
- portEXIT_CRITICAL();
- // Enable Rx and Tx, plus the stats register.
- macb->ncr = AVR32_MACB_NCR_TE_MASK | AVR32_MACB_NCR_RE_MASK;
- return (TRUE);
- }
- return (FALSE);
-}
-
-void vDisableMACBOperations (volatile avr32_macb_t *macb)
-{
- Bool global_interrupt_enabled = Is_global_interrupt_enabled();
-
- // write the MACB control register : disable Tx & Rx
- macb->ncr &= ~((1 << AVR32_MACB_RE_OFFSET) | (1 << AVR32_MACB_TE_OFFSET));
-
- // We no more want to interrupt on Rx and Tx events.
- if (global_interrupt_enabled) Disable_global_interrupt();
- macb->idr = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK;
- macb->isr;
- if (global_interrupt_enabled) Enable_global_interrupt();
-}
-
-
-void vClearMACBTxBuffer(void)
-{
- static unsigned long uxNextBufferToClear = 0;
-
- // Called on Tx interrupt events to set the AVR32_TRANSMIT_OK bit in each
- // Tx buffer within the frame just transmitted. This marks all the buffers
- // as available again.
-
- // The first buffer in the frame should have the bit set automatically. */
- if( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_TRANSMIT_OK )
- {
- // Loop through the other buffers in the frame.
- while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_LAST_BUFFER ) )
- {
- uxNextBufferToClear++;
-
- if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
- {
- uxNextBufferToClear = 0;
- }
-
- xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
- }
-
- // Start with the next buffer the next time a Tx interrupt is called.
- uxNextBufferToClear++;
-
- // Do we need to wrap back to the first buffer?
- if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
- {
- uxNextBufferToClear = 0;
- }
- }
-}
-
-static void prvSetupDescriptors(volatile avr32_macb_t *macb)
-{
- unsigned long xIndex;
- unsigned long ulAddress;
-
- // Initialise xRxDescriptors descriptor.
- for( xIndex = 0; xIndex < ETHERNET_CONF_NB_RX_BUFFERS; ++xIndex )
- {
- // Calculate the address of the nth buffer within the array.
- ulAddress = ( unsigned long )( pcRxBuffer + ( xIndex * RX_BUFFER_SIZE ) );
-
- // Write the buffer address into the descriptor.
- // The DMA will place the data at this address when this descriptor is being used.
- // No need to mask off the bottom bits of the address (these have special meaning
- // for the MACB) because pcRxBuffer is 4Bytes-aligned.
- xRxDescriptors[ xIndex ].addr = ulAddress;
- }
-
- // The last buffer has the wrap bit set so the MACB knows to wrap back
- // to the first buffer.
- xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS - 1 ].addr |= RX_WRAP_BIT;
-
- // Initialise xTxDescriptors.
- for( xIndex = 0; xIndex < ETHERNET_CONF_NB_TX_BUFFERS; ++xIndex )
- {
- // Calculate the address of the nth buffer within the array.
- ulAddress = ( unsigned long )( pcTxBuffer + ( xIndex * ETHERNET_CONF_TX_BUFFER_SIZE ) );
-
- // Write the buffer address into the descriptor.
- // The DMA will read data from here when the descriptor is being used.
- xTxDescriptors[ xIndex ].addr = ulAddress;
- xTxDescriptors[ xIndex ].U_Status.status = AVR32_TRANSMIT_OK;
- }
-
- // The last buffer has the wrap bit set so the MACB knows to wrap back
- // to the first buffer.
- xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS - 1 ].U_Status.status = AVR32_TRANSMIT_WRAP | AVR32_TRANSMIT_OK;
-
- // Tell the MACB where to find the descriptors.
- macb->rbqp = ( unsigned long )xRxDescriptors;
- macb->tbqp = ( unsigned long )xTxDescriptors;
-
- // Do not copy the FCS field of received frames to memory.
- macb->ncfgr |= ( AVR32_MACB_NCFGR_DRFCS_MASK );
-
-}
-
-//!
-//! \brief Restore ownership of all Rx buffers to the MACB.
-//!
-static void vResetMacbRxFrames( void )
-{
- register unsigned long ulIndex;
- unsigned int uiTemp;
-
-
- // Disable MACB frame reception.
- AVR32_MACB.ncr &= ~(AVR32_MACB_NCR_RE_MASK);
-
- // Restore ownership of all Rx buffers to the MACB.
- for( ulIndex = 0; ulIndex < ETHERNET_CONF_NB_RX_BUFFERS; ++ulIndex )
- {
- // Mark the buffer as owned by the MACB.
- uiTemp = xRxDescriptors[ ulIndex ].addr;
- xRxDescriptors[ ulIndex ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
- }
-
- // Reset the Buffer-not-available bit and the overrun bit.
- AVR32_MACB.rsr = AVR32_MACB_RSR_BNA_MASK | AVR32_MACB_RSR_OVR_MASK; // Clear
- AVR32_MACB.rsr; // We read to force the previous operation.
-
- // Reset the MACB starting point.
- AVR32_MACB.rbqp = ( unsigned long )xRxDescriptors;
-
- // Reset the index to the next buffer from which data will be read.
- ulNextRxBuffer = 0;
-
- // Enable MACB frame reception.
- AVR32_MACB.ncr |= AVR32_MACB_NCR_RE_MASK;
-}
-
-
-static void prvSetupMACAddress(volatile avr32_macb_t *macb)
-{
- // Must be written SA1L then SA1H.
- macb->sa1b = ( ( unsigned long ) cMACAddress[ 3 ] << 24 ) |
- ( ( unsigned long ) cMACAddress[ 2 ] << 16 ) |
- ( ( unsigned long ) cMACAddress[ 1 ] << 8 ) |
- cMACAddress[ 0 ];
-
- macb->sa1t = ( ( unsigned long ) cMACAddress[ 5 ] << 8 ) |
- cMACAddress[ 4 ];
-}
-
-static void prvSetupMACBInterrupt(volatile avr32_macb_t *macb)
-{
-
- // Setup the interrupt for MACB.
- // Register the interrupt handler to the interrupt controller at interrupt level 2
- INTC_register_interrupt((__int_handler)&vMACB_ISR, AVR32_MACB_IRQ, AVR32_INTC_INT2);
-
- // We want to interrupt on Rx and Tx events
- macb->ier = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK ;
-}
+
+ // set up registers
+ macb->ncr = 0;
+ macb->tsr = ~0UL;
+ macb->rsr = ~0UL;
+
+ if (global_interrupt_enabled) Disable_global_interrupt();
+ macb->idr = ~0UL;
+ status = macb->isr;
+ if (global_interrupt_enabled) Enable_global_interrupt();
+
+ // RMII used, set 0 to the USRIO Register
+ macb->usrio &= ~AVR32_MACB_RMII_MASK;
+
+ // Load our MAC address into the MACB.
+ prvSetupMACAddress(macb);
+
+ // Setup the buffers and descriptors.
+ prvSetupDescriptors(macb);
+
+#if ETHERNET_CONF_SYSTEM_CLOCK <= 20000000
+ macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV8 << AVR32_MACB_NCFGR_CLK_OFFSET);
+#elif ETHERNET_CONF_SYSTEM_CLOCK <= 40000000
+ macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV16 << AVR32_MACB_NCFGR_CLK_OFFSET);
+#elif ETHERNET_CONF_SYSTEM_CLOCK <= 80000000
+ macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV32 << AVR32_MACB_NCFGR_CLK_OFFSET;
+#elif ETHERNET_CONF_SYSTEM_CLOCK <= 160000000
+ macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV64 << AVR32_MACB_NCFGR_CLK_OFFSET;
+#else
+# error System clock too fast
+#endif
+
+ // Are we connected?
+ if( prvProbePHY(macb) == TRUE )
+ {
+ // Enable the interrupt!
+ portENTER_CRITICAL();
+ {
+ prvSetupMACBInterrupt(macb);
+ }
+ portEXIT_CRITICAL();
+ // Enable Rx and Tx, plus the stats register.
+ macb->ncr = AVR32_MACB_NCR_TE_MASK | AVR32_MACB_NCR_RE_MASK;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+void vDisableMACBOperations (volatile avr32_macb_t *macb)
+{
+ Bool global_interrupt_enabled = Is_global_interrupt_enabled();
+
+ // write the MACB control register : disable Tx & Rx
+ macb->ncr &= ~((1 << AVR32_MACB_RE_OFFSET) | (1 << AVR32_MACB_TE_OFFSET));
+
+ // We no more want to interrupt on Rx and Tx events.
+ if (global_interrupt_enabled) Disable_global_interrupt();
+ macb->idr = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK;
+ macb->isr;
+ if (global_interrupt_enabled) Enable_global_interrupt();
+}
+
+
+void vClearMACBTxBuffer(void)
+{
+ static unsigned long uxNextBufferToClear = 0;
+
+ // Called on Tx interrupt events to set the AVR32_TRANSMIT_OK bit in each
+ // Tx buffer within the frame just transmitted. This marks all the buffers
+ // as available again.
+
+ // The first buffer in the frame should have the bit set automatically. */
+ if( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_TRANSMIT_OK )
+ {
+ // Loop through the other buffers in the frame.
+ while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_LAST_BUFFER ) )
+ {
+ uxNextBufferToClear++;
+
+ if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
+ {
+ uxNextBufferToClear = 0;
+ }
+
+ xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
+ }
+
+ // Start with the next buffer the next time a Tx interrupt is called.
+ uxNextBufferToClear++;
+
+ // Do we need to wrap back to the first buffer?
+ if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
+ {
+ uxNextBufferToClear = 0;
+ }
+ }
+}
+
+static void prvSetupDescriptors(volatile avr32_macb_t *macb)
+{
+ unsigned long xIndex;
+ unsigned long ulAddress;
+
+ // Initialise xRxDescriptors descriptor.
+ for( xIndex = 0; xIndex < ETHERNET_CONF_NB_RX_BUFFERS; ++xIndex )
+ {
+ // Calculate the address of the nth buffer within the array.
+ ulAddress = ( unsigned long )( pcRxBuffer + ( xIndex * RX_BUFFER_SIZE ) );
+
+ // Write the buffer address into the descriptor.
+ // The DMA will place the data at this address when this descriptor is being used.
+ // No need to mask off the bottom bits of the address (these have special meaning
+ // for the MACB) because pcRxBuffer is 4Bytes-aligned.
+ xRxDescriptors[ xIndex ].addr = ulAddress;
+ }
+
+ // The last buffer has the wrap bit set so the MACB knows to wrap back
+ // to the first buffer.
+ xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS - 1 ].addr |= RX_WRAP_BIT;
+
+ // Initialise xTxDescriptors.
+ for( xIndex = 0; xIndex < ETHERNET_CONF_NB_TX_BUFFERS; ++xIndex )
+ {
+ // Calculate the address of the nth buffer within the array.
+ ulAddress = ( unsigned long )( pcTxBuffer + ( xIndex * ETHERNET_CONF_TX_BUFFER_SIZE ) );
+
+ // Write the buffer address into the descriptor.
+ // The DMA will read data from here when the descriptor is being used.
+ xTxDescriptors[ xIndex ].addr = ulAddress;
+ xTxDescriptors[ xIndex ].U_Status.status = AVR32_TRANSMIT_OK;
+ }
+
+ // The last buffer has the wrap bit set so the MACB knows to wrap back
+ // to the first buffer.
+ xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS - 1 ].U_Status.status = AVR32_TRANSMIT_WRAP | AVR32_TRANSMIT_OK;
+
+ // Tell the MACB where to find the descriptors.
+ macb->rbqp = ( unsigned long )xRxDescriptors;
+ macb->tbqp = ( unsigned long )xTxDescriptors;
+
+ // Do not copy the FCS field of received frames to memory.
+ macb->ncfgr |= ( AVR32_MACB_NCFGR_DRFCS_MASK );
+
+}
+
+//!
+//! \brief Restore ownership of all Rx buffers to the MACB.
+//!
+static void vResetMacbRxFrames( void )
+{
+ register unsigned long ulIndex;
+ unsigned int uiTemp;
+
+
+ // Disable MACB frame reception.
+ AVR32_MACB.ncr &= ~(AVR32_MACB_NCR_RE_MASK);
+
+ // Restore ownership of all Rx buffers to the MACB.
+ for( ulIndex = 0; ulIndex < ETHERNET_CONF_NB_RX_BUFFERS; ++ulIndex )
+ {
+ // Mark the buffer as owned by the MACB.
+ uiTemp = xRxDescriptors[ ulIndex ].addr;
+ xRxDescriptors[ ulIndex ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
+ }
+
+ // Reset the Buffer-not-available bit and the overrun bit.
+ AVR32_MACB.rsr = AVR32_MACB_RSR_BNA_MASK | AVR32_MACB_RSR_OVR_MASK; // Clear
+ AVR32_MACB.rsr; // We read to force the previous operation.
+
+ // Reset the MACB starting point.
+ AVR32_MACB.rbqp = ( unsigned long )xRxDescriptors;
+
+ // Reset the index to the next buffer from which data will be read.
+ ulNextRxBuffer = 0;
+
+ // Enable MACB frame reception.
+ AVR32_MACB.ncr |= AVR32_MACB_NCR_RE_MASK;
+}
+
+
+static void prvSetupMACAddress(volatile avr32_macb_t *macb)
+{
+ // Must be written SA1L then SA1H.
+ macb->sa1b = ( ( unsigned long ) cMACAddress[ 3 ] << 24 ) |
+ ( ( unsigned long ) cMACAddress[ 2 ] << 16 ) |
+ ( ( unsigned long ) cMACAddress[ 1 ] << 8 ) |
+ cMACAddress[ 0 ];
+
+ macb->sa1t = ( ( unsigned long ) cMACAddress[ 5 ] << 8 ) |
+ cMACAddress[ 4 ];
+}
+
+static void prvSetupMACBInterrupt(volatile avr32_macb_t *macb)
+{
+
+ // Setup the interrupt for MACB.
+ // Register the interrupt handler to the interrupt controller at interrupt level 2
+ INTC_register_interrupt((__int_handler)&vMACB_ISR, AVR32_MACB_IRQ, AVR32_INTC_INT2);
+
+ // We want to interrupt on Rx and Tx events
+ macb->ier = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK ;
+}
/*! Read a register on MDIO bus (access to the PHY)
* This function is looping until PHY gets ready
@@ -653,7 +653,7 @@ static void prvSetupMACBInterrupt(volatile avr32_macb_t *macb)
*
* \return unsigned long data that has been read
*/
-static unsigned long ulReadMDIO(volatile avr32_macb_t *macb, unsigned short usAddress)
+static unsigned long ulReadMDIO(volatile avr32_macb_t *macb, unsigned short usAddress)
{
unsigned long value, status;
u16 timeout = 0;
@@ -686,7 +686,7 @@ static unsigned long ulReadMDIO(volatile avr32_macb_t *macb, unsigned short usAd
* \param usValue Input. value to write.
*
*/
-static void vWriteMDIO(volatile avr32_macb_t *macb, unsigned short usAddress, unsigned short usValue)
+static void vWriteMDIO(volatile avr32_macb_t *macb, unsigned short usAddress, unsigned short usValue)
{
unsigned long status;
u16 timeout = 0;
@@ -708,7 +708,7 @@ static void vWriteMDIO(volatile avr32_macb_t *macb, unsigned short usAddress, un
macb->ncr &= ~AVR32_MACB_NCR_MPE_MASK;
}
-static Bool prvProbePHY(volatile avr32_macb_t *macb)
+static Bool prvProbePHY(volatile avr32_macb_t *macb)
{
volatile unsigned long mii_status, phy_ctrl;
volatile unsigned long config;
@@ -716,28 +716,28 @@ static Bool prvProbePHY(volatile avr32_macb_t *macb)
volatile unsigned long physID;
// Read Phy Identifier register 1 & 2
- lower = ulReadMDIO(macb, PHY_PHYSID2);
- upper = ulReadMDIO(macb, PHY_PHYSID1);
+ lower = ulReadMDIO(macb, PHY_PHYSID2);
+ upper = ulReadMDIO(macb, PHY_PHYSID1);
// get Phy ID, ignore Revision
physID = ((upper << 16) & 0xFFFF0000) | (lower & 0xFFF0);
// check if it match config
if (physID == ETHERNET_CONF_PHY_ID)
{
// read RBR
- mode = ulReadMDIO(macb, PHY_RBR);
+ mode = ulReadMDIO(macb, PHY_RBR);
// set RMII mode if not done
if ((mode & RBR_RMII) != RBR_RMII)
{
// force RMII flag if strap options are wrong
mode |= RBR_RMII;
- vWriteMDIO(macb, PHY_RBR, mode);
+ vWriteMDIO(macb, PHY_RBR, mode);
}
advertise = ADVERTISE_CSMA | ADVERTISE_ALL;
// write advertise register
- vWriteMDIO(macb, PHY_ADVERTISE, advertise);
+ vWriteMDIO(macb, PHY_ADVERTISE, advertise);
// read Control register
- config = ulReadMDIO(macb, PHY_BMCR);
+ config = ulReadMDIO(macb, PHY_BMCR);
// read Phy Control register
phy_ctrl = ulReadMDIO(macb, PHY_PHYCR);
// enable Auto MDIX
@@ -745,18 +745,18 @@ static Bool prvProbePHY(volatile avr32_macb_t *macb)
// reset auto-negociation capability
config |= (BMCR_ANRESTART | BMCR_ANENABLE);
// update Phy ctrl register
- vWriteMDIO(macb, PHY_PHYCR, phy_ctrl);
+ vWriteMDIO(macb, PHY_PHYCR, phy_ctrl);
// update ctrl register
- vWriteMDIO(macb, PHY_BMCR, config);
+ vWriteMDIO(macb, PHY_BMCR, config);
// loop while link status isn't OK
do {
- mii_status = ulReadMDIO(macb, PHY_BMSR);
+ mii_status = ulReadMDIO(macb, PHY_BMSR);
} while (!(mii_status & BMSR_LSTATUS));
// read the LPA configuration of the PHY
- lpa = ulReadMDIO(macb, PHY_LPA);
+ lpa = ulReadMDIO(macb, PHY_LPA);
// read the MACB config register
config = AVR32_MACB.ncfgr;
@@ -779,13 +779,13 @@ static Bool prvProbePHY(volatile avr32_macb_t *macb)
return TRUE;
}
return FALSE;
-}
-
-/*
- * The MACB ISR. Handles both Tx and Rx complete interrupts.
+}
+
+/*
+ * The MACB ISR. Handles both Tx and Rx complete interrupts.
*/
-__attribute__((__interrupt__)) void vMACB_ISR(void)
-{
+__attribute__((__interrupt__)) void vMACB_ISR(void)
+{
// Variable definitions can be made now.
volatile unsigned long ulIntStatus, ulEventStatus;
@@ -810,5 +810,5 @@ __attribute__((__interrupt__)) void vMACB_ISR(void)
AVR32_MACB.tsr = AVR32_MACB_TSR_COMP_MASK; // Clear
AVR32_MACB.tsr; // Read to force the previous write
}
-}
-#endif
+}
+#endif
diff --git a/src/platform/avr32/ethernet.h b/src/platform/avr32/ethernet.h
index a5aa4cff..b51afa08 100644
--- a/src/platform/avr32/ethernet.h
+++ b/src/platform/avr32/ethernet.h
@@ -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
From 722d5cb0a1b83f3473f41338502c552f9e77ed20 Mon Sep 17 00:00:00 2001
From: Thiago Naves
Date: Tue, 8 Nov 2011 16:44:37 -0200
Subject: [PATCH 74/80] Fix SPI on STR9
---
src/platform/str9/platform.c | 129 +++++++++++++++++++++++++----------
1 file changed, 93 insertions(+), 36 deletions(-)
diff --git a/src/platform/str9/platform.c b/src/platform/str9/platform.c
index 43e6c7e8..82b08cd6 100644
--- a/src/platform/str9/platform.c
+++ b/src/platform/str9/platform.c
@@ -869,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 );
@@ -906,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 )
From a38586f21786685f1a29ca532f3ca19c132cee42 Mon Sep 17 00:00:00 2001
From: Thiago Naves
Date: Tue, 8 Nov 2011 16:55:58 -0200
Subject: [PATCH 75/80] Updated SPI count in str9's platform_conf.h ( also from
the SPI fix )
---
src/platform/str9/platform_conf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/platform/str9/platform_conf.h b/src/platform/str9/platform_conf.h
index 46253eab..ab1e4937 100644
--- a/src/platform/str9/platform_conf.h
+++ b/src/platform/str9/platform_conf.h
@@ -47,7 +47,7 @@
// 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
From b79a1d4eade02e961d3d133165960347c2b211db Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 10 Nov 2011 02:25:55 +0200
Subject: [PATCH 76/80] fix invalid argument matching in tmr.set_match_int
---
src/modules/tmr.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/tmr.c b/src/modules/tmr.c
index 5f78cdb6..a4e1bd76 100644
--- a/src/modules/tmr.c
+++ b/src/modules/tmr.c
@@ -144,7 +144,7 @@ static int tmr_set_match_int( lua_State *L )
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, 3 ) );
+ 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 )
From d4f03efb96973d73056d87b4173c394ca673bebf Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 10 Nov 2011 02:27:44 +0200
Subject: [PATCH 77/80] timer interrupt support for AVR32
---
src/platform/avr32/EVK1100/evk1100_conf.h | 6 +-
src/platform/avr32/EVK1101/evk1101_conf.h | 6 +-
src/platform/avr32/MIZAR32/mizar32_conf.h | 6 +-
src/platform/avr32/platform.c | 99 ++++++++++-------------
src/platform/avr32/platform_int.c | 88 +++++++++++++++++++-
5 files changed, 141 insertions(+), 64 deletions(-)
diff --git a/src/platform/avr32/EVK1100/evk1100_conf.h b/src/platform/avr32/EVK1100/evk1100_conf.h
index 64228112..0f4d7fdc 100644
--- a/src/platform/avr32/EVK1100/evk1100_conf.h
+++ b/src/platform/avr32/EVK1100/evk1100_conf.h
@@ -173,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
diff --git a/src/platform/avr32/EVK1101/evk1101_conf.h b/src/platform/avr32/EVK1101/evk1101_conf.h
index 574b0d8a..03058d18 100644
--- a/src/platform/avr32/EVK1101/evk1101_conf.h
+++ b/src/platform/avr32/EVK1101/evk1101_conf.h
@@ -128,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
diff --git a/src/platform/avr32/MIZAR32/mizar32_conf.h b/src/platform/avr32/MIZAR32/mizar32_conf.h
index bb9a58e9..97653e84 100644
--- a/src/platform/avr32/MIZAR32/mizar32_conf.h
+++ b/src/platform/avr32/MIZAR32/mizar32_conf.h
@@ -228,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
diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c
index 72ab8e70..a1eb6f27 100644
--- a/src/platform/avr32/platform.c
+++ b/src/platform/avr32/platform.c
@@ -119,28 +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_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,
@@ -220,37 +198,6 @@ 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;
@@ -297,6 +244,13 @@ int platform_init()
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
@@ -539,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 )
@@ -639,7 +594,25 @@ timer_data_type platform_s_timer_op( unsigned id, int op, timer_data_type data )
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()
@@ -1164,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
diff --git a/src/platform/avr32/platform_int.c b/src/platform/avr32/platform_int.c
index 7bb06016..c19c9587 100644
--- a/src/platform/avr32/platform_int.c
+++ b/src/platform/avr32/platform_int.c
@@ -12,6 +12,7 @@
#include
#include "usart.h"
#include "intc.h"
+#include "tc.h"
// ****************************************************************************
// Interrupt handlers
@@ -56,6 +57,52 @@ __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 ].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 +133,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 +176,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 +188,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 )
+
From cd530f96403f1287849fed0428f3f22dfb6d59da Mon Sep 17 00:00:00 2001
From: Bogdan Marinescu
Date: Thu, 10 Nov 2011 13:03:57 +0200
Subject: [PATCH 78/80] AVR32 INT_TMR_MATCH fix
Actually disable the timer match interrupt for the non-cyclic mode.
---
src/platform/avr32/platform_int.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/platform/avr32/platform_int.c b/src/platform/avr32/platform_int.c
index c19c9587..29d4a0dc 100644
--- a/src/platform/avr32/platform_int.c
+++ b/src/platform/avr32/platform_int.c
@@ -85,7 +85,10 @@ static void tmr_match_common_handler( int id )
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()
From 7dfad82c0cce3e9814c2fc48edd125e04a38782a Mon Sep 17 00:00:00 2001
From: "naves.thiago"
Date: Thu, 10 Nov 2011 21:28:53 -0200
Subject: [PATCH 79/80] Fix indentation
---
src/platform/str9/platform.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/platform/str9/platform.c b/src/platform/str9/platform.c
index 82b08cd6..68b22ec4 100644
--- a/src/platform/str9/platform.c
+++ b/src/platform/str9/platform.c
@@ -916,7 +916,7 @@ u32 platform_spi_setup( unsigned id, int mode, u32 clock, unsigned cpol, unsigne
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt3;
GPIO_Init(GPIO1, &GPIO_InitStructure);
- GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
+ 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;
@@ -962,7 +962,7 @@ spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data )
}
else
{
- // Send byte through the SSP1 peripheral
+ // Send byte through the SSP1 peripheral
SSP1->DR = data;
// Loop while Transmit FIFO is full
while(SSP_GetFlagStatus(SSP1, SSP_FLAG_TxFifoEmpty) == RESET);
From 9cd7c65e06c298043c463c4670e038ca1508b066 Mon Sep 17 00:00:00 2001
From: James Snyder
Date: Sun, 13 Nov 2011 15:56:06 -0600
Subject: [PATCH 80/80] Fix typo in mmc timer code that prevented writing to
files
---
src/elua_mmc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/elua_mmc.c b/src/elua_mmc.c
index 7c97e6d3..fe6838da 100644
--- a/src/elua_mmc.c
+++ b/src/elua_mmc.c
@@ -114,7 +114,7 @@ BYTE wait_ready (void)
rcvr_spi();
do
res = rcvr_spi(); /* Wait for ready in timeout of 500ms. */
- while ( ( res != 0xFF ) && ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer1 ) < 500000 ) );
+ while ( ( res != 0xFF ) && ( platform_timer_get_diff_crt( PLATFORM_TIMER_SYS_ID, Timer2 ) < 500000 ) );
return res;
}