/** * @brief Main program * @param None * @retval None */ int main(void) { uint16_t addrcmd = 0; uint16_t comlength = 0; uint8_t pAddrcmd[CMD_LENGTH] = {0x00}; uint16_t ackbyte = 0x0000; /* STM32F4xx HAL library initialization: - Configure the Flash prefetch, instruction and Data caches - Configure the Systick to generate an interrupt each 1 msec - Set NVIC Group Priority to 4 - Global MSP (MCU Support Package) initialization */ HAL_Init(); /* Configure the system clock to 168 MHz */ SystemClock_Config(); /* Configure LED5 and LED6 */ BSP_LED_Init(LED5); BSP_LED_Init(LED6); /*##-1- Configure the SPI peripheral #######################################*/ /* Set the SPI parameters */ SpiHandle.Instance = SPIx; SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16; SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; SpiHandle.Init.CRCPolynomial = 7; SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; SpiHandle.Init.NSS = SPI_NSS_SOFT; SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; SpiHandle.Init.Mode = SPI_MODE_SLAVE; if(HAL_SPI_Init(&SpiHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } /* Enter while loop too keep treating new request from Master */ while(1) { /* Synchronization between Master and Slave */ Slave_Synchro(); /* Receive command from Master */ if(HAL_SPI_Receive_IT(&SpiHandle, pAddrcmd, CMD_LENGTH) != HAL_OK) { Error_Handler(); } /* Before starting a new communication transfer, you need to check the current state of the peripheral; if it’s busy you need to wait for the end of current transfer before starting a new one. For simplicity reasons, this example is just waiting till the end of the transfer, but application may perform other tasks while transfer operation is ongoing. */ while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* Compute command and required data length */ addrcmd = (uint16_t) ((pAddrcmd[0] << 8) | pAddrcmd[1]); comlength = (uint16_t) ((pAddrcmd[2] << 8) | pAddrcmd[3]); /* Check if received command correct */ if(((addrcmd == ADDRCMD_MASTER_READ) || (addrcmd == ADDRCMD_MASTER_WRITE)) && (comlength > 0)) { /* Synchronization between Master and Slave */ Slave_Synchro(); /* Send acknowledge to Master */ ackbyte = SPI_ACK_BYTES; if(HAL_SPI_Transmit_IT(&SpiHandle, (uint8_t *)&ackbyte, sizeof(ackbyte)) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* Check if Master requiring data read or write */ if(addrcmd == ADDRCMD_MASTER_READ) { /* Synchronization between Master and Slave */ Slave_Synchro(); /* Send data to Master */ if(HAL_SPI_Transmit_IT(&SpiHandle, aTxSlaveBuffer, DATA_LENGTH) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* Synchronization between Master and Slave */ Slave_Synchro(); /* Receive acknowledgement from Master */ ackbyte = 0; if(HAL_SPI_Receive_IT(&SpiHandle, (uint8_t *)&ackbyte, sizeof(ackbyte)) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* Check acknowledgement */ if(ackbyte != SPI_ACK_BYTES) { Error_Handler(); } } else if(addrcmd == ADDRCMD_MASTER_WRITE) { /* Synchronization between Master and Slave */ Slave_Synchro(); /* Receive data from Master */ if(HAL_SPI_Receive_IT(&SpiHandle, aRxBuffer, DATA_LENGTH) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* Synchronization between Master and Slave */ Slave_Synchro(); /* Send acknowledgement to Master */ ackbyte = SPI_ACK_BYTES; if(HAL_SPI_Transmit_IT(&SpiHandle, (uint8_t *)&ackbyte, sizeof(ackbyte)) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} /* In case, Master has sent data, compare received buffer with one expected */ if(Buffercmp((uint8_t*)aTxMasterBuffer, (uint8_t*)aRxBuffer, DATA_LENGTH)) { /* Transfer error in transmission process */ Error_Handler(); } else { /* Toggle LED6 on: Reception is correct */ BSP_LED_Toggle(LED6); } } } else { /* Synchronization between Master and Slave */ Slave_Synchro(); /* Send acknowledgement to Master */ ackbyte = SPI_NACK_BYTES; if(HAL_SPI_Transmit_IT(&SpiHandle, (uint8_t *)&ackbyte, sizeof(ackbyte)) != HAL_OK) { Error_Handler(); } while (HAL_SPI_GetState(&SpiHandle) != HAL_SPI_STATE_READY) {} Error_Handler(); } /* Flush Rx buffer for next transmission */ Flush_Buffer(aRxBuffer, DATA_LENGTH); } }
PMD_Status pmdSendSpi(PMD_Chunk* chunk) { calAssertTrue(PMD_isTypeSpi(chunk->pmdIfx)); if (chunk->pmdIfx == ptrIf1) { ptrIf1TxChunk = chunk; HAL_StatusTypeDef status; // Enable the chunk receipt if (SPI_IF1_USE_DMA == 1) { status = HAL_SPI_Transmit_DMA(spiTxHandle, ptrIf1TxChunk->data, CHUNK_LENGTH); } else { status = HAL_SPI_Transmit_IT(spiTxHandle, ptrIf1TxChunk->data, CHUNK_LENGTH); } return halStatusToPmdStatus(status); } return PMD_ERROR; }
Spi::Status Spi::transmit(const uint8_t* data, uint16_t n, TransmitCallback cb, void* args) { HAL_StatusTypeDef status; if (!data) return ILLEGAL; if (n < 1) return OK; // nothing to do if (cb) { // Use async spi transfer _txCallback = cb; _txArgs = args; return (Spi::Status) HAL_SPI_Transmit_IT(&_spi, const_cast<uint8_t*>(data), n); } else { // Use blocking spi transfer return (Spi::Status) HAL_SPI_Transmit(&_spi, const_cast<uint8_t*>(data), n, DEFAULT_TIMEOUT); } }
/// @returns the number of bytes transferred, or `0` if nothing transferred static int spi_master_start_asynch_transfer(spi_t *obj, transfer_type_t transfer_type, const void *tx, void *rx, size_t length) { struct spi_s *spiobj = SPI_S(obj); SPI_HandleTypeDef *handle = &(spiobj->handle); bool is16bit = (handle->Init.DataSize == SPI_DATASIZE_16BIT); // the HAL expects number of transfers instead of number of bytes // so for 16 bit transfer width the count needs to be halved size_t words; DEBUG_PRINTF("SPI inst=0x%8X Start: %u, %u\r\n", (int)handle->Instance, transfer_type, length); obj->spi.transfer_type = transfer_type; if (is16bit) { words = length / 2; } else { words = length; } // enable the interrupt IRQn_Type irq_n = spiobj->spiIRQ; NVIC_DisableIRQ(irq_n); NVIC_ClearPendingIRQ(irq_n); NVIC_SetPriority(irq_n, 1); NVIC_EnableIRQ(irq_n); // enable the right hal transfer int rc = 0; switch(transfer_type) { case SPI_TRANSFER_TYPE_TXRX: rc = HAL_SPI_TransmitReceive_IT(handle, (uint8_t*)tx, (uint8_t*)rx, words); break; case SPI_TRANSFER_TYPE_TX: rc = HAL_SPI_Transmit_IT(handle, (uint8_t*)tx, words); break; case SPI_TRANSFER_TYPE_RX: // the receive function also "transmits" the receive buffer so in order // to guarantee that 0xff is on the line, we explicitly memset it here memset(rx, SPI_FILL_WORD, length); rc = HAL_SPI_Receive_IT(handle, (uint8_t*)rx, words); break; default: length = 0; } if (rc) { DEBUG_PRINTF("SPI: RC=%u\n", rc); length = 0; } return length; }