嗨对话框工程师,
我使用DSPS应用程序固件作为我的基线代码开始。
我有一个DA通过UART线与外部MCU通信。这个UART的波特率为56.7kbps。
我实现了两个功能,从DA发送数据到外部MCU。
功能1:
- DA上电后,这个函数从Flash读取并通过UART线下载外部MCU固件。这个功能是100%稳定工作,因为外部MCU可以实际旋转和运行与它的固件。代码如下:
//读取QPI fw /从flash地址“address”和“size”&
//将QPI连接到的UART通道写出来
Void user_sps_qpi_fw_upload(unsigned int address) {
字节缓冲区[2];
//从Host UI flash程序读取存储在flash中的固件大小。
// firmware len是flash中每个FW地址段的前两个字节
unsigned int fwLen;
if(spi_flash_read_data(buf, address, USER_FLASH_QPI_FWSIZE_HDR) == USER_FLASH_QPI_FWSIZE_HDR) {
fwLen = (buf[0] << 8) | buf[1];
地址+ = USER_FLASH_QPI_FWSIZE_HDR;
}
无符号字符data_ptr [USER_FLASH_QPI_CI_BLK_SIZE];
//计算flash读取的次数。每次读取都是USER_FLASH_QPI_CI_BLK_SIZE字节
int n = fwLen/USER_FLASH_QPI_CI_BLK_SIZE + 1;
for (int i = 0;我< n;我+ +){
//从Flash中读取QPI FW。这可以是FW, Degamma表,LUM表
unsigned int ret = spi_flash_read_data(data_ptr, address + i*USER_FLASH_QPI_CI_BLK_SIZE,
USER_FLASH_QPI_CI_BLK_SIZE);
uart2_write (data_ptr USER_FLASH_QPI_CI_BLK_SIZE, NULL);
uart2_finish_transfers ();
}
}
-在这个函数中,我读取USER_FLASH_QPI_CI_BLK_SIZE = 256字节一次从Flash并写入UART2。
功能2:
-这个函数读取来自BLE线的数据,并通过UART2总线发送到外部MCU。以下是代码:
Void user_ble_push(uint8_t* wrdata, uint16_t write_amount)
{
ASSERT_ERR (wrdata ! = NULL);
ASSERT_ERR (write_amount ! = 0);
Bool send_flow_off = false;
//将BLE中的数据写入外部缓冲区
user_buffer_write_items (&ble_to_periph_buffer wrdata write_amount);
//检查缓冲区是否几乎满了,如果是的话发送XOFF
send_flow_off = user_check_buffer_almost_full (&ble_to_periph_buffer);
//如果必须发送XOFF,请尽快发送
如果(send_flow_off) {
user_send_ble_flow_ctrl (FLOW_OFF);
}
/ /开始传输
__disable_irq ();
如果(! uart_qpi_tx_callbackbusy) {
uart_qpi_tx_callbackbusy = true;
uart_qpi_tx_callback (UART_STATUS_INIT);
}
__enable_irq ();
}
-此功能是DSPS样例应用程序固件的一部分。我修改了它,以便用于我们自己的应用程序。uart_qpi_tx_callback()与DSPS示例中的内容相同。下面是该函数的代码,供参考:
静态uart_qpi_tx_callback(uint8_t res)
{
静态uint8_t大小= 0;
uint8_t * peripheral _tx_ptr = NULL;
//函数从uart传输isr或应用程序被调用时,它不运行
开关(res)
{
案例UART_STATUS_OK:
//获取数据和指针
Size = user_peri_pull (& peri_tx_ptr, Size);
打破;
案例UART_STATUS_INIT:
size = user_buffer_read_address(& ble_to_peri_buffer, & peri_tx_ptr, TX_CALLBACK_SIZE);
打破;
默认值:
ASSERT_ERROR (0);//错误:从未知的来源调用回调
}
//如果有可用的数据,发送数据通过periph
如果(size > 0) {
uart2_write (periph_tx_ptr、大小&uart_qpi_tx_callback);
返回;
}
//在缓冲区中没有数据,所以回调完成
uart_qpi_tx_callbackbusy = false;
}
现在我对以上两个功能的问题::
1.在函数1中,我实际上使用的是大小为256字节的UART写入。我知道TX FIFO大小只有16字节。为什么和如何在我的情况下工作。我不是抱怨。我只是想更好地理解它。
2.在函数2中,我在向外部MCU发送超过16字节的数据时遇到了问题。如果我发送16个字节或更少,MCU接收一切。如果我发送了一个大于16字节的数据包,超过16字节的字节将不会被接收。但是,如果我要一步一步地进入uart2_write()函数,并遍历uart2_thr_empty_isr()内的uart2_write(),我可以看到所有的数据,这些数据最终将被外部MCU正确接收。这种情况每次都会发生。如果我进入密码,它就会起作用。如果我让代码运行,它每次都会失败。
请让我知道你看到了什么并向我解释一下发生了什么?
谢谢大家,
——潘文凯
嗨kqtrinh,
1.FIFO有16个字节,但这并不意味着你只能发送一次16字节,我的意思是,只要你坚持推动数据FIFO那么UART将输出数据,您可以继续推动数据只要FIFO的房间(如果FIFO有额外的空间字节由uart2_txfifo_full_getf检查()),如果FIFO是满的,你继续推数据,这意味着数据将被重写,显然你将有丢失的字节。在UART驱动程序中,前16个字节被从uart2_write()函数中推入,一旦uart2_txfifo_full_getf()返回0 (FIFO中没有更多的空间)函数将返回并等待UART FIFO得到空,一旦它得到空,一个UART中断将命中指示一个空的FIFO和uart2_thr_empty_isr()正在中断上下文中被调用,以重新填充FIFO。
2.有关的事实,你可以看到所有的数据通过代码,当步进,只有16字节如果正常运行代码,我只能假设这是因为手动并通过步进代码UART FIFO有时间把单片机提供的数据打印出来,所以UART FIFO中总是有空间(while(uart2_txfifo_full_getf())函数总是非零,所以所有的打印都是从uart2_thr_empty_isr()完成的,uart2_write()调用)。但是在真实的情况下,处理器全速运行,并且在前16个字节之后调用uart2_write(), FIFO将被填满,uart2_thr_empty_isr()将返回并等待UART FIFO打印其所有数据,UART中断后会出现为了通知FIFO是空的,你可以把更多的数据FIFO,所以UART2_Handler()调用,为了uart2_thr_empty_isr()填写下一批16字节,所以显然uart2_thr_empty_isr UART2_Handler不会被调用()。我相信,很可能这就是为什么你只得到16字节的数据在第二种情况下,但是你需要更多的调试这仅仅因为这是一个假设,我不能看到在这种情况下会发生什么和什么是确切的原因,你无法获得数据在另一边。
由于MT_dialog
嗨太,
感谢您带我通过uart2_write()机制。你解释了FIFO如何工作,我只是放置了一个1毫秒的等待每16字节的事务,以允许FIFO时间空其数据之前下一个16字节块再次发送。这招真管用。
谢谢你!
——潘文凯