static Cyg_ErrNo spi_write( cyg_io_handle_t handle, const void *buf, cyg_uint32 *len) { dbguPrint("Start von SPI_WRITE\n"); xPrintf("Status_Register %lX\n", AT91C_BASE_SPI1->SPI_SR); (((struct spi_buf_t*)buf)->driverMode) = 1; xPrintf("-->spi_write(): channel: %d, len: %d , txbuf: %d, rxbuf: %d.. ?", ((struct spi_buf_t*)buf)->channelNum, ((struct spi_buf_t*)buf)->packetSize, ((struct spi_buf_t*)buf)->txBuffer, ((struct spi_buf_t*)buf)->rxBuffer); // AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA2; cyg_mutex_lock(&mut_SpiHW); // AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA2; if ( (((struct spi_buf_t*)buf)->driverMode)==POLLING_MODE ) { while ( !((AT91C_BASE_SPI1->SPI_SR) & AT91C_SPI_ENDRX ) ); //!!! spi hardware muss frei sein! cyg_drv_interrupt_mask( spi_irqConfig.int_vector); // AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA2; dbguPrint("vor transmit\n"); spiTransmit( ((struct spi_buf_t*)buf)->channelNum, ((struct spi_buf_t*)buf)->txBuffer, ((struct spi_buf_t*)buf)->rxBuffer, ((struct spi_buf_t*)buf)->packetSize); dbguPrint("nach transmit\n"); AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA2; while ( !((AT91C_BASE_SPI1->SPI_SR) & AT91C_SPI_ENDRX ) ); //!!! ENDRX ist wichtig! // AT91C_BASE_PIOA->PIO_CODR = AT91C_PIO_PA2; cyg_mutex_unlock(&mut_SpiHW); // AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA2; } else if ( (((struct spi_buf_t*)buf)->driverMode)==INTERRUPT_MODE ) { dbguPrint("Interrupt Mode"); cyg_drv_interrupt_unmask( spi_irqConfig.int_vector); spiTransmit( ((struct spi_buf_t*)buf)->channelNum, ((struct spi_buf_t*)buf)->txBuffer, ((struct spi_buf_t*)buf)->rxBuffer, ((struct spi_buf_t*)buf)->packetSize); } else return EINVAL; */ dbguPrint("Ende von SPI_WRITE\n"); xPrintf("Status_Register %lX\n", AT91C_BASE_SPI1->SPI_SR); return ENOERR; } void spiTransmit(char channel, char *txBuffer, char *rxBuffer, unsigned short length) { // unsigned int status; // unsigned int val; dbguPrint("Start von Transmit\n"); AT91PS_SPI pSPI = AT91C_BASE_SPI1; // pointer to a SPI controller spiTransLength = 0; if (spiRole == SPI_ROLE_MASTER) { //set the rigth chip select AT91F_SPI_CfgPCS(AT91C_BASE_SPI1, ~((char)1<SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS; //* Initialize the Transmit and Receive Pointer pSPI->SPI_TPR = (unsigned int) txBuffer ; //pSPI->SPI_RPR = (unsigned int) rxBuffer ; //* Intialize the Transmit and Receive Counters //pSPI->SPI_RCR = (unsigned int)length; pSPI->SPI_TCR = (unsigned int)length; // trigger interrupt when the last byte was received!! pSPI->SPI_IER = AT91C_SPI_RXBUFF | AT91C_SPI_MODF; //enable transmitter and receiver AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN; } else { //SPI Slave pTxBuffer = txBuffer; pRxBuffer = rxBuffer; txRxLength = length; //write the first byte to the transmit register AT91C_BASE_SPI1->SPI_TDR = (unsigned int) pTxBuffer[0]; rxIndex = 0; txIndex = 0; //enable the Transmit and Receive Data Interrupts pSPI->SPI_IER = AT91C_SPI_TDRE; pSPI->SPI_IER = AT91C_SPI_RDRF; //unblock the master //spiSetRts(FALSE); } } * ------------------------------------------------------------------------- * * at91_spi_ISR() * * Low level Interrupt Service Routine for SPI driver. * ------------------------------------------------------------------------- */ static volatile cyg_uint32 spiEvents; static cyg_uint32 at91_spi_ISR( cyg_vector_t vector, cyg_addrword_t data) { cyg_drv_interrupt_mask( vector); dbguPrint("SPI ISR\n"); spiEvents = spiInterruptHandler(); //xPrintf("SPIint evt: 0x%x", spiEvents); // Clean after the interrupt cyg_drv_interrupt_acknowledge( vector); cyg_drv_interrupt_unmask( vector); // Use DSR_1 only if needed return(spiEvents) ? (CYG_ISR_CALL_DSR | CYG_ISR_HANDLED) : (CYG_ISR_HANDLED); } /* ------------------------------------------------------------------------- * * at91_spi_DSR() * * High level Interrupt Service Routine for SPI driver. * ------------------------------------------------------------------------- */ static void at91_spi_DSR( cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { dbguPrint("SPI DSR\n"); if ((spiEvents & 0x100) && (CS0CallBack)) { //dbguPrint("SPIdsr CS0CallBack"); CS0CallBack(spiEvents & 0xFF); } else if ((spiEvents & 0x200) && (CS1CallBack)) { //dbguPrint("SPIdsr CS1CallBack"); CS1CallBack(spiEvents & 0xFF); } else if ((spiEvents & 0x400) && (CS2CallBack)) { //dbguPrint("SPIdsr CS2CallBack"); CS2CallBack(spiEvents & 0xFF); } else if ((spiEvents & 0x800) && (CS3CallBack)) { //dbguPrint("SPIdsr CS3CallBack"); CS3CallBack(spiEvents & 0xFF); } //if (spiEvents & (SPI_EVENT_TX_DONE | SPI_EVENT_RX_DONE)) { cyg_mutex_unlock( &mut_SpiHW); } return; } /**********************************************************************/ /** * . * * @param * * @return */ /**********************************************************************/ //extern int spiIrqs2; void spiTransmit(char channel, char *txBuffer, char *rxBuffer, unsigned short length) { // unsigned int status; // unsigned int val; dbguPrint("Start von Transmit\n"); AT91PS_SPI pSPI = AT91C_BASE_SPI1; // pointer to a SPI controller spiTransLength = 0; if (spiRole == SPI_ROLE_MASTER) { //set the rigth chip select AT91F_SPI_CfgPCS(AT91C_BASE_SPI1, ~((char)1<SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS; //* Initialize the Transmit and Receive Pointer pSPI->SPI_TPR = (unsigned int) txBuffer ; //pSPI->SPI_RPR = (unsigned int) rxBuffer ; //* Intialize the Transmit and Receive Counters //pSPI->SPI_RCR = (unsigned int)length; pSPI->SPI_TCR = (unsigned int)length; // trigger interrupt when the last byte was received!! pSPI->SPI_IER = AT91C_SPI_RXBUFF | AT91C_SPI_MODF; //enable transmitter and receiver AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_TXTEN + AT91C_PDC_RXTEN; pTxBuffer = txBuffer; pRxBuffer = rxBuffer; txRxLength = length; } else { //SPI Slave pTxBuffer = txBuffer; pRxBuffer = rxBuffer; txRxLength = length; //write the first byte to the transmit register AT91C_BASE_SPI1->SPI_TDR = (unsigned int) pTxBuffer[0]; rxIndex = 0; txIndex = 0; //enable the Transmit and Receive Data Interrupts pSPI->SPI_IER = AT91C_SPI_TDRE; pSPI->SPI_IER = AT91C_SPI_RDRF; //unblock the master //spiSetRts(FALSE); } } /**********************************************************************/ /** * Checks the source of the SPI interrupt. * Returns bitwise event map of the sources. * * @param * * @return */ /**********************************************************************/ unsigned int spiInterruptHandler(void) { dbguPrint("SPI InterruptHandler\n"); unsigned int status; unsigned int event; event = 0; event|= ((~(AT91C_BASE_SPI1->SPI_MR)) & 0xF0000 ) >> 8 ; //read the interrup status status = AT91C_BASE_SPI1->SPI_SR & AT91C_BASE_SPI1->SPI_IMR; //disable receiver and transmitter AT91C_BASE_SPI1->SPI_PTCR = AT91C_PDC_TXTDIS + AT91C_PDC_RXTDIS; if (( status & AT91C_SPI_MODF)) { //* Disable the Mode fault Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_MODF; event |= SPI_EVENT_MODE_FAULT; } if (( status & AT91C_SPI_TDRE)) { //* Disable the Receive Data Register Full Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_TDRE; txIndex++; if (txIndex < txRxLength) { //write the next byte to the transmit register AT91C_BASE_SPI1->SPI_TDR = (unsigned int) (pTxBuffer[txIndex]); //enable the Receive Data Register Full Interrupt //AT91C_BASE_SPI->SPI_IER = AT91C_SPI_TDRE; } } if (( status & AT91C_SPI_RDRF)) { //SPI Slave Implementation //because the PDC doesn#t work under SPI Slave //the transmit buffer empty interrupt is not reliable raised //* Disable the Receive Data Register Full Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_RDRF; //read the received byte pRxBuffer[rxIndex] = AT91C_BASE_SPI1->SPI_RDR; rxIndex++; if (rxIndex < txRxLength) { //enable the Receive Data Register Full Interrupt AT91C_BASE_SPI1->SPI_IER = AT91C_SPI_RDRF; } else { //all bytes were received //so disable the slave select rising Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_NSSR; spiTransLength = txRxLength; event |= SPI_EVENT_RX_DONE; } } if (( status & AT91C_SPI_RXBUFF)) { //* Disable the Receive Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_RXBUFF; //dbguPrint("received over SPI: \n"); spiTransLength = txRxLength; event |= SPI_EVENT_RX_DONE; } if (( status & AT91C_SPI_NSSR)) { //for slave implementation //normally not used, we trigger only on AT91C_SPI_RDRF //* Disable the slave select rising Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_NSSR; //calculate the really transmitted bytes spiTransLength = txRxLength - AT91C_BASE_SPI1->SPI_RCR; event |= SPI_EVENT_RX_DONE; } if (( status & AT91C_SPI_TXBUFE)) { //normally not used, we trigger only on AT91C_SPI_RXBUFF //* Disable the Transmit Interrupt AT91C_BASE_SPI1->SPI_IDR = AT91C_SPI_TXBUFE; event |= SPI_EVENT_TX_DONE; } return event; }