449 lines
9.7 KiB
C
449 lines
9.7 KiB
C
|
|
|
||
|
|
#include "SPIDevice.h"
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
static SPI_BUS_t *spi_bus_head = NULL;
|
||
|
|
|
||
|
|
void RegSpiBusIRQ(SPI_BUS_t *bus)
|
||
|
|
{
|
||
|
|
if (spi_bus_head)
|
||
|
|
{
|
||
|
|
if (spi_bus_head != bus)
|
||
|
|
{
|
||
|
|
SPI_BUS_t *head = spi_bus_head;
|
||
|
|
while (head->next_ptr && head->next_ptr != bus)//一个一个往下走,直到最后一个
|
||
|
|
{
|
||
|
|
head = head->next_ptr;
|
||
|
|
}
|
||
|
|
if (head->next_ptr != bus)
|
||
|
|
{
|
||
|
|
head->next_ptr = bus;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_bus_head = bus;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int SPI_DEV_open(SPI_DEV_t *spi_dev, char *name,
|
||
|
|
SPI_BUS_t *bus, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
|
||
|
|
{
|
||
|
|
spi_dev->name = name;
|
||
|
|
spi_dev->bus = bus;
|
||
|
|
spi_dev->GPIOx = GPIOx;
|
||
|
|
spi_dev->GPIO_Pin = GPIO_Pin;
|
||
|
|
spi_dev->_read_flag = 0x00;
|
||
|
|
|
||
|
|
HAL_GPIO_WritePin(GPIOx, GPIO_Pin, GPIO_PIN_SET);
|
||
|
|
|
||
|
|
RegSpiBusIRQ(bus);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void SPI_DEV_end(SPI_DEV_t *spi_dev)
|
||
|
|
{
|
||
|
|
osMutexRelease(spi_dev->bus->mutex);
|
||
|
|
}
|
||
|
|
|
||
|
|
void SPI_DEV_unselect(SPI_DEV_t *spi_dev)
|
||
|
|
{
|
||
|
|
HAL_GPIO_WritePin(spi_dev->GPIOx,spi_dev->GPIO_Pin, GPIO_PIN_SET);
|
||
|
|
}
|
||
|
|
|
||
|
|
void SPI_DEV_select(SPI_DEV_t *spi_dev)
|
||
|
|
{
|
||
|
|
HAL_GPIO_WritePin(spi_dev->GPIOx,spi_dev->GPIO_Pin, GPIO_PIN_RESET);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
bool SPI_DEV_begin(SPI_DEV_t *spi_dev, uint32_t millisec)
|
||
|
|
{
|
||
|
|
if (!osMutexWait(spi_dev->bus->mutex, millisec))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
void SPI_DEV_set_read_flag(SPI_DEV_t *spi_dev, uint8_t flag)
|
||
|
|
{
|
||
|
|
spi_dev->_read_flag = flag;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool SPI_DEV_read_registers(SPI_DEV_t *spi_dev, uint8_t id, uint8_t *buff_out, size_t len_out)
|
||
|
|
{
|
||
|
|
id |= spi_dev->_read_flag;
|
||
|
|
if (!HAL_SPI_Transmit(spi_dev->bus->hspi,&id,1,1))
|
||
|
|
{
|
||
|
|
if (len_out > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_DMA(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 10))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_IT(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 10))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_Receive(spi_dev->bus->hspi,buff_out,len_out,10))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool SPI_DEV_write_register(SPI_DEV_t *spi_dev, uint8_t id, uint8_t val)
|
||
|
|
{
|
||
|
|
uint8_t buf[2];
|
||
|
|
buf[0] = id;
|
||
|
|
buf[1] = val;
|
||
|
|
if (!HAL_SPI_Transmit(spi_dev->bus->hspi,buf,2,1))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool SPI_DEV_transfer(SPI_DEV_t *spi_dev, uint8_t *buff_in, size_t len_in, uint8_t *buff_out, size_t len_out, uint32_t millisec)
|
||
|
|
{
|
||
|
|
bool rslt = false;
|
||
|
|
|
||
|
|
if (buff_in && buff_out)
|
||
|
|
{
|
||
|
|
if (len_in == len_out)
|
||
|
|
{
|
||
|
|
if (len_in > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_TransmitReceive_DMA(spi_dev->bus->hspi,buff_in, buff_out,len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, millisec))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_TransmitReceive_IT(spi_dev->bus->hspi,buff_in, buff_out, len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, millisec))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_TransmitReceive(spi_dev->bus->hspi,buff_in, buff_out, len_in, 100))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (len_in > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Transmit_DMA(spi_dev->bus->hspi,buff_in,len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Transmit_IT(spi_dev->bus->hspi,buff_in,len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_Transmit(spi_dev->bus->hspi,buff_in,len_in,100))
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
if (rslt)
|
||
|
|
{
|
||
|
|
rslt = false;
|
||
|
|
if (len_out > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_DMA(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_IT(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_Receive(spi_dev->bus->hspi,buff_out,len_out,10))
|
||
|
|
{
|
||
|
|
rslt = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (buff_in)
|
||
|
|
{
|
||
|
|
if (len_in > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Transmit_DMA(spi_dev->bus->hspi,buff_in,len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Transmit_IT(spi_dev->bus->hspi,buff_in,len_in))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_Transmit(spi_dev->bus->hspi,buff_in,len_in,100))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else if (buff_out)
|
||
|
|
{
|
||
|
|
if (len_out > 16 && spi_dev->bus->mode != SPI_BUS_BLOCK)
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = xTaskGetCurrentTaskHandle();
|
||
|
|
spi_dev->bus->task_waitfor_ret = false;
|
||
|
|
if (spi_dev->bus->mode == SPI_BUS_DMA)
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_DMA(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_DMAStop(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if (!HAL_SPI_Receive_IT(spi_dev->bus->hspi,buff_out,len_out))
|
||
|
|
{
|
||
|
|
if (ulTaskNotifyTake( pdTRUE, 100))
|
||
|
|
{
|
||
|
|
if (spi_dev->bus->task_waitfor_ret)
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
spi_dev->bus->task_waitfor_cmpl = NULL;
|
||
|
|
HAL_SPI_Abort(spi_dev->bus->hspi);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
if (!HAL_SPI_Receive(spi_dev->bus->hspi,buff_out,len_out,10))
|
||
|
|
{
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return rslt;
|
||
|
|
}
|
||
|
|
|
||
|
|
void SPI_DEV_CpltCallback(SPI_HandleTypeDef *hspi, bool ret)
|
||
|
|
{
|
||
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||
|
|
|
||
|
|
SPI_BUS_t *bus = spi_bus_head;
|
||
|
|
while (bus)
|
||
|
|
{
|
||
|
|
if (bus->hspi == hspi && bus->task_waitfor_cmpl)
|
||
|
|
{
|
||
|
|
vTaskNotifyGiveFromISR( bus->task_waitfor_cmpl, &xHigherPriorityTaskWoken );
|
||
|
|
bus->task_waitfor_cmpl = NULL;
|
||
|
|
bus->task_waitfor_ret = ret;
|
||
|
|
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
bus = bus->next_ptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
|
||
|
|
{
|
||
|
|
SPI_DEV_CpltCallback(hspi, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
|
||
|
|
{
|
||
|
|
SPI_DEV_CpltCallback(hspi, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
|
||
|
|
{
|
||
|
|
SPI_DEV_CpltCallback(hspi, true);
|
||
|
|
}
|
||
|
|
|
||
|
|
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
|
||
|
|
{
|
||
|
|
SPI_DEV_CpltCallback(hspi, false);
|
||
|
|
}
|
||
|
|
|
||
|
|
void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
|
||
|
|
{
|
||
|
|
SPI_DEV_CpltCallback(hspi, false);
|
||
|
|
}
|
||
|
|
|
||
|
|
|