#include "SPIDevice.h" #include #include 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); }