/*FUNCTION**************************************************************** * * Function Name : _io_spi_read * Returned Value : Number of bytes read * Comments : * POSIX wrapper to perform SPI transfer storing received data into the buffer. * Returns number of bytes received. * *END*********************************************************************/ static _mqx_int _io_spi_read ( /* [IN] The handle returned from _fopen */ MQX_FILE_PTR fd_ptr, /* [OUT] Where the characters are to be stored */ char *data_ptr, /* [IN] The number of bytes to read */ _mqx_int n ) { #if 0 //SPI_DEV_DATA_STRUCT_PTR dev_data; SPI_DRIVER_DATA_STRUCT_PTR driver_data; _mqx_int num = n; //dev_data = (SPI_DEV_DATA_STRUCT_PTR)(fd_ptr->DEV_DATA_PTR); char tmp; driver_data = (SPI_DRIVER_DATA_STRUCT_PTR)(fd_ptr->DEV_PTR->DRIVER_INIT_PTR); _lwsem_wait(&driver_data->IRQ_SEM); /*add callback function here before real read*/ SPI_CS_CALLBACK_STRUCT callback; callback.CALLBACK = read_cs_callback; callback.USERDATA = fd_ptr; _io_spi_ioctl(fd_ptr, IO_IOCTL_SPI_SET_CS_CALLBACK, &callback); while(lwgpio_get_value(&driver_data->SPI_IRQ_PIN) && num) { if(IO_ERROR !=_io_spi_read_write(fd_ptr, NULL, &tmp, 1)) { *data_ptr++ = tmp; num--; } else return IO_ERROR; } //return _io_spi_read_write(fd_ptr, NULL, data_ptr, n); _io_spi_flush(fd_ptr, 0); return (n-num); #endif return _io_spi_read_write(fd_ptr, NULL, data_ptr, n); }
/*FUNCTION**************************************************************** * * Function Name : _io_spi_write * Returned Value : Number of bytes to write * Comments : * POSIX wrapper to perform SPI transfer sending data from the buffer. * Returns number of bytes received. * *END**********************************************************************/ static _mqx_int _io_spi_write ( /* [IN] The handle returned from _fopen */ MQX_FILE_PTR fd_ptr, /* [IN] Where the bytes are stored */ char *data_ptr, /* [IN] The number of bytes to output */ _mqx_int n ) { #if 0 //return _io_spi_read_write(fd_ptr, data_ptr, NULL, n); if(IO_ERROR == _io_spi_read_write(fd_ptr, data_ptr, NULL, n)) return IO_ERROR; _io_spi_flush(fd_ptr, 0); return MQX_OK; #endif return _io_spi_read_write(fd_ptr, data_ptr, NULL, n); }
/*FUNCTION**************************************************************** * * Function Name : _io_spi_write * Returned Value : Number of bytes to write * Comments : * POSIX wrapper to perform SPI transfer sending data from the buffer. * Returns number of bytes received. * *END**********************************************************************/ static _mqx_int _io_spi_write ( /* [IN] The handle returned from _fopen */ MQX_FILE_PTR fd_ptr, /* [IN] Where the bytes are stored */ char *data_ptr, /* [IN] The number of bytes to output */ _mqx_int n ) { return _io_spi_read_write(fd_ptr, data_ptr, NULL, n); }
/*FUNCTION**************************************************************** * * Function Name : _io_spi_read * Returned Value : Number of bytes read * Comments : * POSIX wrapper to perform SPI transfer storing received data into the buffer. * Returns number of bytes received. * *END*********************************************************************/ static _mqx_int _io_spi_read ( /* [IN] The handle returned from _fopen */ MQX_FILE_PTR fd_ptr, /* [OUT] Where the characters are to be stored */ char *data_ptr, /* [IN] The number of bytes to read */ _mqx_int n ) { return _io_spi_read_write(fd_ptr, NULL, data_ptr, n); }
/*FUNCTION***************************************************************** * * Function Name : _io_spi_ioctl * Returned Value : MQX error code * Comments : * Returns result of SPI ioctl operation. * *END*********************************************************************/ static _mqx_int _io_spi_ioctl ( /* [IN] the file handle for the device */ MQX_FILE_PTR fd_ptr, /* [IN] the ioctl command */ uint32_t cmd, /* [IN] the ioctl parameters */ void *param_ptr ) { SPI_DEV_DATA_STRUCT_PTR dev_data; SPI_DRIVER_DATA_STRUCT_PTR driver_data; _mqx_int result = MQX_OK; _mqx_int lldrv_result = MQX_OK; dev_data = (SPI_DEV_DATA_STRUCT_PTR)(fd_ptr->DEV_DATA_PTR); driver_data = (SPI_DRIVER_DATA_STRUCT_PTR)(fd_ptr->DEV_PTR->DRIVER_INIT_PTR); switch (cmd) { case IO_IOCTL_DEVICE_IDENTIFY: /* return the device identification */ ((_mqx_uint_ptr)param_ptr)[0] = IO_DEV_TYPE_PHYS_SPI; ((_mqx_uint_ptr)param_ptr)[1] = 0; ((_mqx_uint_ptr)param_ptr)[2] = IO_DEV_ATTR_READ | IO_DEV_ATTR_WRITE; break; case IO_IOCTL_FLUSH_OUTPUT: result = _io_spi_flush(fd_ptr, ((dev_data->FLAGS & SPI_FLAG_NO_DEASSERT_ON_FLUSH)!=0)); break; case IO_IOCTL_SPI_FLUSH_DEASSERT_CS: result = _io_spi_flush(fd_ptr, 0); break; case IO_IOCTL_SPI_READ_WRITE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { SPI_READ_WRITE_STRUCT_PTR rw_ptr = (SPI_READ_WRITE_STRUCT_PTR)param_ptr; if (rw_ptr->BUFFER_LENGTH != _io_spi_read_write(fd_ptr, rw_ptr->WRITE_BUFFER, rw_ptr->READ_BUFFER, rw_ptr->BUFFER_LENGTH)) result = IO_ERROR; } break; case IO_IOCTL_SPI_GET_FLAGS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->FLAGS; } break; case IO_IOCTL_SPI_SET_FLAGS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { dev_data->FLAGS = *((uint32_t *)param_ptr); } break; case IO_IOCTL_SPI_GET_BAUD: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->PARAMS.BAUDRATE; /* Pass IOCTL also to the low level driver */ if (driver_data->DEVIF->IOCTL != NULL) result = driver_data->DEVIF->IOCTL(driver_data->DEVIF_DATA, &(dev_data->PARAMS), cmd, param_ptr); /* Invalid IOCTL reported by the low level driver is not an error (implementation is not mandatory) */ if (result == IO_ERROR_INVALID_IOCTL_CMD) result = MQX_OK; } break; case IO_IOCTL_SPI_SET_BAUD: if (NULL == param_ptr || 0 == *((uint32_t *)param_ptr)) { /* use default baudrate */ dev_data->PARAMS.BAUDRATE = driver_data->PARAMS.BAUDRATE; dev_data->PARAMS_DIRTY = TRUE; } else { dev_data->PARAMS.BAUDRATE = *((uint32_t *)param_ptr); dev_data->PARAMS_DIRTY = TRUE; } break; case IO_IOCTL_SPI_GET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->PARAMS.MODE; } break; case IO_IOCTL_SPI_SET_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { dev_data->PARAMS.MODE = *((uint32_t *)param_ptr); dev_data->PARAMS_DIRTY = TRUE; } break; case IO_IOCTL_SPI_GET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->PARAMS.CS; } break; case IO_IOCTL_SPI_SET_CS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { dev_data->PARAMS.CS = *((uint32_t *)param_ptr); dev_data->PARAMS_DIRTY = TRUE; } break; case IO_IOCTL_SPI_GET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->PARAMS.FRAMESIZE; } break; case IO_IOCTL_SPI_SET_FRAMESIZE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { dev_data->PARAMS.FRAMESIZE = *((uint32_t *)param_ptr); dev_data->PARAMS_DIRTY = TRUE; } break; case IO_IOCTL_SPI_GET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if ((dev_data->PARAMS.ATTR & SPI_ATTR_TRANSFER_MODE_MASK) == SPI_ATTR_SLAVE_MODE) { *((uint32_t *)param_ptr) = SPI_DEVICE_SLAVE_MODE; } else { *((uint32_t *)param_ptr) = SPI_DEVICE_MASTER_MODE; } break; case IO_IOCTL_SPI_SET_TRANSFER_MODE: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (*((uint32_t *)param_ptr) == SPI_DEVICE_SLAVE_MODE) { dev_data->PARAMS.ATTR &= ~SPI_ATTR_TRANSFER_MODE_MASK; dev_data->PARAMS.ATTR |= SPI_ATTR_SLAVE_MODE; dev_data->PARAMS_DIRTY = TRUE; } else if (*((uint32_t *)param_ptr) == SPI_DEVICE_MASTER_MODE) { dev_data->PARAMS.ATTR &= ~SPI_ATTR_TRANSFER_MODE_MASK; dev_data->PARAMS.ATTR |= SPI_ATTR_MASTER_MODE; dev_data->PARAMS_DIRTY = TRUE; } else { result = SPI_ERROR_TRANSFER_MODE_INVALID; } break; case IO_IOCTL_SPI_GET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if ((dev_data->PARAMS.ATTR & SPI_ATTR_ENDIAN_MASK) == SPI_ATTR_LITTLE_ENDIAN) { *((uint32_t *)param_ptr) = SPI_DEVICE_LITTLE_ENDIAN; } else { *((uint32_t *)param_ptr) = SPI_DEVICE_BIG_ENDIAN; } break; case IO_IOCTL_SPI_SET_ENDIAN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else if (*((uint32_t *)param_ptr) == SPI_DEVICE_LITTLE_ENDIAN) { dev_data->PARAMS.ATTR &= ~SPI_ATTR_ENDIAN_MASK; dev_data->PARAMS.ATTR |= SPI_ATTR_LITTLE_ENDIAN; dev_data->PARAMS_DIRTY = TRUE; } else if (*((uint32_t *)param_ptr) == SPI_DEVICE_BIG_ENDIAN) { dev_data->PARAMS.ATTR &= ~SPI_ATTR_ENDIAN_MASK; dev_data->PARAMS.ATTR |= SPI_ATTR_BIG_ENDIAN; dev_data->PARAMS_DIRTY = TRUE; } else { result = SPI_ERROR_ENDIAN_INVALID; } break; case IO_IOCTL_SPI_GET_DUMMY_PATTERN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { *((uint32_t *)param_ptr) = dev_data->PARAMS.DUMMY_PATTERN; } break; case IO_IOCTL_SPI_SET_DUMMY_PATTERN: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { dev_data->PARAMS.DUMMY_PATTERN = *((uint32_t *)param_ptr); dev_data->PARAMS_DIRTY = TRUE; } break; case IO_IOCTL_SPI_SET_CS_CALLBACK: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { if (!(dev_data->BUS_OWNER) && ((result=_lwsem_wait(&(driver_data->BUS_LOCK))) != MQX_OK)) break; driver_data->CS_CALLBACK = ((SPI_CS_CALLBACK_STRUCT_PTR)param_ptr)->CALLBACK; driver_data->CS_USERDATA = ((SPI_CS_CALLBACK_STRUCT_PTR)param_ptr)->USERDATA; if (!(dev_data->BUS_OWNER)) result = _lwsem_post(&(driver_data->BUS_LOCK)); } break; case IO_IOCTL_SPI_GET_STATS: if (NULL == param_ptr) { result = SPI_ERROR_INVALID_PARAMETER; } else { #if BSPCFG_ENABLE_SPI_STATS *((SPI_STATISTICS_STRUCT_PTR)param_ptr) = dev_data->STATS; #else _mem_zero(param_ptr, sizeof(SPI_STATISTICS_STRUCT)); result = MQX_IO_OPERATION_NOT_AVAILABLE; #endif } break; case IO_IOCTL_SPI_CLEAR_STATS: #if BSPCFG_ENABLE_SPI_STATS _mem_zero(&(dev_data->STATS), sizeof(dev_data->STATS)); #else result = MQX_IO_OPERATION_NOT_AVAILABLE; #endif break; case IO_IOCTL_SPI_DEVICE_ENABLE: break; case IO_IOCTL_SPI_DEVICE_DISABLE: break; default: /* Pass unhandled IOCTL to the low level driver */ if (driver_data->DEVIF->IOCTL != NULL) { /* Do not assume that the low level driver is re-entrant, lock semaphore */ if (!(dev_data->BUS_OWNER) && ((result=_lwsem_wait(&(driver_data->BUS_LOCK))) != MQX_OK)) break; lldrv_result = driver_data->DEVIF->IOCTL(driver_data->DEVIF_DATA, &(dev_data->PARAMS), cmd, param_ptr); if (!(dev_data->BUS_OWNER)) result = _lwsem_post(&(driver_data->BUS_LOCK)); /* Report low level driver error, if any */ if (lldrv_result != MQX_OK) result = lldrv_result; } else { result = IO_ERROR_INVALID_IOCTL_CMD; } break; } return result; }