// Helper function: pin operations // Gets the stack index of the first pin and the operation static int pioh_set_pins( lua_State* L, int stackidx, int op ) { int total = lua_gettop( L ); int i, v, port, pin; pioh_clear_masks(); // Get all masks for( i = stackidx; i <= total; i ++ ) { v = luaL_checkinteger( L, i ); port = PLATFORM_IO_GET_PORT( v ); pin = PLATFORM_IO_GET_PIN( v ); if( PLATFORM_IO_IS_PORT( v ) || !platform_pio_has_port( port ) || !platform_pio_has_pin( port, pin ) ) return luaL_error( L, "invalid pin" ); pio_masks[ port ] |= 1 << pin; } // Ask platform to execute the given operation for( i = 0; i < PLATFORM_IO_PORTS; i ++ ) if( pio_masks[ i ] ) if( !platform_pio_op( i, pio_masks[ i ], op ) ) return luaL_error( L, "invalid PIO operation" ); return 0; }
static int int_gpio_negedge_set_status( elua_int_resnum resnum, int status ) { unsigned long portbase = pio_base[ PLATFORM_IO_GET_PORT( resnum ) ]; u8 pinmask = 1 << PLATFORM_IO_GET_PIN( resnum ); int prev = int_gpio_posedge_get_status( resnum ); int crtstat = inth_gpio_get_int_status( resnum ); if( status == PLATFORM_CPU_ENABLE ) { // If already configured for rising edge, set both edges // Otherwise set only negedge if( crtstat & GPIO_INT_POSEDGE_ENABLED ) HWREG( portbase + GPIO_O_IBE ) |= pinmask; else HWREG( portbase + GPIO_O_IEV ) &= ( u8 )~pinmask; MAP_GPIOPinIntEnable( portbase, pinmask ); } else { // If configured for both, enable only rising edge // Otherwise disable interrupts completely if( crtstat == GPIO_INT_BOTH_ENABLED ) { HWREG( portbase + GPIO_O_IBE ) &= ( u8 )~pinmask; HWREG( portbase + GPIO_O_IEV ) |= pinmask; } else if( crtstat == GPIO_INT_NEGEDGE_ENABLED ) MAP_GPIOPinIntDisable( portbase, pinmask ); } return prev; }
// Lua: stm32.pio.set_function( function, pin1, pin2, ..., pinn ) // Function can be stm32.pio.GPIO, stm32.pio.AFx (x = 0..15), stm32.pio.ADC static int stm32_pio_set_function( lua_State *L ) { int func = luaL_checkinteger( L, 1 ), gpio, pin, port, idx; int total = lua_gettop( L ), i; GPIO_TypeDef *base; if( total == 1 ) return luaL_error( L, "no pin specified" ); for( i = 2; i <= total; i ++ ) { gpio = luaL_checkinteger( L, i ); port = PLATFORM_IO_GET_PORT( gpio ); pin = PLATFORM_IO_GET_PIN( gpio ); base = pio_port[ port ]; if( func == PIN_FUNC_GPIO ) base->MODER &= ~( 0x03 << ( pin * 2 ) ); else if( func == PIN_FUNC_ADC ) base->MODER |= 0x03 << ( pin * 2 ); else if( func >= PIN_FUNC_ALT_FIRST && func <= PIN_FUNC_ALT_LAST ) { base->MODER &= ~( 0x03 << ( pin * 2 ) ); base->MODER |= 0x02 << ( pin * 2 ); if( pin >= 8 ) { pin -= 8; idx = 1; } else idx = 0; base->AFR[ idx ] &= ~( 0x0F << ( pin * 4 ) ); base->AFR[ idx ] |= func << ( pin * 4 ); } } return 0; }
static int pio_decode( lua_State *L ) { int code = ( int )luaL_checkinteger( L, 1 ); lua_pushinteger( L, PLATFORM_IO_GET_PORT( code ) ); lua_pushinteger( L, PLATFORM_IO_GET_PIN( code ) ); return 2; }
static int int_gpio_negedge_get_status( elua_int_resnum resnum ) { int port = PLATFORM_IO_GET_PORT( resnum ), pin = PLATFORM_IO_GET_PIN( resnum ); unsigned long type; if( ( HWREG( pio_base[ port ] + GPIO_O_IM ) & ( 1 << pin ) ) == 0 ) return 0; type = MAP_GPIOIntTypeGet( pio_base[ port ], pin ); return ( type == GPIO_FALLING_EDGE || type == GPIO_BOTH_EDGES ) ? 1 : 0; }
static int gpioh_get_int_status( elua_int_id id, elua_int_resnum resnum ) { int port, pin; port = PLATFORM_IO_GET_PORT( resnum ); pin = PLATFORM_IO_GET_PIN( resnum ); if( id == INT_GPIO_POSEDGE ) return *posedge_regs[ port ] & ( 1 << pin ); else return *negedge_regs[ port ] & ( 1 << pin ); return 0; }
// Get GPIO interrupt status as a mask static int inth_gpio_get_int_status( elua_int_resnum resnum ) { const u32 portbase = pio_base[ PLATFORM_IO_GET_PORT( resnum ) ]; const u8 pinmask = 1 << PLATFORM_IO_GET_PIN( resnum ); if( ( HWREG( portbase + GPIO_O_IM ) & pinmask ) == 0 ) return 0; if( ( HWREG( portbase + GPIO_O_IBE ) & pinmask ) != 0 ) return GPIO_INT_BOTH_ENABLED; else if( ( HWREG( portbase + GPIO_O_IEV ) & pinmask ) != 0 ) return GPIO_INT_POSEDGE_ENABLED; else return GPIO_INT_NEGEDGE_ENABLED; }
static int int_gpio_negedge_get_flag( elua_int_resnum resnum, int clear ) { unsigned long portbase = pio_base[ PLATFORM_IO_GET_PORT( resnum ) ]; u8 pinmask = 1 << PLATFORM_IO_GET_PIN( resnum ); if( MAP_GPIOPinRead( portbase, pinmask ) != 0 ) return 0; if( MAP_GPIOPinIntStatus( portbase, true ) & pinmask ) { if( clear ) MAP_GPIOPinIntClear( portbase, pinmask ); return 1; } return 0; }
static void all_exti_irqhandler( int line ) { u16 v, port, pin; v = exti_line_to_gpio( line ); port = PLATFORM_IO_GET_PORT( v ); pin = PLATFORM_IO_GET_PIN( v ); if( EXTI->RTSR & (1 << line ) && platform_pio_op( port, 1 << pin, PLATFORM_IO_PIN_GET ) ) cmn_int_handler( INT_GPIO_POSEDGE, v ); if( EXTI->FTSR & (1 << line ) && ( platform_pio_op( port, 1 << pin, PLATFORM_IO_PIN_GET ) == 0 ) ) cmn_int_handler( INT_GPIO_NEGEDGE, v ); EXTI_ClearITPendingBit( exti_line[ line ] ); }
// Lua: pin1, pin2, ..., pinn = pio.pin.getval( pin1, pin2, ..., pinn ) static int pio_pin_getval( lua_State *L ) { pio_type value; int v, i, port, pin; int total = lua_gettop( L ); for( i = 1; i <= total; i ++ ) { v = luaL_checkinteger( L, i ); port = PLATFORM_IO_GET_PORT( v ); pin = PLATFORM_IO_GET_PIN( v ); if( PLATFORM_IO_IS_PORT( v ) || !platform_pio_has_port( port ) || !platform_pio_has_pin( port, pin ) ) return luaL_error( L, "invalid pin" ); else { value = platform_pio_op( port, 1 << pin, PLATFORM_IO_PIN_GET ); lua_pushinteger( L, value ); } } return total; }
static int gpioh_set_int_status( elua_int_id id, elua_int_resnum resnum, int status ) { int prev = gpioh_get_int_status( id, resnum ); u32 mask = 1 << exint_gpio_to_src( resnum ); EXTI_InitTypeDef exti_init_struct; if( status == PLATFORM_CPU_ENABLE ) { // Configure port for interrupt line GPIO_EXTILineConfig( PLATFORM_IO_GET_PORT( resnum ), PLATFORM_IO_GET_PIN( resnum ) ); EXTI_StructInit(&exti_init_struct); exti_init_struct.EXTI_Line = exti_line[ exint_gpio_to_src( resnum ) ]; exti_init_struct.EXTI_Mode = EXTI_Mode_Interrupt; if( ( ( ( EXTI->RTSR & mask ) != 0 ) && ( id == INT_GPIO_NEGEDGE ) ) || ( ( ( EXTI->FTSR & mask ) != 0 ) && ( id == INT_GPIO_POSEDGE ) ) ) exti_init_struct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; else exti_init_struct.EXTI_Trigger = id == INT_GPIO_POSEDGE ? EXTI_Trigger_Rising : EXTI_Trigger_Falling; exti_init_struct.EXTI_LineCmd = ENABLE; EXTI_Init(&exti_init_struct); EXTI_ClearITPendingBit( exti_line[ exint_gpio_to_src( resnum ) ] ); } else { //Disable edge if( id == INT_GPIO_POSEDGE ) EXTI->RTSR &= ~mask; else EXTI->FTSR &= ~mask; //If no edges enabled, disable line interrupt if( ( ( EXTI->RTSR | EXTI->FTSR ) & mask ) == 0 ) EXTI->IMR &= ~mask; } return prev; }
static int configpin( lua_State* L ) { pio_type v = ( pio_type )luaL_checkinteger( L, 1 ); int funcnum = luaL_checkinteger( L, 2 ); int opendrain = luaL_checkinteger( L, 3 ); int pinmode = luaL_checkinteger( L, 4 ); PINSEL_CFG_Type PinCfg; int port, pin; port = PLATFORM_IO_GET_PORT( v ); pin = PLATFORM_IO_GET_PIN( v ); if( PLATFORM_IO_IS_PORT( v ) || !platform_pio_has_port( port ) || !platform_pio_has_pin( port, pin ) ) return luaL_error( L, "invalid pin" ); PinCfg.Funcnum = funcnum; PinCfg.OpenDrain = opendrain; PinCfg.Pinmode = pinmode; PinCfg.Portnum = port; PinCfg.Pinnum = pin; PINSEL_ConfigPin(&PinCfg); return 0; }
static int gpioh_set_int_status( elua_int_id id, elua_int_resnum resnum, int status ) { int crt_status = gpioh_get_int_status( id, resnum ); int port, pin; port = PLATFORM_IO_GET_PORT( resnum ); pin = PLATFORM_IO_GET_PIN( resnum ); if( id == INT_GPIO_POSEDGE ) { if( status == PLATFORM_CPU_ENABLE ) *posedge_regs[ port ] |= 1 << pin; else *posedge_regs[ port ] &= ~( 1 << pin ); } else { if( status == PLATFORM_CPU_ENABLE ) *negedge_regs[ port ] |= 1 << pin; else *negedge_regs[ port ] &= ~( 1 << pin ); } EXTINT |= 1 << EINT3_BIT; return crt_status; }
// Convert a GPIO ID to a EXINT number static int exint_gpio_to_src( pio_type piodata ) { u16 pin = PLATFORM_IO_GET_PIN( piodata ); return pin; }