Files
motor/Common/spi/SPIDevice.c
T
2024-09-26 22:32:20 +08:00

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);
}