non-blocking SPI slave implementation

5 posts / 0 new
Last post
BB
Offline
Last seen:3 years 10 months ago
加入:2015-11-03 12:16
non-blocking SPI slave implementation

Dear reader,
我正在尝试在DA14580和主机MCU之间实现SPI通信,用于数据包传输。DA14580充当SPI从站(8位,POL = 0,PHA = 0,双向FIFO,减少中断线,自己的流量控制)。作为我使用的起点spi_hci.c. However, I noticed that thespi_hci_write_func()是阻止的,不是 - 作为spi_hci_read_func()is - interrupt based. I am trying to make the write function interrupt based, however some things are not clear to me:
- It is unclear from the datasheet which bits (e.g. SPI_INT_BIT, SPI_TXH, SPI_BUSY) are set/cleared and when. Is there a timing diagram available?
- Is it possible to read and write at the same time with this module? (according to the SPI specs it should be)

Currently, I am testing with a Bus Pirate and a 2-channel oscilloscope and when I try to write the code hangs in a while loop inspi_transfer_byte()checkin for spi_txh位。


/**
****************************************************************************************
* @brief Read function of the SPI external interface API.
*
* @param [in] * bufptr:指向存储器位置的指针,读取数据将被存储。
* @param[in] size: Size of the data to be read in bytes.
* @param[in] *callback: Pointer to the callback function.
****************************************************************************************
*/
void spi_hci_read_func(uint8_t *bufptr, uint32_t size,void (*callback) (uint8_t))
{
// 完整性检查
ASSERT_ERR(bufptr != NULL);
ASSERT_ERR(size != 0);
assert_err(spi_env.rx.bufptr == null);
//准备RX参数
spi_env.rx.size = size;
spi_env.rx.bufptr = bufptr;
spi_env.rx.callback = callback;
// Enable SPI interrupt
nvic_enableirq(spi_irqn);
}


/**
****************************************************************************************
* @brief Write function of the SPI external interface API.
*
* @param[in] *bufptr: Pointer to the memory location of the data to be written.
* @param[in] size: Size of the data to be written in bytes.
* @param[in] *callback: Pointer to the callback function.
****************************************************************************************
*/
空白spi_hci_write_func (uint8_t * bufptr uint32_t size, void (*callback) (uint8_t))
{
// 完整性检查
ASSERT_ERR(bufptr != NULL);
ASSERT_ERR(size != 0);
assert_err(spi_env.tx.bufptr == null);
//准备TX参数
spi_env.tx.size = size;
spi_env.tx.bufptr = bufptr;
spi_env.tx.callback = callback;
// Enable SPI interrupt
nvic_enableirq(spi_irqn);
//assert DREADY signal
spi_dready_high();
}


/**
****************************************************************************************
* @brief Exported function for SPI interrupt handler.
****************************************************************************************
*/
void SPI_Handler(void)
{
//NVIC_DisableIRQ(SPI_IRQn); // <<-- should I disable the interrupt callback?
spi_transfer_data_isr();
}


/**
****************************************************************************************
* @brief Serves the receive data interrupt requests. It reads incoming data from SPI
* while SPI_INT_BIT is 1, and saves them to the receive buffer pointer.
* Serves the transmit data requests. It asserts the DREADY signal to request a
*发送到主设备,当主设备提供时钟信号时数据
* transaction is performed. Upon completion, it de-asserts the DREADY signal.
*
****************************************************************************************
*/
static void spi_transfer_data_isr(void)
{
void (*callback_transmit) (uint8_t) = NULL;
void (*callback_receive) (uint8_t) = NULL;
// Read available received data to SPI environment buffer pointer
while (spi_data_rdy_getf())
{
// Read the received byte in the FIFO and write byte. Any more bytes received are ignored.
spi_transfer_byte(spi_env.tx.bufptr,spi_env.rx.bufptr);
if (spi_env.rx.bufptr!=NULL)
{
// Update RX parameters
spi_env.rx.size--;
spi_env.rx.bufptr++;
}
if (spi_env.tx.bufptr!=NULL)
{
// Update RX parameters
spi_env.tx.size--;
spi_env.tx.bufptr++;
}
//检查是否已收到所有预期数据
if(spi_env.rx.size == 0 && spi_env.rx.bufptr!= null)
{
// Retrieve callback pointer
callback_receive = spi_env.rx.callback;
//清除回调指针
spi_env.rx.callback = null;
// Reset RX parameters
spi_env.rx.bufptr = null;
break;
}
//检查是否已传输所有数据
if (spi_env.tx.size == 0 && spi_env.tx.bufptr!=NULL)
{
spi_dready_low(); // De-assert DREADY signal, transmit completed
// Retrieve callback pointer
callback_transmit = spi_env.tx.callback;
//清除回调指针
spi_env.tx.callback = NULL;
// Reset TX parameters
spi_env.tx.bufptr = NULL;
break;
}
}
// Disable TX interrupt
spi_int_bit_clear(); // <-- if this is cleared in the transfer function, the while loop may exit before all bytes are transmitted
NVIC_DisableIRQ(SPI_IRQn);
if(callback_receive != NULL)
{
// Call handler
callback_receive(SPI_STATUS_OK);
}
else if(callback_transmit != NULL)
{
// Call handler
callback_transmit(SPI_STATUS_OK);
}
else
{
ASSERT_ERR(0);
}
}


/**
****************************************************************************************
* @brief read and/or write a byte to SPI.
*
* @param [in] wr_byte:要传输的字节。如果没有传输,则为null
* rd_byte: byte to be received. NULL if nothing has to be read.
****************************************************************************************
*/
__INLINE void spi_transfer_byte(const uint8_t* wr_byte, uint8_t *rd_byte) //@@@Wouter: combined read and write into one function, so a read and write can occur simultaneously
{
if (wr_byte!=NULL)
{
而(getBits16(SPI_CTRL_REG,SPI_TXH)== 1);//等待SPI TX FIFO已满
setword16(spi_rx_tx_reg0,0xff&(0xAb));//发送字节
}
while (GetBits16(SPI_CTRL_REG1,SPI_BUSY)==1); // Wait while SPI is busy <-- the system hangs here
if (rd_byte!=NULL)
{
*rd_byte = 0xFF&GetWord16(SPI_RX_TX_REG0); // Read byte from SPI
}
else
{
getword16(spi_rx_tx_reg0);//获得收到的字节并丢弃它。
}
//SetWord16(SPI_CLEAR_INT_REG, 0x01); // Clear pending flag <-- clearing the flag will exit the while loop in the interrupt handler.
}

Keywords:
Device:
BB
Offline
Last seen:3 years 10 months ago
加入:2015-11-03 12:16
It seems like writing to the

似乎写入sp_rx_tx_reg0根本不会影响寄存器的值。可以阻止访问此寄存器的东西吗?

BB
Offline
Last seen:3 years 10 months ago
加入:2015-11-03 12:16
It was a signal line problem.

It was a signal line problem.
Nevertheless a SPI time diagram would be very useful.

mabraun
Offline
Last seen:3年6个月前
加入:2015-11-16 15:57
我第二个是一个有用性

我第二个是一个有用性timing diagram regarding the signals SPI_INT_BIT, SPI_TXH, SPI_BUSY. I am working on something similar and would profit from a better understanding of the SPI timings.

问候,
mabraun

MT_dialog
Offline
Last seen:2 months 2 weeks ago
Staff
加入:2015-06-08 11:34
Hi all,

Hi all,

当时没有可用的图表,将SPI寄存器的状态映射到在SPI上的外部模式下执行的函数。我将向团队提供您的请求,以进一步对SPI进行外部配置的文件。

Thanks MT_dialog