@ -68,6 +68,11 @@ typedef struct _rp2_state_machine_irq_obj_t {
STATIC const rp2_state_machine_obj_t rp2_state_machine_obj [ 8 ] ;
STATIC uint8_t rp2_state_machine_initial_pc [ 8 ] ;
// These masks keep track of PIO instruction memory used by this module.
STATIC uint32_t rp2_pio_instruction_memory_usage_mask [ 2 ] ;
STATIC const rp2_state_machine_obj_t * rp2_state_machine_get_object ( mp_int_t sm_id ) ;
STATIC void rp2_state_machine_reset_all ( void ) ;
STATIC mp_obj_t rp2_state_machine_init_helper ( const rp2_state_machine_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) ;
STATIC void pio_irq0 ( PIO pio ) {
@ -101,16 +106,42 @@ STATIC void pio1_irq0(void) {
pio_irq0 ( pio1 ) ;
}
void rp2_pio_init ( void ) {
// Reset all PIO instruction memory.
# if MICROPY_PY_NETWORK_CYW43
// TODO: cannot reset PIO memory when CYW43 driver is enabled and active
// because it uses a PIO for the bus interface.
# else
pio_clear_instruction_memory ( pio0 ) ;
pio_clear_instruction_memory ( pio1 ) ;
# endif
// Calls pio_add_program() and keeps track of used instruction memory.
STATIC uint rp2_pio_add_managed_program ( PIO pio , struct pio_program * pio_program ) {
uint offset = pio_add_program ( pio , pio_program ) ;
uint32_t mask = ( ( 1 < < pio_program - > length ) - 1 ) < < offset ;
rp2_pio_instruction_memory_usage_mask [ pio_get_index ( pio ) ] | = mask ;
return offset ;
}
// Calls pio_remove_program() and keeps track of used instruction memory.
STATIC void rp2_pio_remove_managed_program ( PIO pio , struct pio_program * pio_program , uint offset ) {
pio_remove_program ( pio , pio_program , offset ) ;
uint32_t mask = ( ( 1 < < pio_program - > length ) - 1 ) < < offset ;
rp2_pio_instruction_memory_usage_mask [ pio_get_index ( pio ) ] & = ~ mask ;
}
// Calls pio_remove_program() for all programs registered with rp2_pio_add_managed_program(),
// that weren't already removed via rp2_pio_remove_managed_program().
STATIC void rp2_pio_remove_all_managed_programs ( PIO pio ) {
uint32_t mask = rp2_pio_instruction_memory_usage_mask [ pio_get_index ( pio ) ] ;
for ( size_t i = 0 ; i < 32 ; + + i ) {
if ( mask & ( 1 < < i ) ) {
size_t j ;
for ( j = i + 1 ; j < 32 ; + + j ) {
if ( ! ( mask & ( 1 < < j ) ) ) {
break ;
}
}
struct pio_program pio_program = { NULL , j - i , - 1 } ;
pio_remove_program ( pio , & pio_program , i ) ;
i = j ; // i indexes an unused bit, or is 32
}
}
rp2_pio_instruction_memory_usage_mask [ pio_get_index ( pio ) ] = 0 ;
}
void rp2_pio_init ( void ) {
// Set up interrupts.
memset ( MP_STATE_PORT ( rp2_pio_irq_obj ) , 0 , sizeof ( MP_STATE_PORT ( rp2_pio_irq_obj ) ) ) ;
memset ( MP_STATE_PORT ( rp2_state_machine_irq_obj ) , 0 , sizeof ( MP_STATE_PORT ( rp2_state_machine_irq_obj ) ) ) ;
@ -123,6 +154,14 @@ void rp2_pio_deinit(void) {
irq_set_mask_enabled ( ( 1u < < PIO0_IRQ_0 ) | ( 1u < < PIO0_IRQ_1 ) , false ) ;
irq_remove_handler ( PIO0_IRQ_0 , pio0_irq0 ) ;
irq_remove_handler ( PIO1_IRQ_0 , pio1_irq0 ) ;
rp2_state_machine_reset_all ( ) ;
// Reset all PIO instruction memory allocated by this module.
// Note: other subsystems (eg the CYW43 driver) may use the PIO,
// and their PIO programs should remain intact.
rp2_pio_remove_all_managed_programs ( pio0 ) ;
rp2_pio_remove_all_managed_programs ( pio1 ) ;
}
/******************************************************************************/
@ -238,7 +277,7 @@ STATIC mp_obj_t rp2_pio_add_program(mp_obj_t self_in, mp_obj_t prog_in) {
if ( ! pio_can_add_program ( self - > pio , & pio_program ) ) {
mp_raise_OSError ( MP_ENOMEM ) ;
}
uint offset = pio_add_program ( self - > pio , & pio_program ) ;
uint offset = rp2_ pio_add_manage d_program( self - > pio , & pio_program ) ;
// Store the program offset in the program object.
prog [ PROG_OFFSET_PIO0 + PIO_NUM ( self - > pio ) ] = MP_OBJ_NEW_SMALL_INT ( offset ) ;
@ -272,7 +311,7 @@ STATIC mp_obj_t rp2_pio_remove_program(size_t n_args, const mp_obj_t *args) {
// Remove the program from the instruction memory.
struct pio_program pio_program = { NULL , length , - 1 } ;
pio_remove_program ( self - > pio , & pio_program , offset ) ;
rp2_ pio_remove_managed _program( self - > pio , & pio_program , offset ) ;
return mp_const_none ;
}
@ -285,11 +324,11 @@ STATIC mp_obj_t rp2_pio_state_machine(size_t n_args, const mp_obj_t *pos_args, m
// Get and verify the state machine id.
mp_int_t sm_id = mp_obj_get_int ( pos_args [ 1 ] ) ;
if ( ! ( 0 < = sm_id & & sm_id < 4 ) ) {
mp_raise_ValueError ( " invalide state m achine " ) ;
mp_raise_ValueError ( " invalid StateM achine " ) ;
}
// Return the correct StateMachine object.
const rp2_state_machine_obj_t * sm = & rp2_state_machine_obj [ ( self - > pio = = pio0 ? 0 : 4 ) + sm_id ] ;
const rp2_state_machine_obj_t * sm = rp2_state_machine_get_object ( ( self - > pio = = pio0 ? 0 : 4 ) + sm_id ) ;
if ( n_args > 2 | | kw_args - > used > 0 ) {
// Configuration arguments given so init this StateMachine.
@ -414,6 +453,9 @@ STATIC const mp_irq_methods_t rp2_pio_irq_methods = {
/******************************************************************************/
// StateMachine object
// This mask keeps track of state machines claimed by this module.
STATIC uint32_t rp2_state_machine_claimed_mask ;
STATIC const mp_irq_methods_t rp2_state_machine_irq_methods ;
STATIC const rp2_state_machine_obj_t rp2_state_machine_obj [ ] = {
@ -427,6 +469,35 @@ STATIC const rp2_state_machine_obj_t rp2_state_machine_obj[] = {
{ { & rp2_state_machine_type } , pio1 , PIO1_IRQ_0 , 3 , 7 } ,
} ;
STATIC const rp2_state_machine_obj_t * rp2_state_machine_get_object ( mp_int_t sm_id ) {
if ( ! ( 0 < = sm_id & & sm_id < MP_ARRAY_SIZE ( rp2_state_machine_obj ) ) ) {
mp_raise_ValueError ( " invalid StateMachine " ) ;
}
const rp2_state_machine_obj_t * sm_obj = & rp2_state_machine_obj [ sm_id ] ;
if ( ! ( rp2_state_machine_claimed_mask & ( 1 < < sm_id ) ) ) {
if ( pio_sm_is_claimed ( sm_obj - > pio , sm_obj - > sm ) ) {
mp_raise_ValueError ( " StateMachine claimed by external resource " ) ;
}
pio_sm_claim ( sm_obj - > pio , sm_obj - > sm ) ;
rp2_state_machine_claimed_mask | = 1 < < sm_id ;
}
return sm_obj ;
}
STATIC void rp2_state_machine_reset_all ( void ) {
for ( size_t i = 0 ; i < MP_ARRAY_SIZE ( rp2_state_machine_obj ) ; + + i ) {
if ( rp2_state_machine_claimed_mask & ( 1 < < i ) ) {
const rp2_state_machine_obj_t * sm_obj = & rp2_state_machine_obj [ i ] ;
pio_sm_unclaim ( sm_obj - > pio , sm_obj - > sm ) ;
pio_sm_set_enabled ( sm_obj - > pio , sm_obj - > sm , false ) ;
}
}
rp2_state_machine_claimed_mask = 0 ;
}
STATIC void rp2_state_machine_print ( const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
rp2_state_machine_obj_t * self = MP_OBJ_TO_PTR ( self_in ) ;
mp_printf ( print , " StateMachine(%u) " , self - > id ) ;
@ -573,10 +644,7 @@ STATIC mp_obj_t rp2_state_machine_make_new(const mp_obj_type_t *type, size_t n_a
// Get the StateMachine object.
mp_int_t sm_id = mp_obj_get_int ( args [ 0 ] ) ;
if ( ! ( 0 < = sm_id & & sm_id < MP_ARRAY_SIZE ( rp2_state_machine_obj ) ) ) {
mp_raise_ValueError ( " invalid StateMachine " ) ;
}
const rp2_state_machine_obj_t * self = & rp2_state_machine_obj [ sm_id ] ;
const rp2_state_machine_obj_t * self = rp2_state_machine_get_object ( sm_id ) ;
if ( n_args > 1 | | n_kw > 0 ) {
// Configuration arguments given so init this StateMachine.