1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00
This commit is contained in:
James Snyder 2011-04-26 16:53:40 -05:00
commit a637578dc6
9 changed files with 138 additions and 19 deletions

View File

@ -17,7 +17,7 @@ data_en =
be available by using $tmr.VIRT0$ to $tmr.VIRT3$ as timer IDs.</p>
<p>All "time units" (delays, differences in time) in this module, as well as in other parts of eLua (timeouts) are expressed in microseconds. However,
please keep in mind that the actual timer resolution depends on many factors. For example, it's very likely that the @#tmr.delay@tmr.delay@ function won't
be able to delay for the exact amount you specify (in us), as the real delay depends ona number of variables, most notably the base clock of the timer
be able to delay for the exact amount you specify (in us), as the real delay depends on a number of variables, most notably the base clock of the timer
and the size of the timer counter register (32 bits on some platforms, 16 bits on most platforms, other values are less common). To ensure that the delay
you're requesting is achievable, use @#tmr.getmindelay@tmr.getmindelay@ and @#tmr.getmaxdelay@tmr.getmaxdelay@ to obtain the maximum and the minimum
achievable wait times on your timer, respectively. Even if your delay is within these limits, the $precision$ of this function still varies a lot,
@ -59,13 +59,13 @@ data_en =
},
{ sig = "mindelay = #tmr.getmindelay#( id )",
desc = "Get the minimum achieavable delay on the specified timer.",
desc = "Get the minimum achievable delay on the specified timer.",
args = "$id$ - the timer ID.",
ret = "The minimum achievable delay on the specified timer (in us)."
},
{ sig = "maxdelay = #tmr.getmaxdelay#( id )",
desc = "Get the maximum achieavable delay on the specified timer.",
desc = "Get the maximum achievable delay on the specified timer.",
args = "$id$ - the timer ID.",
ret = "The maximum achievable delay on the specified timer (in us)."
},

View File

@ -3,9 +3,9 @@ $$HEADER$$
<p>The EGC (Emergency Garbage Collector) patch was originally written for Lua by Robert Jakabosky, who was kind enough to port it to <b>eLua</b>. You can find the author's detailed
description of the patch <a href="http://lua-users.org/wiki/EmergencyGarbageCollector">here</a>. In short, what it does is that it lets you run a garbage collection cycle in Lua in a low memory
situation, from inside Lua's memory allocation function (something that the current version of Lua can't do out of the box). By forcing a garbage collection cycle, Lua can reclaim memory that's
not in use anymore, thus making more memory available for your program. The downside is reduced execution speed, as a direct result of running the gargabe collector when needed. For some
not in use any more, thus making more memory available for your program. The downside is reduced execution speed, as a direct result of running the garbage collector when needed. For some
applications, reducing the execution speed to fit the application in memory might be acceptable, and for other applications it might not. As usual, it all depends on your application. As a generic
guideline, if your application isn't concerned with realtime processing, you should be fine with sacrifing execution speed to get more memory in many real life scenarios.</p>
guideline, if your application isn't concerned with realtime processing, you should be fine with sacrificing execution speed to get more memory in many real life scenarios.</p>
<p>In <b>eLua</b>, the EGC patch can be configured to run in 4 different modes:</p>
<ol>
<li><b>disabled</b>: EGC inactive, no collection cycle will be forced in low memory situations.</li>

View File

@ -80,7 +80,7 @@ static _ssize_t std_read( struct _reent *r, int fd, void* vptr, size_t len )
}
ptr[ i ++ ] = c;
}
return len;
return i;
}
// 'write'

View File

@ -18,7 +18,7 @@
#define BUILD_CON_GENERIC
//#define BUILD_RPC
#define BUILD_C_INT_HANDLERS
#define BUILA_LUA_INT_HANDLERS
#define BUILD_LUA_INT_HANDLERS
//#define BUILD_RFS
//#define BUILD_SERMUX
#define BUILD_ADC
@ -161,6 +161,9 @@
//#define SERMUX_NUM_VUART 2
//#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
// Interrupt queue size
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX

View File

@ -114,6 +114,9 @@
#define MEM_START_ADDRESS { ( void* )end }
#define MEM_END_ADDRESS { ( void* )( AVR32_SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
// Interrupt queue size
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX

View File

@ -22,6 +22,7 @@
//#define BUILD_RPC
#define BUF_ENABLE_UART
#define BUILD_C_INT_HANDLERS
//#define BUILD_ADC
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
@ -59,6 +60,12 @@
#define BUILD_RPC
#endif
#ifdef BUILD_ADC
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
#else
#define ADCLINE
#endif
#if defined( BUILD_RPC )
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
#else
@ -74,6 +81,7 @@
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
ADCLINE\
RPCLINE\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
@ -102,7 +110,7 @@
#define NUM_TIMER 3
#endif
#define NUM_PWM 7 // PWM7 is on GPIO50
#define NUM_ADC 0
#define NUM_ADC 8 // Though ADC3 pin is the Ethernet IRQ
#define NUM_CAN 0
// As flow control seems not to work, we use a large buffer so that people
@ -116,6 +124,15 @@
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// ADC Configuration Params
#define ADC_BIT_RESOLUTION 10
#define BUF_ENABLE_ADC
#define ADC_BUF_SIZE BUF_SIZE_2
// These should be adjusted to support multiple ADC devices
#define ADC_TIMER_FIRST_ID 0
#define ADC_NUM_TIMERS 0
// SD/MMC Filesystem Setup
#define MMCFS_TICK_HZ 10
#define MMCFS_TICK_MS ( 1000 / MMCFS_TICK_HZ )
@ -145,6 +162,9 @@
#define MEM_START_ADDRESS { ( void* )end, ( void* )( SDRAM + ELUA_FIRMWARE_SIZE ) }
#define MEM_END_ADDRESS { ( void* )( 0x8000 - STACK_SIZE_TOTAL - 1 ), ( void* )( SDRAM + SDRAM_SIZE - 1 ) }
// Interrupt queue size
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
// Interrupt list
#define INT_UART_RX ELUA_INT_FIRST_ID
#define INT_ELUA_LAST INT_UART_RX

View File

@ -37,7 +37,7 @@ extern int pm_configure_clocks( pm_freq_param_t *param );
static u32 platform_timer_set_clock( unsigned id, u32 clock );
#if NUM_ADC > 0
#ifdef BUILD_ADC
__attribute__((__interrupt__)) static void adc_int_handler();
#endif
@ -176,7 +176,7 @@ int platform_init()
#endif
#if NUM_ADC > 0
#ifdef BUILD_ADC
(&AVR32_ADC)->ier = AVR32_ADC_DRDY_MASK;
INTC_register_interrupt( &adc_int_handler, AVR32_ADC_IRQ, AVR32_INTC_INT0);
@ -348,27 +348,42 @@ u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int st
opts.baudrate = baud;
// Set stopbits
if( stopbits == PLATFORM_UART_STOPBITS_1 )
switch (stopbits) {
case PLATFORM_UART_STOPBITS_1:
opts.stopbits = USART_1_STOPBIT;
else if( stopbits == PLATFORM_UART_STOPBITS_1_5 )
break;
case PLATFORM_UART_STOPBITS_1_5:
opts.stopbits = USART_1_5_STOPBITS;
else
break;
case PLATFORM_UART_STOPBITS_2:
opts.stopbits = USART_2_STOPBITS;
break;
default:
return 0;
}
// Set parity
if( parity == PLATFORM_UART_PARITY_EVEN )
switch (parity) {
case PLATFORM_UART_PARITY_EVEN:
opts.paritytype = USART_EVEN_PARITY;
else if( parity == PLATFORM_UART_PARITY_ODD )
break;
case PLATFORM_UART_PARITY_ODD:
opts.paritytype = USART_ODD_PARITY;
else
break;
case PLATFORM_UART_PARITY_NONE:
opts.paritytype = USART_NO_PARITY;
break;
default:
return 0;
}
// Set actual interface
gpio_enable_module(uart_pins + id * 2, 2 );
usart_init_rs232( pusart, &opts, REQ_PBA_FREQ );
if ( usart_init_rs232( pusart, &opts, REQ_PBA_FREQ ) != USART_SUCCESS )
return 0;
// [TODO] Return actual baud here
return baud;
// Return actual baud here
return usart_get_async_baudrate(pusart, REQ_PBA_FREQ);
}
void platform_s_uart_send( unsigned id, u8 data )
@ -564,6 +579,11 @@ u32 platform_s_timer_op( unsigned id, int op, u32 data )
return res;
}
int platform_s_timer_set_match_int( unsigned id, u32 period_us, int type )
{
return PLATFORM_TIMER_INT_INVALID_ID;
}
// ****************************************************************************
// SPI functions

View File

@ -111,6 +111,60 @@ static int usart_set_async_baudrate(volatile avr32_usart_t *usart, unsigned int
}
/*! \brief Return the actual baud rate set into the USART
*
* Baud rate calculation:
* \f$ Baudrate = \frac{SelectedClock}{Over \times (CD + \frac{FP}{8})} \f$, \e Over being 16 or 8.
*
* \param usart Base address of the USART instance.
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval baudrate The closest integer to the actual baud rate
* \retval 0 UART clock is off or there was some error on our part
*/
unsigned int usart_get_async_baudrate(volatile avr32_usart_t *usart, unsigned long pba_hz)
{
unsigned int clock; // Master clock frequency
unsigned int over; // divisor of 8 or 16
unsigned int cd; // clock divider (0-65535)
unsigned int fp; // fractional part of clock divider (0-7)
unsigned int divisor; // What the master clock is divided by to get
// the final baud rate
// Find
switch ((usart->mr & AVR32_USART_MR_USCLKS_MASK) >> AVR32_USART_MR_USCLKS_OFFSET)
{
case AVR32_USART_MR_USCLKS_MCK:
clock = pba_hz;
break;
case AVR32_USART_MR_USCLKS_MCK_DIV:
// I can't figure out where the divider is defined. The datasheet
// section 26.7.1 says it is "product dependent, but generally set to 8".
// Fortunately, the code above always selects MCK.
case AVR32_USART_MR_USCLKS_SCK:
// If we have an external clock, we don't know its frequency here.
default:
return 0;
}
over = usart->mr & AVR32_USART_MR_OVER_MASK;
cd = (usart->brgr & AVR32_USART_BRGR_CD_MASK) >> AVR32_USART_BRGR_CD_OFFSET;
fp = (usart->brgr & AVR32_USART_BRGR_FP_MASK) >> AVR32_USART_BRGR_FP_OFFSET;
// if CD==0, no baud rate is generated.
// if CD==1, the clock divider and fractional part are bypassed.
if (cd == 0) return 0;
if (cd == 1) fp = 0;
// Rewriting "divisor = 8 * (2 - over) * (cd + fp/8)" for integer math:
divisor = (2 - over) * (8 * cd + fp);
// Round to the integer that is closest to the actual result
return (clock + divisor/2) / divisor;
}
/*! \brief Calculates a clock divider (\e CD) for the USART synchronous master
* modes to generate a baud rate as close as possible to the baud rate
* set point.
@ -288,7 +342,11 @@ void usart_reset(volatile avr32_usart_t *usart)
int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)
{
// Reset the USART and shutdown TX and RX.
// This is too brutal for eLua, for which the power-on reset state is OK.
// Otherwise a buffered serial port stops receiving when you change baud rate.
#ifndef ELUA_PLATFORM
usart_reset(usart);
#endif
// Check input values.
if (!opt || // Null pointer.
@ -844,7 +902,12 @@ int usart_read_char(volatile avr32_usart_t *usart, int *c)
if (usart->csr & (AVR32_USART_CSR_OVRE_MASK |
AVR32_USART_CSR_FRAME_MASK |
AVR32_USART_CSR_PARE_MASK))
{
// Clear the error flag
usart->cr = AVR32_USART_CR_RSTSTA_MASK;
// Signal failure
return USART_RX_ERROR;
}
// No error; if we really did receive a char, read it and return SUCCESS.
if (usart_test_hit(usart))

View File

@ -230,6 +230,16 @@ extern void usart_reset(volatile avr32_usart_t *usart);
*/
extern int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Returns the actual baud rate set into the USART in async mode
*
* \param usart Base address of the USART instance.
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval baudrate The nearest integer to the actual baud rate
* \retval 0 No baudrate is being generated or some error
*/
extern unsigned int usart_get_async_baudrate(volatile avr32_usart_t *usart, unsigned long pba_hz);
/*! \brief Sets up the USART to use the standard RS232 protocol in TX-only mode.
*
* Compared to \ref usart_init_rs232, this function allows very high baud rates