如何通过 UART 读取 firmware.bin 文件?

how to read firmware.bin file through UART?

我必须通过 UART 读取 firmware.bin 文件,文件大小 50,000 byte.i 编写代码但它在读取文件时显示垃圾值。

我如何读取 firmware.bin 大小为 50,000 字节的文件。?我使用 ARM cortex 控制器进行编程。

我能够读取大小小于 150 字节的 .txt 文件,但当文件大小超过 150 字节时,它的读取垃圾值。我的任务是读取 50,000 字节的二进制文件 .bin

void read file()
{
UART1_TxString("AT+QFOPEN=\"RAM:FIRMWARE.BIN\",2\r");
                                              //2:only read for opend file.
WaitForExpectedResponse("+QFOPEN:",1000);    // timeout 1000ms       
                                     //in response +QFOPEN: 134072 filehandler
UART1_TxString("AT+QFREAD=134072\r");
connect = WaitForConnectResponse("CONNECT",60000); // timeout 60000ms
                       // in response CONNECT 50000 (i.e.filesize 50,000 byte)
while(connect)
{    
   int i=0,j=0;
   char* param = strchr(UART1Buffer, 'T') + (strlen(size_buff)+2);
          // UART1Buffer its UART-Buffer of size 160.
          // size_buff store file size to be read in string (50000)
          // size_int  store file size to be read in integer(50000)
 for(i=0;i<size_int;i++){           
        UART2_Printf(" %c ",*param);// print UART-BUFFER-DATA
  }
 }
}
void UART1_IRQHandler ( void ) 
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;

  IIRValue = LPC_UART1->IIR;

  IIRValue >>= 1;           /* skip pending bit in IIR */
  IIRValue &= 0x07;         /* check bit 1~3, interrupt identification */
  if ( IIRValue == IIR_RLS )        /* Receive Line Status */
  {
    LSRValue = LPC_UART1->LSR;

    if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
    {
      UART1Status = LSRValue;
      Dummy = LPC_UART1->RBR;       /* Dummy read on RX to clear 
                                interrupt, then bail out */
      return;
    }
    if ( LSRValue & LSR_RDR )   /* Receive Data Ready */            
    {
      UART1Buffer[UART1Count] = LPC_UART1->RBR;
      UART1Count++;
      if ( UART1Count == BUFSIZE )  // BUFSIZE= 160
      {
        UART1Count = 0;     /* buffer overflow */
      } 
    }
  }
  else if ( IIRValue == IIR_RDA )   /* Receive Data Available */
  {
    UART1Buffer[UART1Count] = LPC_UART1->RBR;
    UART1Count++;
    if ( UART1Count == BUFSIZE )
    {
      UART1Count = 0;       /* buffer overflow */
    }
  }
}

要缓冲将在其他上下文中异步读取的数据(在本例中,在 ISR 和 "normal" 线程之间,您应该使用 FIFO 或环形缓冲区,以便 ISR 可以继续在正常线程读取和处理缓冲区时写入缓冲区。例如,给定:

#include <stdint.h>
#include <stdatomic.h>

#define BUFFLEN ((uint8_t)128u)               // Must be a power of 2
#define BUFFMODMASK ((uint8_t)(BUFFLEN - 1))  // modulo BUFFLEN mask

typedef volatile struct
{
    uint8_t write_idx ;
    uint8_t read_idx ;
    atomic_int count ;
    uint8_t data[BUFFLEN] ;
} tRingBuf ;

void ringBufPut( tRingBuf* buffer, uint8_t ch )
{
    if( buffer->count < BUFFLEN )
    {
        buffer->data[buffer->write_idx++] = ch ;
        buffer->write_idx &= BUFFMODMASK ;
        buffer->count++ ;
    }
}

int ringBufGet( tRingBuf* buffer )
{
    int ch = -1 ;
    if( buffer->count > 0 )
    {
        ch =  (int)buffer->data[buffer->read_idx++] ;    
        buffer->read_idx &= BUFFMODMASK ;
        buffer->count-- ;
    }

    return ch ;
}

tRingBuf UART1RxBuffer = { 0, 0, 0, {0} } ;

您的 ISR 然后将数据放入缓冲区:

ringBufPut( &UART1RxBuffer, LPC_UART1->RBR ) ;

那么你的主线程就可以这样读取数据了:

for( int i = 0; i < size_int; i++ )
{           
    int ch = ringBufGet( &UART1RxBuffer ) ;
    if( ch > 0 )
    {
        uint8_t byte = (uint8_t)ch ;

        // ... do something with the data here
        // For example...
        UART2_Printf( "%02X", (unsigned)byte ) ;
    }
}

对于所有 UART,您最好以相同的方式(反转 put/get)实现 UART Tx - 您的 ISR 当前仅处理 Rx。完全缓冲 I/O 将导致更确定的时序。

感谢克利福德的回复。我几乎非常接近我需要做的事情。 我尝试使用环形缓冲区来工作,我几乎完成了这个。

但是当我尝试读取大文件 (48kB) Update.BIN 文件时, 它正在读取完整的文件,但是当我将这个读取的文件与 实际文件 进行比较时,观察到数据丢失和数据不匹配 (附上实际文件和我在此阅读的内容)。

我通过 UART 环形缓冲区读取的文件: https://www.dropbox.com/s/93k3i3r598jkxro/My_Read_file.log?dl=0

我尝试读取的实际文件:https://www.dropbox.com/s/bmh5wyurrdvvtqx/Update.BIN.txt?dl=0

我的环形缓冲区代码如下:

#define UART_RING_BUFSIZE 256
#define __BUF_MASK (UART_RING_BUFSIZE-1)
#define __BUF_IS_FULL(head, tail) ((tail&__BUF_MASK)==((head+1)&__BUF_MASK))
#define __BUF_WILL_FULL(head, tail) ((tail&__BUF_MASK)==((head+2)&__BUF_MASK))
#define __BUF_IS_EMPTY(head, tail) ((head&__BUF_MASK)==(tail&__BUF_MASK))
#define __BUF_RESET(bufidx) (bufidx=0)
#define __BUF_INCR(bufidx)  (bufidx=(bufidx+1)&__BUF_MASK)

typedef struct
{
    __IO uint32_t tx_head;                /*!< UART Tx ring buffer head index */
    __IO uint32_t tx_tail;                /*!< UART Tx ring buffer tail index */
    __IO uint32_t rx_head;                /*!< UART Rx ring buffer head index */
    __IO uint32_t rx_tail;                /*!< UART Rx ring buffer tail index */
    __IO uint8_t  tx[UART_RING_BUFSIZE];  /*!< UART Tx data ring buffer */
    __IO uint8_t  rx[UART_RING_BUFSIZE];  /*!< UART Rx data ring buffer */
} UART_RING_BUFFER_T;


// UART Ring buffer
UART_RING_BUFFER_T rb;

// Current Tx Interrupt enable state
__IO FlagStatus TxIntStat;

中断 IRQHandler:

void UART0_IRQHandler(void)
{
    uint32_t intsrc, tmp, tmp1;

    /* Determine the interrupt source */
    intsrc = UART_GetIntId(LPC_UART0);
    tmp = intsrc & UART_IIR_INTID_MASK;

    // Receive Line Status
    if (tmp == UART_IIR_INTID_RLS){
        // Check line status
        tmp1 = UART_GetLineStatus(LPC_UART0);
        // Mask out the Receive Ready and Transmit Holding empty status
        tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
                | UART_LSR_BI | UART_LSR_RXFE);
        // If any error exist
        if (tmp1) {
                UART_IntErr(tmp1);
        }
    }
    // Receive Data Available or Character time-out
    if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)){
            UART_IntReceive();
    }
    // Transmit Holding Empty
    if (tmp == UART_IIR_INTID_THRE){
            UART_IntTransmit();
    }
}

用于接收数据:

void UART_IntReceive(void)
{
    uint8_t temp;
    uint32_t recv_byte;

    while(1){

        recv_byte = UART_Receive((LPC_UART_TypeDef *)LPC_UART0, &temp, 1, NONE_BLOCKING);
        // If data received
        if (recv_byte){

            if (!__BUF_IS_FULL(rb.rx_head,rb.rx_tail)){
                rb.rx[rb.rx_head] = temp;
                __BUF_INCR(rb.rx_head);
            }
        }
        // no more data
        else {
            break;
        }
    }
}

用于传输数据:

void UART_IntTransmit(void)
{
    // Disable THRE interrupt
    UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0, UART_INTCFG_THRE, DISABLE);

    while (UART_CheckBusy((LPC_UART_TypeDef *)LPC_UART0) == SET);

    while (!__BUF_IS_EMPTY(rb.tx_head,rb.tx_tail))
    {
        /* Move a piece of data into the transmit FIFO */
        if (UART_Send((LPC_UART_TypeDef *)LPC_UART0, (uint8_t *)&rb.tx[rb.tx_tail], 1, NONE_BLOCKING)){
        /* Update transmit ring FIFO tail pointer */
        __BUF_INCR(rb.tx_tail);
        } else {
            break;
        }
    }

    if (__BUF_IS_EMPTY(rb.tx_head, rb.tx_tail)) {
        UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0, UART_INTCFG_THRE, DISABLE);
        // Reset Tx Interrupt state
        TxIntStat = RESET;
    }
    else{
        // Set Tx Interrupt state
        TxIntStat = SET;
        UART_IntConfig((LPC_UART_TypeDef *)LPC_UART0, UART_INTCFG_THRE, ENABLE);
    }
}
void UART_IntErr(uint8_t bLSErrType)
{
    uint8_t test;
    // Loop forever
    while (1){
        // For testing purpose
        test = bLSErrType;
    }
}

UART 接收和发送函数在中断中的使用:

uint32_t UART_Send(LPC_UART_TypeDef *UARTx, uint8_t *txbuf,
        uint32_t buflen, TRANSFER_BLOCK_Type flag)
{
    uint32_t bToSend, bSent, timeOut, fifo_cnt;
    uint8_t *pChar = txbuf;

    bToSend = buflen;

    // blocking mode
    if (flag == BLOCKING) {
        bSent = 0;
        while (bToSend){
            timeOut = UART_BLOCKING_TIMEOUT;
            // Wait for THR empty with timeout
            while (!(UARTx->LSR & UART_LSR_THRE)) {
                if (timeOut == 0) break;
                timeOut--;
            }
            // Time out!
            if(timeOut == 0) break;
            fifo_cnt = UART_TX_FIFO_SIZE;
            while (fifo_cnt && bToSend){
                UART_SendByte(UARTx, (*pChar++));
                fifo_cnt--;
                bToSend--;
                bSent++;
            }
        }
    }
    // None blocking mode
    else {
        bSent = 0;
        while (bToSend) {
            if (!(UARTx->LSR & UART_LSR_THRE)){
                break;
            }
            fifo_cnt = UART_TX_FIFO_SIZE;
            while (fifo_cnt && bToSend) {
                UART_SendByte(UARTx, (*pChar++));
                bToSend--;
                fifo_cnt--;
                bSent++;
            }
        }
    }
    return bSent;
}
uint32_t UART_Receive(LPC_UART_TypeDef *UARTx, uint8_t *rxbuf, \
        uint32_t buflen, TRANSFER_BLOCK_Type flag)
{
    uint32_t bToRecv, bRecv, timeOut;
    uint8_t *pChar = rxbuf;

    bToRecv = buflen;

    // Blocking mode
    if (flag == BLOCKING) {
        bRecv = 0;
        while (bToRecv){
            timeOut = UART_BLOCKING_TIMEOUT;
            while (!(UARTx->LSR & UART_LSR_RDR)){
                if (timeOut == 0) break;
                timeOut--;
            }
            // Time out!
            if(timeOut == 0) break;
            // Get data from the buffer
            (*pChar++) = UART_ReceiveByte(UARTx);
            bToRecv--;
            bRecv++;
        }
    }
    // None blocking mode
    else {
        bRecv = 0;
        while (bToRecv) {
            if (!(UARTx->LSR & UART_LSR_RDR)) {
                break;
            } else {
                (*pChar++) = UART_ReceiveByte(UARTx);
                bRecv++;
                bToRecv--;
            }
        }
    }
    return bRecv;
}

UART TX 和 RX 功能:

uint32_t UARTSend(LPC_UART_TypeDef *UARTPort, uint8_t *txbuf, uint8_t buflen)
{
    uint8_t *data = (uint8_t *) txbuf;
    uint32_t bytes = 0;

    UART_IntConfig(UARTPort, UART_INTCFG_THRE, DISABLE);

    while ((buflen > 0) && (!__BUF_IS_FULL(rb.tx_head, rb.tx_tail)))
    {
        /* Write data from buffer into ring buffer */
        rb.tx[rb.tx_head] = *data;
        data++;

        /* Increment head pointer */
        __BUF_INCR(rb.tx_head);

        bytes++;
        buflen--;
    }

    if (TxIntStat == RESET) {
        UART_IntTransmit();
    }
    else {
        UART_IntConfig(UARTPort, UART_INTCFG_THRE, ENABLE);
    }

    return bytes;
}

uint32_t UARTReceive(LPC_UART_TypeDef *UARTPort, uint8_t *rxbuf, uint8_t buflen)
{
    uint8_t *data = (uint8_t *) rxbuf;
    uint32_t bytes = 0;

    UART_IntConfig(UARTPort, UART_INTCFG_RBR, DISABLE);


    while ((buflen > 0) && (!(__BUF_IS_EMPTY(rb.rx_head, rb.rx_tail))))
    {
        /* Read data from ring buffer into user buffer */
        *data = rb.rx[rb.rx_tail];
        data++;

        /* Update tail pointer */
        __BUF_INCR(rb.rx_tail);

        /* Increment data count and decrement buffer size count */
        bytes++;
        buflen--;
    }
    UART_IntConfig(UARTPort, UART_INTCFG_RBR, ENABLE);
    return bytes;
}

主要功能

void main(){

uint32_t idx=0, len[enter link description here][1]=0;
    __IO FlagStatus exitflag;
    uint8_t buffer[100]

// reset exit flag
    exitflag = RESET;
while (exitflag == RESET)
    {
        len = 0;
        while (len == 0)
        {
            len = UARTReceive((LPC_UART_TypeDef *)LPC_UART0, buffer, sizeof(buffer));
        }
        idx = 0;
        while (idx < len)
        {
          UARTSend((LPC_UART_TypeDef *)LPC_UART0, &buffer[idx], 1);
          idx++;
        }
    }
}

还观察到读取 .txt 文件时不会丢失任何字节。仅在读取 .bin 文件时出现问题。

请告诉我哪里出了问题。