/** * \brief Interrupt handler for the SPI slave. */ void SPI_IrqHandler( void ) { uint32_t status; uint8_t startNew = 0; status = SPI_GetStatus( SPI_SLAVE_BASE ) ; if ( status & SPI_SR_NSSR ) { if ( status & SPI_SR_RXBUFF ) { /* Disable the RX and TX PDC transfer requests */ SPI_PdcDisableTx( SPI_SLAVE_BASE ) ; SPI_PdcDisableRx( SPI_SLAVE_BASE ) ; } if ( status & SPI_IDR_ENDRX ) { SPI_DisableIt( SPI_SLAVE_BASE, SPI_IDR_ENDRX ) ; } switch ( status & (SPI_SR_RXBUFF | SPI_SR_ENDRX) ) { case (SPI_SR_RXBUFF | SPI_SR_ENDRX): case (SPI_SR_RXBUFF): SpiSlaveCommandProcess() ; startNew = 1 ; break ; /* Maybe command break data transfer, start new */ case SPI_SR_ENDRX: { /* Command breaks data transfer */ SPI_PdcDisableTx( SPI_SLAVE_BASE ) ; SPI_PdcDisableRx( SPI_SLAVE_BASE ) ; SPI_Configure( SPI_SLAVE_BASE, ID_SPI, 0 ) ; SPI_ConfigureNPCS( SPI_SLAVE_BASE, 0 , 0 ) ; startNew = 1 ; } break; default: break; } if ( startNew ) { if ( spiCmd != CMD_END ) { spiStatus.cmdList[spiStatus.totalNumCommands] = spiCmd; spiStatus.totalNumCommands ++; } SpiSlaveNewCommand(); } } }
/** * \brief Configures spi in slave mode. */ static void _ConfigureSpiSlave( void ) { /* Configure SPI slave mode */ SPI_Configure(SPI, ID_SPI, SPI_PCS(0)); NVIC_ClearPendingIRQ(SPI_IRQn); NVIC_SetPriority(SPI_IRQn ,1); NVIC_EnableIRQ(SPI_IRQn); SPI_DisableIt(SPI, 0xffffffff); SPI_ConfigureNPCS(SPI, 0, 0); }
/** * \brief Configures spi in master mode. */ static void _ConfigureSpiMaster(void) { /* Configure SPI master mode */ SPI_Configure(SPI, ID_SPI, (SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_PCS(1))); NVIC_ClearPendingIRQ(SPI_IRQn); NVIC_SetPriority(SPI_IRQn ,1); NVIC_EnableIRQ(SPI_IRQn); SPI_DisableIt(SPI, 0xffffffff); SPI_ConfigureNPCS(SPI, 1, SPI_DLYBCT( 100, BOARD_MCK ) | SPI_DLYBS(100, BOARD_MCK) | SPI_SCBR( spiClock, BOARD_MCK) | SPI_CSR_BITS_8_BIT); }
void spi_stack_master_disable_dma(void) { SPI_DisableIt(SPI, SPI_IER_ENDRX | SPI_IER_ENDTX); SPI->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS; spi_stack_deselect(); }
void SPI_IrqHandler(void) { if(spi_stack_buffer_size_recv != 0) { return; } // Disable SPI interrupt and interrupt controller SPI_DisableIt(SPI, SPI_IER_RDRF); __disable_irq(); uint8_t slave_checksum = 0; uint8_t master_checksum = 0; PEARSON(slave_checksum, spi_stack_buffer_size_send); volatile uint8_t dummy; // Empty read register while((SPI->SPI_SR & SPI_SR_RDRF) == 0); dummy = SPI->SPI_RDR; while((SPI->SPI_SR & SPI_SR_RDRF) == 0); dummy = SPI->SPI_RDR; // Synchronize with master while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = 0xFF; while((SPI->SPI_SR & SPI_SR_RDRF) == 0); dummy = SPI->SPI_RDR; // Write length while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = spi_stack_buffer_size_send; // Write first byte while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = spi_stack_buffer_send[0]; PEARSON(slave_checksum, spi_stack_buffer_send[0]); // Read length from master while((SPI->SPI_SR & SPI_SR_RDRF) == 0); uint8_t master_length = SPI->SPI_RDR; PEARSON(master_checksum, master_length); // If master and slave length are 0, stop communication if(master_length == 0 && spi_stack_buffer_size_send == 0) { // Read dummy while((SPI->SPI_SR & SPI_SR_RDRF) == 0); dummy = SPI->SPI_RDR; // Write 0 (so there is no random 0xFF) SPI->SPI_TDR = 0; SPI_EnableIt(SPI, SPI_IER_RDRF); __enable_irq(); return; } // Length to transceive is maximum of slave and master length uint8_t max_length = MIN(MAX(spi_stack_buffer_size_send, master_length), SPI_STACK_BUFFER_SIZE); // Exchange data for(uint8_t i = 1; i < max_length; i++) { // Write while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = spi_stack_buffer_send[i]; PEARSON(slave_checksum, spi_stack_buffer_send[i]); // Read while((SPI->SPI_SR & SPI_SR_RDRF) == 0); spi_stack_buffer_recv[i-1] = SPI->SPI_RDR; PEARSON(master_checksum, spi_stack_buffer_recv[i-1]); } // Write CRC while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = slave_checksum; // Read last data byte while((SPI->SPI_SR & SPI_SR_RDRF) == 0); spi_stack_buffer_recv[max_length-1] = SPI->SPI_RDR; PEARSON(master_checksum, spi_stack_buffer_recv[max_length-1]); // Read CRC while((SPI->SPI_SR & SPI_SR_RDRF) == 0); uint8_t crc = SPI->SPI_RDR; // CRC correct? uint8_t slave_ack = crc == master_checksum; // Write ACK/NACK while((SPI->SPI_SR & SPI_SR_TDRE) == 0); SPI->SPI_TDR = slave_ack; // Read ACK/NACK while((SPI->SPI_SR & SPI_SR_RDRF) == 0); uint8_t master_ack = SPI->SPI_RDR; // If everything OK, set sizes accordingly if(master_ack == 1 && slave_ack == 1) { spi_stack_buffer_size_recv = master_length; spi_stack_buffer_size_send = 0; } // Last byte written is 1 or 0 (ack/nack), so there can't be an // accidental 0xFF // Enable SPI interrupt only if no new data is received. // Otherwise the spi_recv function will enable interrupt again. if(spi_stack_buffer_size_recv == 0) { SPI_EnableIt(SPI, SPI_IER_RDRF); } __enable_irq(); }