/* * This interrupt service routine is called for an External Exception. */ rtems_isr external_exception_ISR ( rtems_vector_number vector /* IN */ ) { uint16_t index; EE_ISR_Type *node; uint16_t value; #if (HAS_PMC_PSC8) uint16_t PMC_irq; uint16_t check_irq; uint16_t status_word; #endif index = read_and_clear_irq(); if ( index >= NUM_LIRQ ) { printk( "ERROR:: Invalid interrupt number (%02x)\n", index ); return; } #if (HAS_PMC_PSC8) PMC_irq = SCORE603E_PCI_IRQ_0 - SCORE603E_IRQ00; if (index == PMC_irq) { status_word = read_and_clear_PMC_irq( index ); for (check_irq=SCORE603E_IRQ16; check_irq<=SCORE603E_IRQ19; check_irq++) { if ( Is_PMC_IRQ( check_irq, status_word )) { index = check_irq - SCORE603E_IRQ00; node = (EE_ISR_Type *)(ISR_Array[ index ].first); if ( rtems_chain_is_tail( &ISR_Array[ index ], (void *)node ) ) { printk ("ERROR:: check %d interrupt %02d has no isr\n", check_irq, index); value = get_irq_mask(); printk(" Mask = %02x\n", value); } while ( !rtems_chain_is_tail( &ISR_Array[ index ], (void *)node ) ) { (*node->handler)( node->vector ); node = (EE_ISR_Type *) node->Node.next; } } } } else #endif { node = (EE_ISR_Type *)(ISR_Array[ index ].first); if ( rtems_chain_is_tail( &ISR_Array[ index ], (void *)node ) ) { printk( "ERROR:: interrupt %02x has no isr\n", index); value = get_irq_mask(); printk(" Mask = %02x\n", value); return; } while ( !rtems_chain_is_tail( &ISR_Array[ index ], (void *)node ) ) { (*node->handler)( node->vector ); node = (EE_ISR_Type *) node->Node.next; } } }
void unmask_irq( uint16_t irq_idx ) { uint16_t value; uint32_t mask_idx = irq_idx; value = get_irq_mask(); #if (HAS_PMC_PSC8) switch (irq_idx + Score_IRQ_First ) { case SCORE603E_85C30_4_IRQ: case SCORE603E_85C30_2_IRQ: case SCORE603E_85C30_5_IRQ: case SCORE603E_85C30_3_IRQ: mask_idx = SCORE603E_PCI_IRQ_0 - Score_IRQ_First; break; default: break; } #endif value &= (~(0x1 << mask_idx)); set_irq_mask( value ); }
_mqx_int gpio_cpu_ioctl ( /* [IN] the file handle for the device */ MQX_FILE_PTR fd_ptr, /* [IN] the ioctl command */ _mqx_uint cmd, /* [IN] the ioctl parameters */ pointer param_ptr ) { /* Body */ GPIO_DEV_DATA_PTR dev_data_ptr = (GPIO_DEV_DATA_PTR) fd_ptr->DEV_DATA_PTR; switch (cmd) { case GPIO_IOCTL_ADD_PINS: { /* Add pins to this file. Params: table with pin addresses */ GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; uint_32 pin; /* check pin_table if they are not in global pin_map */ _int_disable(); for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* check pin validity bit */ if (*pin_table & GPIO_PIN_VALID) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* pin address out of map scope? */ if (addr < sizeof(GPIO_PIN_MAP) * 8 / (GPIO_PIN_BIT_MASK + 1)) { /* pin address already used? */ if (! (gpio_global_pin_map.memory32[addr] & pin)) { /* manage next pin */ continue; } } } /* some problem occured */ _int_enable(); return IO_ERROR; } /* check successful, now we have to copy these bits to local pin map */ for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* mark pin as used by this file */ dev_data_ptr->pin_map.memory32[addr] |= pin; /* mark pin as used globally */ gpio_global_pin_map.memory32[addr] |= pin; } gpio_cpu_configure(dev_data_ptr); _int_enable(); } break; case GPIO_IOCTL_WRITE_LOG1: { /* If this file is configured as output, sets every pin to 1. Params: list of pin addresses to be used or NULL for every pin in the file */ if (dev_data_ptr->type != DEV_OUTPUT) return IO_ERROR; if (param_ptr == NULL) { /* apply command to whole file */ _int_disable(); /* _lwsem_wait(&gpio_sem) replacement */ GPIOA_PSOR = dev_data_ptr->pin_map.memory32[0]; GPIOB_PSOR = dev_data_ptr->pin_map.memory32[1]; GPIOC_PSOR = dev_data_ptr->pin_map.memory32[2]; GPIOD_PSOR = dev_data_ptr->pin_map.memory32[3]; GPIOE_PSOR = dev_data_ptr->pin_map.memory32[4]; _int_enable(); break; } else { GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; uint_32 pin; GPIO_PIN_MAP temp_pin_map = {0}; _int_disable(); /* check if there is not pin in the list which this file does not contain */ for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* check pin validity bit */ if (*pin_table & GPIO_PIN_VALID) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* pin address out of map scope? */ if (addr < sizeof(GPIO_PIN_MAP) * 8 / (GPIO_PIN_BIT_MASK + 1)) { /* pin address already used? */ if (dev_data_ptr->pin_map.memory32[addr] & pin) { temp_pin_map.memory32[addr] |= pin; continue; /* manage next pin */ } } } /* some problem occured */ _int_enable(); return IO_ERROR; } /* ok, now we can apply new map */ /* note: applying the map after collecting pins is due to have pins applied in one instruction */ GPIOA_PSOR = temp_pin_map.memory32[0]; GPIOB_PSOR = temp_pin_map.memory32[1]; GPIOC_PSOR = temp_pin_map.memory32[2]; GPIOD_PSOR = temp_pin_map.memory32[3]; GPIOE_PSOR = temp_pin_map.memory32[4]; _int_enable(); } } break; case GPIO_IOCTL_WRITE_LOG0: { /* If this file is configured as output, clears every pin to 0. Params: list of pin addresses to be used or NULL for every pin in the file */ if (dev_data_ptr->type != DEV_OUTPUT) return IO_ERROR; /* apply command to whole file */ if (param_ptr == NULL) { _int_disable(); /* _lwsem_wait(&gpio_sem) replacement */ GPIOA_PCOR = dev_data_ptr->pin_map.memory32[0]; GPIOB_PCOR = dev_data_ptr->pin_map.memory32[1]; GPIOC_PCOR = dev_data_ptr->pin_map.memory32[2]; GPIOD_PCOR = dev_data_ptr->pin_map.memory32[3]; GPIOE_PCOR = dev_data_ptr->pin_map.memory32[4]; _int_enable(); break; } else { GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; uint_32 pin; GPIO_PIN_MAP temp_pin_map = {0}; _int_disable(); /* check if there is not pin in the list which this file does not contain */ for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* check pin validity bit */ if (*pin_table & GPIO_PIN_VALID) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* pin address out of map scope? */ if (addr < sizeof(GPIO_PIN_MAP) * 8 / (GPIO_PIN_BIT_MASK + 1)) { /* pin address already used? */ if (dev_data_ptr->pin_map.memory32[addr] & pin) { temp_pin_map.memory32[addr] |= pin; continue; /* manage next pin */ } } } /* some problem occurred */ _int_enable(); return IO_ERROR; } /* ok, now we can apply new map */ /* note: applying the map after collecting pins is due to have pins applied in one instruction */ GPIOA_PCOR = temp_pin_map.memory32[0]; GPIOB_PCOR = temp_pin_map.memory32[1]; GPIOC_PCOR = temp_pin_map.memory32[2]; GPIOD_PCOR = temp_pin_map.memory32[3]; GPIOE_PCOR = temp_pin_map.memory32[4]; _int_enable(); } } break; case GPIO_IOCTL_WRITE: { /* If this file is configured as output, sets every pin to the state ** defined in GPIO_PIN_STATUS. Params: ** list of pin addresses to be used or NULL for every pin in the file */ if (dev_data_ptr->type != DEV_OUTPUT) return IO_ERROR; if (param_ptr == NULL) /* no param specified , but must be */ return IO_ERROR; else { GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; uint_32 pin; GPIO_PIN_MAP temp_pin0_map = {0}; GPIO_PIN_MAP temp_pin1_map = {0}; _int_disable(); /* check if there is not pin in the list which this file does not contain */ for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* check pin validity bit */ if (*pin_table & GPIO_PIN_VALID) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* pin address out of map scope? */ if (addr < sizeof(GPIO_PIN_MAP) * 8 / (GPIO_PIN_BIT_MASK + 1)) { /* pin address already used? */ if (dev_data_ptr->pin_map.memory32[addr] & pin) { if (*pin_table & GPIO_PIN_STATUS) temp_pin1_map.memory32[addr] |= pin; else temp_pin0_map.memory32[addr] |= pin; continue; /* manage next pin */ } } } /* some problem occurred */ _int_enable(); return IO_ERROR; } /* ok, now we can apply new map */ /* note: applying the map after collecting pins is due to have pins applied in one instruction */ GPIOA_PSOR = temp_pin1_map.memory32[0]; GPIOA_PCOR = temp_pin0_map.memory32[0]; GPIOB_PSOR = temp_pin1_map.memory32[1]; GPIOB_PCOR = temp_pin0_map.memory32[1]; GPIOC_PSOR = temp_pin1_map.memory32[2]; GPIOC_PCOR = temp_pin0_map.memory32[2]; GPIOD_PSOR = temp_pin1_map.memory32[3]; GPIOD_PCOR = temp_pin0_map.memory32[3]; GPIOE_PSOR = temp_pin1_map.memory32[4]; GPIOE_PCOR = temp_pin0_map.memory32[4]; _int_enable(); } } break; case GPIO_IOCTL_READ: { /* Read status of pins, if configured as input. Params: pointer to ** predefined table where data will be written */ GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; volatile uint32_t _PTR_ rgpio_pdir_ptr; uint_32 pin; volatile uint32_t _PTR_ rgpio_ptr_arr[] = { &GPIOA_PDIR, &GPIOB_PDIR, &GPIOC_PDIR, &GPIOD_PDIR, &GPIOE_PDIR }; if (dev_data_ptr->type != DEV_INPUT) return IO_ERROR; if (param_ptr == NULL) /* no list defined */ return IO_ERROR; _int_disable(); /* check if there is not pin in the list which this file does not contain */ for (pin_table = (GPIO_PIN_STRUCT _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { /* check pin validity bit */ if (*pin_table & GPIO_PIN_VALID) { /* prepare address of port */ addr = GPIO_GET_PORT(*pin_table); rgpio_pdir_ptr = rgpio_ptr_arr[ addr ]; /* prepare bit mask */ pin = GPIO_GET_BIT_MASK( *pin_table ); /* pin address out of map scope? */ if (addr < sizeof(GPIO_PIN_MAP) * 8 / (GPIO_PIN_BIT_MASK + 1)) { /* pin address already used? */ if (dev_data_ptr->pin_map.memory32[addr] & pin) { /* GPIO port */ /* check pin status */ if ( *rgpio_pdir_ptr & pin) { /* set pin status to 1 in the list */ *pin_table |= GPIO_PIN_STATUS; } else { /* clear pin status to 0 in the list */ *pin_table &= ~GPIO_PIN_STATUS; } continue; /* manage next pin */ } } } /* some problem occured */ _int_enable(); return IO_ERROR; } _int_enable(); } break; case GPIO_IOCTL_ENABLE_IRQ: { uint_32 port_pointer, pin_idx; /* set "interrupt enabled" for the whole file */ for( port_pointer = 0; port_pointer < PORT_END; port_pointer++) { /* This variable is for quick access to determine if we should perform any change ** to IRQC register field. ** We can set IRQC for every pin of port also, but it will be time consuming */ uint_32 port_imask = dev_data_ptr->irqp_map.memory32[ port_pointer ] | \ dev_data_ptr->irqn_map.memory32[ port_pointer ] | \ dev_data_ptr->irql_map.memory32[ port_pointer ]; for( pin_idx = 0; pin_idx < PIN_IDX_NUM; pin_idx ++) { if (port_imask & 0x00000001) { /* clear PCRx.IRQC field */ *(pctl_ptr_arr[port_pointer] + pin_idx) &= ~PORT_PCR_IRQC(0x0F); *(pctl_ptr_arr[port_pointer] + pin_idx) |= PORT_PCR_IRQC( get_irq_mask( dev_data_ptr->irqn_map.memory32[ port_pointer ] & ( 1 << pin_idx), dev_data_ptr->irqp_map.memory32[ port_pointer ] & ( 1 << pin_idx), dev_data_ptr->irql_map.memory32[ port_pointer ] & ( 1 << pin_idx))); } port_imask >>= 1; } } } break; case GPIO_IOCTL_DISABLE_IRQ: { uint_32 port_pointer, pin_idx; /* set "interrupt disabled" for whole file */ for( port_pointer = 0; port_pointer < PORT_END; port_pointer++) { /* This variable is for quick access to determine if we should perform any change ** to IRQC register field. ** We can set IRQC for every pin of port also, but it will be time consuming */ uint_32 port_imask = dev_data_ptr->irqp_map.memory32[ port_pointer ] | \ dev_data_ptr->irqn_map.memory32[ port_pointer ] | \ dev_data_ptr->irql_map.memory32[ port_pointer ]; for( pin_idx = 0; pin_idx < PIN_IDX_NUM; pin_idx ++) { if (port_imask & 0x00000001) { /* set PCRx to default state */ *(pctl_ptr_arr[port_pointer] + pin_idx) &= ~PORT_PCR_IRQC(0x0F); } port_imask >>= 1; } } } break; case GPIO_IOCTL_SET_IRQ_FUNCTION: { if (dev_data_ptr->type == DEV_OUTPUT) return IO_ERROR; /* cannot set IRQ for output devices */ dev_data_ptr->irq_func = (IRQ_FUNC)param_ptr; _int_disable(); if (param_ptr == NULL) { /* remove function from list */ if (first_irq != NULL) { GPIO_DEV_DATA_PTR gptr = first_irq; while (gptr->NEXT != NULL) { if (gptr == dev_data_ptr) break; if (gptr->NEXT == dev_data_ptr) break; gptr = gptr->NEXT; } if (gptr == dev_data_ptr) /* found as first in the list */ first_irq = first_irq->NEXT; else if (gptr->NEXT == dev_data_ptr) /* found in the middle or at the end of list */ gptr->NEXT = gptr->NEXT->NEXT; } } else { /* add new function to the list */ if (first_irq == NULL) { first_irq = dev_data_ptr; } else { GPIO_DEV_DATA_PTR gptr = first_irq; while (gptr->NEXT != NULL) { if (gptr == dev_data_ptr) break; gptr = gptr->NEXT; } if (gptr != dev_data_ptr) gptr->NEXT = dev_data_ptr; } } _int_enable(); } break; default: return IO_ERROR_INVALID_IOCTL_CMD; } return IO_OK; } /* Endbody */
void gpio_cpu_configure ( /* [IN] pointer to file data */ GPIO_DEV_DATA_PTR dev_data_ptr ) { /* Body */ _mqx_int port_pointer, pin_idx; /* set GPIO output behavior */ if (dev_data_ptr->type == DEV_OUTPUT) { GPIOA_PDDR |= dev_data_ptr->pin_map.reg.porta; GPIOB_PDDR |= dev_data_ptr->pin_map.reg.portb; GPIOC_PDDR |= dev_data_ptr->pin_map.reg.portc; GPIOD_PDDR |= dev_data_ptr->pin_map.reg.portd; GPIOE_PDDR |= dev_data_ptr->pin_map.reg.porte; } else { /* DEV_INPUT type is supposed */ GPIOA_PDDR &= ~dev_data_ptr->pin_map.reg.porta; GPIOB_PDDR &= ~dev_data_ptr->pin_map.reg.portb; GPIOC_PDDR &= ~dev_data_ptr->pin_map.reg.portc; GPIOD_PDDR &= ~dev_data_ptr->pin_map.reg.portd; GPIOE_PDDR &= ~dev_data_ptr->pin_map.reg.porte; } /* set pin functionality to be GPIO for the whole file */ for( port_pointer = 0; port_pointer < PORT_END; port_pointer++) { /* This variable is for quick access to determine if we should perform any change ** interrupt configuration for port. */ uint_32 port_imask = dev_data_ptr->irqp_map.memory32[ port_pointer ] | \ dev_data_ptr->irqn_map.memory32[ port_pointer ] | \ dev_data_ptr->irql_map.memory32[ port_pointer ]; for( pin_idx = 0; pin_idx < PIN_IDX_NUM; pin_idx ++) { /* set pin mux as gpio */ if( dev_data_ptr->pin_map.memory32[ port_pointer ] & ( 1 << pin_idx ) ) { /* set PCRx to default state */ *(pctl_ptr_arr[port_pointer] + pin_idx) = PORT_PCR_MUX(MUX_GPIO) | PORT_PCR_IRQC( get_irq_mask( dev_data_ptr->irqn_map.memory32[ port_pointer ] & ( 1 << pin_idx), dev_data_ptr->irqp_map.memory32[ port_pointer ] & ( 1 << pin_idx), dev_data_ptr->irql_map.memory32[ port_pointer ] & ( 1 << pin_idx))); /* enable internal pull-up resistor for output pin */ if(dev_data_ptr->type == DEV_INPUT) { *(pctl_ptr_arr[port_pointer] + pin_idx) |= (PORT_PCR_PE_MASK|PORT_PCR_PS_MASK); } } } if (port_imask) { /* Enable and configure interrupts on NVIC */ _bsp_int_init(INT_PORTA + port_pointer, _port_int_prio[port_pointer], 0, TRUE); } } } /* Endbody */