/* * Transmit message. * * This implements flow control by waiting for the slave to be non-busy. */ void spi_tx_wait(void) { struct spi_dev *dev = &spi_dev; struct ayla_cmd *cmd; u8 mask; cmd = (struct ayla_cmd *)spi_tx_buf; mask = spi_tx_get_mask_to_check(cmd->protocol, cmd->opcode); if (spi_tx_check_busy(mask)) { return; } dev->state = SS_TX_START; spi_tx_start(); }
static void tx_task(void) { if (USB_DeviceState != DEVICE_STATE_Configured) return; Endpoint_SelectEndpoint(OUT_EPADDR); if (Endpoint_IsOUTReceived() && csma_tx_allowed() && spi_tx_prepare()) { if (Endpoint_IsReadWriteAllowed()) { if (!(data[front].flags & FLAG_TX_READY)) { Endpoint_Read_Stream_LE(&data[front], sizeof(data[front]), NULL); data[front].flags |= FLAG_TX_READY; adf_set_tx_mode(); spi_tx_start(); } else { Endpoint_Read_Stream_LE(&data[back], sizeof(data[back]), NULL); data[back].flags |= FLAG_TX_READY; } Endpoint_ClearOUT(); } } }
/* * Poll for incoming messages. */ void spi_poll(void) { struct spi_dev *dev = &spi_dev; int pri; if (!stm32_ready()) { return; } pri = intr_disable_save(); switch (dev->state) { case SS_IDLE: if (spi_platform_rx_pending()) { dev->state = SS_RX_WAIT; spi_platform_slave_select(); spi_rx_wait(); } else if (dev->tx_ready) { spi_platform_slave_select(); dev->state = SS_TX_WAIT; } break; case SS_RX_WAIT: spi_rx_wait(); break; case SS_RX: spi_rx(); break; case SS_TX_WAIT: spi_tx_wait(); break; case SS_TX_START: spi_tx_start(); break; case SS_TX_END: spi_tx_end(); break; } intr_restore(pri); }