_mqx_int gpio_cpu_open ( /* [IN] the file handle for the device */ MQX_FILE_PTR fd_ptr, /* [IN] the file name */ char_ptr file_name, /* [IN] pointer to parameters */ char_ptr param_ptr ) { /* Body */ GPIO_DEV_DATA_PTR dev_data_ptr = (GPIO_DEV_DATA_PTR) fd_ptr->DEV_DATA_PTR; /* if file_name is used, then the user wants to open peripheral */ if ((file_name != NULL) && (*file_name != 0)) { if (!strncmp(file_name, "gpio:write", 11)) /* user wants write access to GPIO */ dev_data_ptr->type = DEV_OUTPUT; else if (!strncmp(file_name, "gpio:output", 12)) /* user wants write access to GPIO */ dev_data_ptr->type = DEV_OUTPUT; else if (!strncmp(file_name, "gpio:read", 10)) /* user wants read access to GPIO */ dev_data_ptr->type = DEV_INPUT; else if (!strncmp(file_name, "gpio:input", 11)) /* user wants read access to GPIO */ dev_data_ptr->type = DEV_INPUT; else /* peripherals not used yet */ return IO_ERROR; } else return IO_ERROR; /* install interrupt service routine */ if( IO_OK != install_isr( fd_ptr ) ) { return IO_ERROR; } /* set pins status before selecting GPIO function */ if ((param_ptr != NULL) && (dev_data_ptr->type == DEV_OUTPUT)) { /* note that this is similar to GPIO_IOCTL_WRITE function, but no checking ** is performed (was done in io_gpio_open function) */ GPIO_PIN_STRUCT _PTR_ pin_table; uint_32 addr; uint_8 pin; GPIO_PIN_MAP temp_pin0_map = {0}; GPIO_PIN_MAP temp_pin1_map = {0}; /* prepare 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 ); if (*pin_table & GPIO_PIN_STATUS) temp_pin1_map.memory32[addr] |= pin; else temp_pin0_map.memory32[addr] |= pin; } /* 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]; } gpio_cpu_configure(dev_data_ptr); return IO_OK; } /* Endbody */
_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 */
_mqx_int gpio_cpu_open ( /* [IN] the file handle for the device */ MQX_FILE_PTR fd_ptr, /* [IN] the file name */ char_ptr file_name, /* [IN] pointer to parameters */ char_ptr param_ptr ) { /* Body */ _mqx_int i; GPIO_DEV_DATA_PTR dev_data_ptr = (GPIO_DEV_DATA_PTR) fd_ptr->DEV_DATA_PTR; /* if file_name is used, then the user wants to open peripheral */ if ((file_name != NULL) && (*file_name != 0)) { if (!strncmp(file_name, "gpio:write", 11)) /* user wants write access to GPIO */ dev_data_ptr->type = DEV_OUTPUT; else if (!strncmp(file_name, "gpio:output", 12)) /* user wants write access to GPIO */ dev_data_ptr->type = DEV_OUTPUT; else if (!strncmp(file_name, "gpio:read", 10)) /* user wants read access to GPIO */ dev_data_ptr->type = DEV_INPUT; else if (!strncmp(file_name, "gpio:input", 11)) /* user wants read access to GPIO */ dev_data_ptr->type = DEV_INPUT; else /* peripherals not used yet */ return IO_ERROR; } else return IO_ERROR; if ((param_ptr != NULL) && (dev_data_ptr->type == DEV_OUTPUT)) { /* set pins status before selecting GPIO function */ /* note that this is similar to GPIO_IOCTL_WRITE function, but no checking is performed (was done in io_gpio_open function) */ uint_32 _PTR_ pin_table; uint_32 addr; uint_8 pin; GPIO_PIN_MAP_PTR temp_pin0_map_ptr; GPIO_PIN_MAP_PTR temp_pin1_map_ptr; if (NULL == (temp_pin0_map_ptr = (GPIO_PIN_MAP_PTR) _mem_alloc_system_zero(sizeof(GPIO_PIN_MAP)))) return IO_ERROR; if (NULL == (temp_pin1_map_ptr = (GPIO_PIN_MAP_PTR) _mem_alloc_system_zero(sizeof(GPIO_PIN_MAP)))) { _mem_free(temp_pin0_map_ptr); return IO_ERROR; } /* prepare pin map */ for (pin_table = (uint_32 _PTR_) param_ptr; *pin_table != GPIO_LIST_END; pin_table++) { addr = (*pin_table & GPIO_PIN_ADDR) >> 3; /* prepare address of port */ pin = 1 << (*pin_table & 0x07); /* prepare bit mask */ if (*pin_table & GPIO_PIN_STATUS) temp_pin1_map_ptr->memory8[addr] |= pin; else temp_pin0_map_ptr->memory8[addr] |= pin; } /* first, configure pin as output */ gpio_cpu_configure(dev_data_ptr); /* ok, now we can apply new map */ /* note: applying the map after collecting pins is due to have pins applied in one instruction */ for (i = GPIO_PORT_A; i < GPIO_PORT_MAX; i++) mcf521cn_gpioX_ptr->PORT[i].PTxD = (mcf521cn_gpioX_ptr->PORT[i].PTxD | temp_pin1_map_ptr->reg.portt[i]) & ~temp_pin0_map_ptr->reg.portt[i]; _mem_free(temp_pin1_map_ptr); _mem_free(temp_pin0_map_ptr); }