// 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 ) { volatile struct elua_uip_state *pstate = ( volatile struct elua_uip_state* )&( uip_conns[ s ].appstate ); u32 tmrstart = 0; int old_status; if( !ELUA_UIP_IS_SOCK_OK( s ) || !uip_conn_active( s ) ) return -1; if( maxsize == 0 ) 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 ); 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 ) { old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); if( pstate->state != ELUA_UIP_STATE_IDLE ) { pstate->res = ELUA_NET_ERR_TIMEDOUT; pstate->state = ELUA_UIP_STATE_IDLE; } platform_cpu_set_global_interrupts( old_status ); break; } } return maxsize - pstate->len; }
// 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 ) { u32 tmrstart = 0; int old_status; if( !elua_uip_configured ) return -1; #ifdef BUILD_CON_TCP if( port == ELUA_NET_TELNET_PORT ) return -1; #endif old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); uip_unlisten( htons( port ) ); uip_listen( htons( port ) ); platform_cpu_set_global_interrupts( old_status ); 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 ); 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 ) { elua_uip_accept_request = 0; break; } } *pfrom = elua_uip_accept_remote; return elua_uip_accept_sock; }
LUA_API void lua_close (lua_State *L) { #ifndef LUA_CROSS_COMPILER // ToDo: Revise // Removing unsupported functions from the close. #ifndef __PIC32MX int oldstate = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); lua_sethook( L, NULL, 0, 0 ); lua_crtstate = NULL; lua_pushnil( L ); lua_rawseti( L, LUA_REGISTRYINDEX, LUA_INT_HANDLER_KEY ); elua_int_cleanup(); platform_cpu_set_global_interrupts( oldstate ); linenoise_cleanup( LINENOISE_ID_LUA ); #endif #endif L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ L->errfunc = 0; /* no error function during GC metamethods */ do { /* repeat until no more errors */ L->ci = L->base_ci; L->base = L->top = L->ci->base; L->nCcalls = L->baseCcalls = 0; } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); lua_assert(G(L)->tmudata == NULL); luai_userstateclose(L); close_state(L); }
int elua_net_socket( int type ) { int i; struct uip_conn* pconn; int old_status; // [TODO] add UDP support at some point. if( type == ELUA_NET_SOCK_DGRAM ) return -1; old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); // Iterate through the list of connections, looking for a free one for( i = 0; i < UIP_CONNS; i ++ ) { pconn = uip_conns + i; if( pconn->tcpstateflags == UIP_CLOSED ) { // Found a free connection, reserve it for later use uip_conn_reserve( i ); break; } } platform_cpu_set_global_interrupts( old_status ); return i == UIP_CONNS ? -1 : i; }
// Our hook function (called by the Lua VM) static void elua_int_hook( lua_State *L, lua_Debug *ar ) { elua_int_element crt; int old_status; // Get interrupt (and remove from queue) crt = elua_int_queue[ elua_int_read_idx ]; elua_int_queue[ elua_int_read_idx ].id = ELUA_INT_EMPTY_SLOT; elua_int_read_idx = ( elua_int_read_idx + 1 ) & INT_IDX_MASK; if( elua_int_is_enabled( crt.id ) ) { // Call Lua handler // Get interrupt handler table lua_rawgeti( L, LUA_REGISTRYINDEX, LUA_INT_HANDLER_KEY ); // inttable lua_rawgeti( L, -1, crt.id ); // inttable f if( !lua_isnil( L, -1 ) ) { lua_pushinteger( L, crt.resnum ); // inttable f resnum lua_call( L, 1, 0 ); // inttable } else lua_remove( L, -1 ); // inttable lua_remove( L, -1 ); } old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); if( elua_int_queue[ elua_int_read_idx ].id == ELUA_INT_EMPTY_SLOT ) // no more interrupts in the queue, so clear the hook lua_sethook( L, NULL, 0, 0 ); platform_cpu_set_global_interrupts( old_status ); }
// Helper function: setup timers static void platform_setup_timers() { unsigned i; PREG TxTCR; // Set base frequency to 1MHz, as we can't use a better resolution anyway for( i = 0; i < 4; i ++ ) { TxTCR = ( PREG )tmr_tcr[ i ]; *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 T3TCR = TMR_RESET; T3MR0 = 1000000ULL / VTMR_FREQ_HZ - 1; T3IR = 0xFF; // Set interrupt handle and eanble timer interrupt (and global interrupts) T3MCR = 0x03; // interrupt on match with MR0 and clear on match install_irq( TIMER3_INT, int_handler_tmr, HIGHEST_PRIORITY ); platform_cpu_set_global_interrupts( PLATFORM_CPU_ENABLE ); // Start timer T3TCR = TMR_ENABLE; #endif }
// Lua: cli() // Lua: cli() - to disable all interrupts // or cli( id1, resnum1, [resnum2], ..., [resnumn] ) - to disable a specific id/resnum(s) static int cpu_cli( lua_State *L ) { #ifdef BUILD_LUA_INT_HANDLERS unsigned i; elua_int_id id; elua_int_resnum resnum; if( lua_gettop( L ) > 0 ) { id = ( elua_int_id )luaL_checkinteger( L, 1 ); for( i = 2; i <= lua_gettop( L ); i ++ ) { resnum = ( elua_int_resnum )luaL_checkinteger( L, i ); platform_cpu_set_interrupt( id, resnum, PLATFORM_CPU_DISABLE ); } elua_int_disable( id ); } else #else // #ifdef BUILD_LUA_INT_HANDLERS if( lua_gettop( L ) > 0 ) return luaL_error( L, "Lua interrupt support not available." ); #endif // #ifdef BUILD_LUA_INT_HANDLERS platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); return 0; }
// 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 ) { BUF_CHECK_RESNUM( resid, resnum ); BUF_GETPTR( resid, resnum ); int old_status; const char* s = ( const char* )( pbuf->buf + pbuf->rptr ); char* d = ( char* )data; if( pbuf->logsize == BUF_SIZE_NONE || READ16( pbuf->count ) == 0 ) return PLATFORM_UNDERFLOW; DUFF_DEVICE_8( BUF_REALDSIZE( pbuf ), *d++ = *s++ ); old_status = platform_cpu_set_global_interrupts( PLATFORM_CPU_DISABLE ); pbuf->count --; platform_cpu_set_global_interrupts( old_status ); BUF_MOD_INCR( pbuf, rptr ); return PLATFORM_OK; }
// Lua: sei() - to enable all interrupts // or sei( id1, resnum1, [resnum2], ..., [resnumn] ) - to enable a specific id/resnum(s) static int cpu_sei( lua_State *L ) { unsigned i; elua_int_id id; elua_int_resnum resnum; if( lua_gettop( L ) > 0 ) { id = ( elua_int_id )luaL_checkinteger( L, 1 ); for( i = 2; i <= lua_gettop( L ); i ++ ) { resnum = ( elua_int_resnum )luaL_checkinteger( L, i ); platform_cpu_set_interrupt( id, resnum, PLATFORM_CPU_ENABLE ); } elua_int_enable( id ); } else platform_cpu_set_global_interrupts( PLATFORM_CPU_ENABLE ); return 0; }