/* * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ #include "FreeRTOS.h" #include "task.h" #include "spi.h" #include "iot_spi.h" #include "board-config.h" static IotSPIHandle_t SpiHandle[2]; void SpiInit( Spi_t *obj, SpiId_t spiId, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss ) { taskENTER_CRITICAL(); obj->SpiId = spiId; SpiHandle[ spiId ] = iot_spi_open( spiId ); configASSERT( SpiHandle[ spiId ] != NULL ) if( nss == NC ) { SpiFormat( obj, 8, 0, 0, 0 ); } else { SpiFormat( obj, 8, 0, 0, 1 ); } SpiFrequency( obj, LORA_MAC_SPI_FREQUENCY ); taskEXIT_CRITICAL(); } void SpiDeInit( Spi_t *obj ) { taskENTER_CRITICAL(); iot_spi_close( SpiHandle[obj->SpiId] ); SpiHandle[obj->SpiId] = NULL; taskEXIT_CRITICAL(); } void SpiFormat( Spi_t *obj, int8_t bits, int8_t cpol, int8_t cpha, int8_t slave ) { IotSPIMasterConfig_t spiConfig; int32_t ret; /** * No support in common IO to configure these parameters. */ ( void ) bits; ( void ) slave; ret = iot_spi_ioctl( SpiHandle[obj->SpiId], eSPIGetMasterConfig, &spiConfig ); if( ret == IOT_SPI_SUCCESS ) { if( ( cpol == 0 ) && ( cpha == 0 ) ) { spiConfig.eMode = eSPIMode0; } else if( ( cpol == 0 ) && ( cpha == 1 ) ) { spiConfig.eMode = eSPIMode1; } else if( ( cpol == 1 ) && ( cpha == 0 ) ) { spiConfig.eMode = eSPIMode2; } else { spiConfig.eMode = eSPIMode3; } spiConfig.eSetBitOrder = eSPIMSBFirst; ret = iot_spi_ioctl( SpiHandle[obj->SpiId], eSPISetMasterConfig, &spiConfig ); configASSERT( IOT_SPI_SUCCESS == ret ); } } void SpiFrequency( Spi_t *obj, uint32_t hz ) { IotSPIMasterConfig_t spiConfig; int32_t ret; ret = iot_spi_ioctl( SpiHandle[obj->SpiId], eSPIGetMasterConfig, &spiConfig ); if( ret == IOT_SPI_SUCCESS ) { spiConfig.ulFreq = hz; ret = iot_spi_ioctl( SpiHandle[obj->SpiId], eSPISetMasterConfig, &spiConfig ); configASSERT( IOT_SPI_SUCCESS == ret ); } } /* * Some boards require interrutps to be enabled to sync spi transaction to finish * #define _PROTECT_BOARD_SPI_TRANSACTIONS */ uint16_t SpiInOut( Spi_t *obj, uint16_t outData ) { uint8_t rxData = 0; BaseType_t interruptStatus = 0; int32_t ret; configASSERT( ( obj != NULL ) && ( SpiHandle[obj->SpiId ] != NULL ) ); /** * TODO: Remove mutual exclusion code and handle it in caller if needed. */ #ifdef _PROTECT_BOARD_SPI_TRANSACTIONS if( xPortIsInsideInterrupt() == pdTRUE ) { interruptStatus = taskENTER_CRITICAL_FROM_ISR(); } else { taskENTER_CRITICAL( ); } #endif do { ret = iot_spi_transfer_sync( SpiHandle[ obj->SpiId ], ( uint8_t * ) &outData, &rxData, 1 ); } while( ret == IOT_SPI_BUS_BUSY ); configASSERT( IOT_SPI_SUCCESS == ret ); #ifdef _PROTECT_BOARD_SPI_TRANSACTIONS if( xPortIsInsideInterrupt() == pdTRUE ) { taskEXIT_CRITICAL_FROM_ISR( interruptStatus ); } else { taskEXIT_CRITICAL( ); } #endif return( rxData ); }