diff --git a/inc/buf.h b/inc/buf.h index 05b81326..03d21a23 100644 --- a/inc/buf.h +++ b/inc/buf.h @@ -7,13 +7,15 @@ // [TODO] the buffer data type is currently u8, is this OK? typedef u8 t_buf_data; +typedef u16 t_buf_data_u16; // IDs of "bufferable" devices enum { BUF_ID_UART = 0, + BUF_ID_ADC = 1, BUF_ID_FIRST = BUF_ID_UART, - BUF_ID_LAST = BUF_ID_UART, + BUF_ID_LAST = BUF_ID_ADC, BUF_ID_TOTAL = BUF_ID_LAST - BUF_ID_FIRST + 1 }; @@ -23,6 +25,7 @@ typedef struct u8 logsize; volatile u16 wptr, rptr, count; t_buf_data *buf; + size_t dsize; } buf_desc; // Buffer sizes (there are power of 2 to speed up modulo operations) @@ -43,12 +46,16 @@ enum BUF_SIZE_32768 }; + + + // Buffer API -int buf_set( unsigned resid, unsigned resnum, u8 logsize ); +int buf_set(unsigned resid, unsigned resnum, u8 logsize, size_t dsize); int buf_is_enabled( unsigned resid, unsigned resnum ); unsigned buf_get_size( unsigned resid, unsigned resnum ); unsigned buf_get_count( unsigned resid, unsigned resnum ); -int buf_get_char( unsigned resid, unsigned resnum ); -void buf_rx_cb( unsigned resid, unsigned resnum, t_buf_data data ); +int buf_write( unsigned resid, unsigned resnum, t_buf_data *data, size_t dsize ); +int buf_read( unsigned resid, unsigned resnum, t_buf_data *data, size_t dsize ); + #endif diff --git a/inc/platform.h b/inc/platform.h index 0bcb0871..fbfbb188 100644 --- a/inc/platform.h +++ b/inc/platform.h @@ -6,11 +6,12 @@ #include "devman.h" #include "type.h" -// Error codes +// Error / status codes enum { PLATFORM_ERR, - PLATFORM_OK + PLATFORM_OK, + PLATFORM_UNDERFLOW }; // Platform initialization diff --git a/src/buf.c b/src/buf.c index 7ad6613c..a6ff3a99 100644 --- a/src/buf.c +++ b/src/buf.c @@ -13,6 +13,7 @@ #include "platform.h" #include "utils.h" #include +#include // [TODO]? Following code might need a C99 compiler (for 0-sized arrays) #ifdef BUF_ENABLE_UART @@ -21,15 +22,18 @@ static buf_desc buf_desc_uart[ 0 ]; #endif +static buf_desc buf_desc_adc [ NUM_ADC ]; + // NOTE: the order of descriptors here MUST match the order of the BUF_ID_xx // enum in inc/buf.h static const buf_desc* buf_desc_array[ BUF_ID_TOTAL ] = { - buf_desc_uart + buf_desc_uart, + buf_desc_adc }; // Helper macros -#define BUF_MOD_INCR( p, m ) p->m = ( p->m + 1 ) & ( ( ( u16 )1 << p->logsize ) - 1 ) +#define BUF_MOD_INCR( p, m ) p->m = ( p->m + p->dsize ) & ( ( ( u16 )1 << ( p->logsize + ( p->dsize - 1 ) ) ) - 1 ) #define BUF_REALSIZE( p ) ( ( u16 )1 << p->logsize ) #define BUF_GETPTR( resid, resnum ) buf_desc *pbuf = ( buf_desc* )buf_desc_array[ resid ] + resnum @@ -38,18 +42,23 @@ static const buf_desc* buf_desc_array[ BUF_ID_TOTAL ] = #define READ16( p ) p #define WRITE16( p, x ) p = x + + // Initialize the buffer of the specified resource // resid - resource ID (BUF_ID_UART ...) // resnum - resource number (0, 1, 2...) // bufsize - new size of the buffer (one of the BUF_SIZE_xxx constants from +// dsize - number of bytes held by each element // buf.h, or BUF_SIZE_NONE to disable buffering // Returns 1 on success, 0 on failure -int buf_set( unsigned resid, unsigned resnum, u8 logsize ) +int buf_set( unsigned resid, unsigned resnum, u8 logsize, size_t dsize ) { BUF_GETPTR( resid, resnum ); pbuf->logsize = logsize; - if( ( pbuf->buf = ( t_buf_data* )realloc( pbuf->buf, BUF_REALSIZE( pbuf ) * sizeof( t_buf_data ) ) ) == NULL ) + pbuf->dsize = dsize; + + if( ( pbuf->buf = ( t_buf_data* )realloc( pbuf->buf, BUF_REALSIZE( pbuf ) * pbuf->dsize ) ) == NULL ) { pbuf->logsize = BUF_SIZE_NONE; pbuf->rptr = pbuf->wptr = pbuf->count = 0; @@ -59,22 +68,31 @@ int buf_set( unsigned resid, unsigned resnum, u8 logsize ) return PLATFORM_OK; } -// Callback for RX buffer +// Write to buffer // resid - resource ID (BUF_ID_UART ...) // resnum - resource number (0, 1, 2...) -// data - the new data -// Returns 1 on success, 0 on failure +// data - pointer for where data will come from +// dsize - length of data to get +// Returns PLATFORM_OK on success, PLATFORM_ERR on failure // [TODO] maybe add a buffer overflow flag -void buf_rx_cb( unsigned resid, unsigned resnum, t_buf_data data ) +int buf_write( unsigned resid, unsigned resnum, t_buf_data *data, size_t dsize ) { BUF_GETPTR( resid, resnum ); - - pbuf->buf[ pbuf->wptr ] = data; + + // Make sure we only add more of same type + if (pbuf->dsize != dsize) + return PLATFORM_ERR; + + memcpy(&pbuf->buf[ pbuf->wptr ], data, dsize); + BUF_MOD_INCR( pbuf, wptr ); + if( pbuf->count == BUF_REALSIZE( pbuf ) ) BUF_MOD_INCR( pbuf, rptr ); else pbuf->count ++; + + return PLATFORM_OK; } // Returns 1 if the specified device is buffered, 0 otherwise @@ -87,7 +105,7 @@ int buf_is_enabled( unsigned resid, unsigned resnum ) return pbuf->logsize != BUF_SIZE_NONE; } -// Return the size of the buffer +// Return the size of the buffer in number unsigned buf_get_size( unsigned resid, unsigned resnum ) { BUF_GETPTR( resid, resnum ); @@ -103,20 +121,32 @@ unsigned buf_get_count( unsigned resid, unsigned resnum ) return READ16( pbuf->count ); } -// Returns a char from the RX buffer (-1 if not available) -int buf_get_char( unsigned resid, unsigned resnum ) +// Get data from buffer of size dsize +// resid - resource ID (BUF_ID_UART ...) +// resnum - resource number (0, 1, 2...) +// data - pointer for where data should go +// dsize - length of data to get +// Returns PLATFORM_OK on success, PLATFORM_ERR on failure, +// PLATFORM_UNDERFLOW on buffer empty +int buf_read( unsigned resid, unsigned resnum, t_buf_data *data, size_t dsize ) { BUF_GETPTR( resid, resnum ); - t_buf_data data; + + // Make sure buffer contains right type + if (pbuf->dsize != dsize) + return PLATFORM_ERR; if( READ16( pbuf->count ) == 0 ) - return -1; - data = pbuf->buf[ pbuf->rptr ]; + return PLATFORM_UNDERFLOW; + + memcpy(data, &pbuf->buf[ pbuf->rptr ], dsize); + platform_cpu_disable_interrupts(); pbuf->count --; BUF_MOD_INCR( pbuf, rptr ); platform_cpu_enable_interrupts(); - return ( int )data; + + return PLATFORM_OK; } #endif // #ifdef BUF_ENALE diff --git a/src/common.c b/src/common.c index 6dc95da7..79f93ff7 100644 --- a/src/common.c +++ b/src/common.c @@ -70,16 +70,21 @@ int platform_uart_exists( unsigned id ) static int cmn_recv_helper( unsigned id, s32 timeout ) { #ifdef BUF_ENABLE_UART + t_buf_data data; int res; + if( buf_is_enabled( BUF_ID_UART, id ) ) { if( timeout == 0 ) - return buf_get_char( BUF_ID_UART, id ); + { + if ( ( buf_read( BUF_ID_UART, id, &data, sizeof( t_buf_data ) ) ) == PLATFORM_UNDERFLOW ) + return -1; + } else { - while( ( res = buf_get_char( BUF_ID_UART, id ) ) == -1 ); - return res; + while( ( buf_read( BUF_ID_UART, id, &data, sizeof( t_buf_data ) ) ) == PLATFORM_UNDERFLOW ); } + return ( int )data; } else #endif diff --git a/src/platform/at91sam7x/platform.c b/src/platform/at91sam7x/platform.c index 2f3bb23d..bc255e5a 100644 --- a/src/platform/at91sam7x/platform.c +++ b/src/platform/at91sam7x/platform.c @@ -50,7 +50,7 @@ static void uart_rx_handler() AT91S_USART* base = CON_UART_ID == 0 ? AT91C_BASE_US0 : AT91C_BASE_US1; c = USART_Read( base, 0 ); - buf_rx_cb( BUF_ID_UART, CON_UART_ID, ( t_buf_data )c ); + buf_write( BUF_ID_UART, CON_UART_ID, ( t_buf_data* )&c, sizeof ( t_buf_data ) ); asm( "pop {r0}":: ); asm( "bx r0":: ); } @@ -82,7 +82,7 @@ int platform_init() USART_SetReceiverEnabled(AT91C_BASE_US0, 1); #if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE ) // Enable buffering on the console UART - buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE ); + buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( t_buf_data ) ); // Set interrupt handler and interrupt flag on UART unsigned uart_id = CON_UART_ID == 0 ? AT91C_ID_US0 : AT91C_ID_US1; AT91S_USART* base = CON_UART_ID == 0 ? AT91C_BASE_US0 : AT91C_BASE_US1; diff --git a/src/platform/avr32/platform.c b/src/platform/avr32/platform.c index 837a7671..43035410 100644 --- a/src/platform/avr32/platform.c +++ b/src/platform/avr32/platform.c @@ -55,7 +55,7 @@ __attribute__((__interrupt__)) static void uart_rx_handler() volatile avr32_usart_t *pusart = ( volatile avr32_usart_t* )uart_base_addr[ CON_UART_ID ]; usart_read_char( pusart, &c ); - buf_rx_cb( BUF_ID_UART, CON_UART_ID, ( t_buf_data )c ); + buf_write( BUF_ID_UART, CON_UART_ID, ( t_buf_data* )&c, sizeof ( t_buf_data ) ); } #endif @@ -116,7 +116,7 @@ int platform_init() platform_uart_setup( CON_UART_ID, CON_UART_SPEED, 8, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_STOPBITS_1 ); #if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE ) // Enable buffering on the console UART - buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE ); + buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( t_buf_data ) ); // Set interrupt handler and interrupt flag on UART INTC_register_interrupt( &uart_rx_handler, CON_UART_IRQ, AVR32_INTC_INT0 ); volatile avr32_usart_t *pusart = ( volatile avr32_usart_t* )uart_base_addr[ CON_UART_ID ]; diff --git a/src/platform/lm3s/platform.c b/src/platform/lm3s/platform.c index de70cf8f..8b306ec8 100644 --- a/src/platform/lm3s/platform.c +++ b/src/platform/lm3s/platform.c @@ -38,6 +38,7 @@ #include "interrupt.h" #include "elua_net.h" #include "dhcpc.h" +#include "buf.h" #include "rit128x96x4.h" #include "disp.h" #include "adc.h" @@ -242,6 +243,23 @@ static const u32 uart_sysctl[] = { SYSCTL_PERIPH_UART0, SYSCTL_PERIPH_UART1, SYS static const u32 uart_gpio_base[] = { GPIO_PORTA_BASE, GPIO_PORTD_BASE, GPIO_PORTG_BASE }; static const u8 uart_gpio_pins[] = { GPIO_PIN_0 | GPIO_PIN_1, GPIO_PIN_2 | GPIO_PIN_3, GPIO_PIN_0 | GPIO_PIN_1 }; +#ifdef BUF_ENABLE_UART +void UARTIntHandler() +{ + u32 temp; + int c; + + temp = UARTIntStatus(uart_base[ CON_UART_ID ], true); + UARTIntClear(uart_base[ CON_UART_ID ], temp); + while( UARTCharsAvail( uart_base[ CON_UART_ID ] ) ) + { + c = UARTCharGetNonBlocking( uart_base[ CON_UART_ID ] ); + buf_write( BUF_ID_UART, CON_UART_ID, ( t_buf_data* )&c, sizeof ( t_buf_data ) ); + } +} +#endif + + static void uarts_init() { unsigned i; @@ -255,6 +273,17 @@ static void uarts_init() UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), CON_UART_SPEED, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); + + +#if defined( BUF_ENABLE_UART ) && defined( CON_BUF_SIZE ) + // Enable buffering on the console UART + buf_set( BUF_ID_UART, CON_UART_ID, CON_BUF_SIZE, sizeof ( t_buf_data ) ); + // Set interrupt handler and interrupt flag on UART + + IntEnable(INT_UART0); + + UARTIntEnable( uart_base[ CON_UART_ID ], UART_INT_RX | UART_INT_RT ); +#endif } u32 platform_uart_setup( unsigned id, u32 baud, int databits, int parity, int stopbits ) diff --git a/src/platform/lm3s/platform_conf.h b/src/platform/lm3s/platform_conf.h index 91d85b6b..c36f367c 100644 --- a/src/platform/lm3s/platform_conf.h +++ b/src/platform/lm3s/platform_conf.h @@ -98,6 +98,10 @@ LUALIB_API int ( luaopen_disp )( lua_State* L ); #define NUM_PWM 6 #define NUM_ADC 4 +// Enable RX buffering on UART +#define BUF_ENABLE_UART +#define CON_BUF_SIZE BUF_SIZE_128 + // ADC Bit Depth for Built-in ADCs #define ADC_BIT_RESOLUTION 10 diff --git a/src/platform/lm3s/startup_gcc.c b/src/platform/lm3s/startup_gcc.c index 6f2b569b..395c3de1 100644 --- a/src/platform/lm3s/startup_gcc.c +++ b/src/platform/lm3s/startup_gcc.c @@ -40,8 +40,10 @@ static void IntDefaultHandler(void); extern void EthernetIntHandler(); extern void SysTickIntHandler(); extern void ADCIntHandler(); +extern void UARTIntHandler(); #include "hw_memmap.h" +#include "platform_conf.h" //***************************************************************************** // @@ -82,7 +84,11 @@ void (* const g_pfnVectors[])(void) = IntDefaultHandler, // GPIO Port C IntDefaultHandler, // GPIO Port D IntDefaultHandler, // GPIO Port E - IntDefaultHandler, // UART0 Rx and Tx +#ifdef BUF_ENABLE_UART + UARTIntHandler, // UART0 Rx and Tx +#else + IntDefaultHandler, +#endif IntDefaultHandler, // UART1 Rx and Tx IntDefaultHandler, // SSI0 Rx and Tx IntDefaultHandler, // I2C0 Master and Slave