platform_result_t platform_spi_transfer( const platform_spi_t* spi, const platform_spi_config_t* config, const platform_spi_message_segment_t* segments, uint16_t number_of_segments ) { platform_result_t result = PLATFORM_SUCCESS; uint32_t count = 0; uint16_t i; wiced_assert( "bad argument", ( spi != NULL ) && ( config != NULL ) && ( segments != NULL ) && ( number_of_segments != 0 ) ); platform_mcu_powersave_disable(); /* Activate chip select */ platform_gpio_output_low( config->chip_select ); for ( i = 0; i < number_of_segments; i++ ) { /* Check if we are using DMA */ if ( config->mode & SPI_USE_DMA ) { spi_dma_config( spi, &segments[ i ] ); result = spi_dma_transfer( spi, config ); if ( result != PLATFORM_SUCCESS ) { goto cleanup_transfer; } } else { count = segments[i].length; /* in interrupt-less mode */ if ( config->bits == 8 ) { const uint8_t* send_ptr = ( const uint8_t* )segments[i].tx_buffer; uint8_t* rcv_ptr = ( uint8_t* )segments[i].rx_buffer; while ( count-- ) { uint16_t data = 0xFF; if ( send_ptr != NULL ) { data = *send_ptr++; } data = spi_transfer( spi, data ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = (uint8_t)data; } } } else if ( config->bits == 16 ) { const uint16_t* send_ptr = (const uint16_t *) segments[i].tx_buffer; uint16_t* rcv_ptr = (uint16_t *) segments[i].rx_buffer; /* Check that the message length is a multiple of 2 */ if ( ( count % 2 ) != 0 ) { result = WICED_ERROR; goto cleanup_transfer; } /* Transmit/receive data stream, 16-bit at time */ while ( count != 0 ) { uint16_t data = 0xFFFF; if ( send_ptr != NULL ) { data = *send_ptr++; } data = spi_transfer( spi, data ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = data; } count -= 2; } } } } cleanup_transfer: /* Deassert chip select */ platform_gpio_output_high( config->chip_select ); platform_mcu_powersave_enable( ); return result; }
OSStatus MicoSpiTransfer( const mico_spi_device_t* spi, mico_spi_message_segment_t* segments, uint16_t number_of_segments ) { OSStatus result = kNoErr; uint16_t i; uint32_t count = 0; check_string( (spi != NULL) && (segments != NULL) && (number_of_segments != 0), "Bad args"); MicoMcuPowerSaveConfig(false); /* If the given SPI device is not the current SPI device, initialise */ if ( spi != current_spi_device ) { MicoSpiInitialize( spi ); } /* Activate chip select */ MicoGpioOutputLow(spi->chip_select); for ( i = 0; i < number_of_segments; i++ ) { /* Check if we are using DMA */ if ( spi->mode & SPI_USE_DMA ) { spi_dma_config( spi, &segments[i] ); result = spi_dma_transfer( spi ); if ( result != kNoErr ) { goto cleanup_transfer; } } else { /* in interrupt-less mode */ if ( spi->bits == 8 ) { const uint8_t* send_ptr = ( const uint8_t* )segments[i].tx_buffer; uint8_t* rcv_ptr = ( uint8_t* )segments[i].rx_buffer; count = segments[i].length; while ( count-- ) { uint16_t data; if ( send_ptr != NULL ) { data = *send_ptr; send_ptr++; } else { data = 0xFF; } /* Wait until the transmit buffer is empty */ while ( SPI_I2S_GetFlagStatus( spi_mapping[spi->port].spi_regs, SPI_I2S_FLAG_TXE ) == RESET ) {} /* Send the byte */ SPI_I2S_SendData( spi_mapping[spi->port].spi_regs, data ); /* Wait until a data is received */ while ( SPI_I2S_GetFlagStatus( spi_mapping[spi->port].spi_regs, SPI_I2S_FLAG_RXNE ) == RESET ) {} /* Get the received data */ data = SPI_I2S_ReceiveData( spi_mapping[spi->port].spi_regs ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = (uint8_t)data; } } } else if ( spi->bits == 16 ) { const uint16_t* send_ptr = (const uint16_t *) segments[i].tx_buffer; uint16_t* rcv_ptr = (uint16_t *) segments[i].rx_buffer; /* Check that the message length is a multiple of 2 */ if ( ( count % 2 ) == 0 ) { result = kGeneralErr; goto cleanup_transfer; } while ( count != 0) { uint16_t data = 0xFFFF; count -= 2; if ( send_ptr != NULL ) { data = *send_ptr++; } /* Wait until the transmit buffer is empty */ while ( SPI_I2S_GetFlagStatus( spi_mapping[spi->port].spi_regs, SPI_I2S_FLAG_TXE ) == RESET ) {} /* Send the byte */ SPI_I2S_SendData( spi_mapping[spi->port].spi_regs, data ); /* Wait until a data is received */ while ( SPI_I2S_GetFlagStatus( spi_mapping[spi->port].spi_regs, SPI_I2S_FLAG_RXNE ) == RESET ) {} /* Get the received data */ data = SPI_I2S_ReceiveData( spi_mapping[spi->port].spi_regs ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = data; } } } } } cleanup_transfer: MicoGpioOutputHigh(spi->chip_select); MicoMcuPowerSaveConfig(true); return result; }
OSStatus platform_spi_transfer( platform_spi_driver_t* driver, const platform_spi_config_t* config, const platform_spi_message_segment_t* segments, uint16_t number_of_segments ) { OSStatus err = kNoErr; uint32_t count = 0; uint16_t i; platform_mcu_powersave_disable(); require_action_quiet( ( driver != NULL ) && ( config != NULL ) && ( segments != NULL ) && ( number_of_segments != 0 ), exit, err = kParamErr); /* Activate chip select */ platform_gpio_output_low( config->chip_select ); for ( i = 0; i < number_of_segments; i++ ) { /* Check if we are using DMA */ if ( config->mode & SPI_USE_DMA ) { if( segments[ i ].length != 0){ //platform_log( "length: %d, i:%d", segments[ i ].length, i ); spi_dma_config( driver->peripheral, &segments[ i ] ); err = spi_dma_transfer( driver->peripheral, config ); require_noerr(err, cleanup_transfer); } } else { count = segments[i].length; /* in interrupt-less mode */ if ( config->bits == 8 ) { const uint8_t* send_ptr = ( const uint8_t* )segments[i].tx_buffer; uint8_t* rcv_ptr = ( uint8_t* )segments[i].rx_buffer; while ( count-- ) { uint16_t data = 0xFF; if ( send_ptr != NULL ) { data = *send_ptr++; } data = spi_transfer( driver->peripheral, data ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = (uint8_t)data; } } } else if ( config->bits == 16 ) { const uint16_t* send_ptr = (const uint16_t *) segments[i].tx_buffer; uint16_t* rcv_ptr = (uint16_t *) segments[i].rx_buffer; /* Check that the message length is a multiple of 2 */ require_action_quiet( ( count % 2 ) == 0, cleanup_transfer, err = kSizeErr); /* Transmit/receive data stream, 16-bit at time */ while ( count != 0 ) { uint16_t data = 0xFFFF; if ( send_ptr != NULL ) { data = *send_ptr++; } data = spi_transfer( driver->peripheral, data ); if ( rcv_ptr != NULL ) { *rcv_ptr++ = data; } count -= 2; } } } } cleanup_transfer: /* Deassert chip select */ platform_gpio_output_high( config->chip_select ); exit: platform_mcu_powersave_enable( ); return err; }