王不财 2024-08-28 16:44 采纳率: 33.3%
浏览 7

CY7C68013A-56PVXI使用内部时钟,通过修改Bulkloop固件发现会固件会陷入死循环卡死EZUSB_WaitForEEPROMWrite函数

CY7C68013A-56PVXI芯片想要使用内部时钟来与FPGA交互,但是我通过修改Bulkloop固件发现,这个固件中的接口会卡死,代码如下


#pragma NOIV               // Do not generate interrupt vectors

#include "fx2.h"
#include "fx2regs.h"
#include "syncdly.h"            // SYNCDELAY macro

extern BOOL GotSUD;             // Received setup data flag
extern BOOL Sleep;
extern BOOL Rwuen;
extern BOOL Selfpwr;

BYTE Configuration;             // Current configuration
BYTE AlternateSetting;          // Alternate settings

int start_7_seg_display = 0;  //This variable is used to start 7-seg display after the FX2LP is enumerated.
void EZUSB_INITI2C();

#define VR_NAKALL_ON    0xD0
#define VR_NAKALL_OFF   0xD1
#define bmEP2IRQ        0x10
#define bmEP6IRQ        0x40    
// 7-segment readout
#define LED_ADDR        0x21

// Provide access to FX2LP DVK LED's D2-D5. An LED is turned 
// on or off by doing a read to one of these memory addresses.  
xdata volatile BYTE D5OFF _at_ 0xB000;
xdata volatile BYTE D4OFF _at_ 0xA000;
xdata volatile BYTE D3OFF _at_ 0x9000;
xdata volatile BYTE D2OFF _at_ 0x8000;
xdata volatile BYTE D5ON  _at_ 0xB800;
xdata volatile BYTE D4ON  _at_ 0xA800;
xdata volatile BYTE D3ON  _at_ 0x9800;
xdata volatile BYTE D2ON  _at_ 0x8800;

int LEDCounter = 0;            // Activity LED blink period
BYTE inblink = 0x00;        // IN transfer LED time constant
BYTE outblink = 0x00;        // OUT transfer LED time constant

// 7-segment readout digits 0-F 
BYTE xdata Digit[] = { 0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x98, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e };

//-----------------------------------------------------------------------------
// Task Dispatcher hooks
//   The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------

void TD_Init(void)             // Called once at startup
{
   BYTE dum;                    // For the LEDS
   CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ;    // 48 MHz CPU clock
   
   
   // Turn off all 4 LEDS
   dum = D2OFF;
   dum = D3OFF;
   dum = D4OFF;
   dum = D5OFF;

// EP2CFG & EP6CFG configure our two endpoints, EP2-OUT and EP6-IN
// b7:        Valid
// b6:        DIR (0=OUT, 1=IN)
// b[5:4]    Type (01=ISO, 10=BULK, 11=INT)
// b3:        Size (0=512, 1=1024 bytes)
// b2:        0
// b[1:0]    Buffering (00=quad, 10=double, 11=triple)        
//

  EP2CFG = 0xA2;    // Valid, BULK-OUT, 512 byte buffer, double-buffered
  SYNCDELAY;        // Some regs take longer to update, see TRM Section 15.14.                    
  EP6CFG = 0xE2;    // Valid, BULK-IN, 512 byte buffer, double-buffered
  SYNCDELAY;                    

  // OUT endpoints do not come up armed
  // Since the endpoint is double buffered we must write dummy byte counts twice
  EP2BCL = 0x80;      // arm EP2OUT by writing byte count w/skip.
  SYNCDELAY;                    
  EP2BCL = 0x80;    // again
  SYNCDELAY;                    
  // enable dual autopointer feature
  AUTOPTRSETUP |= 0x01;

  USBIE |= bmSOF;                // Enable the SOF IRQ to serve as LED timers
  EPIE = bmEP6IRQ | bmEP2IRQ;    // Enable EP6 and EP2 Interrupts to turn on transfer LEDS
}

void TD_Poll(void)              // Called repeatedly while the device is idle
{
  WORD i;
  WORD count;
//  BYTE dummy_LED2;        // ***For the LED
  BYTE waiting_inpkts;

#ifdef ENABLE_7_SEG_DISPLAY
if(start_7_seg_display)
{
// update 7-seg readout with number of IN packets waiting for transfer to the host
  waiting_inpkts = (EP6CS & 0xF0)>>4;
  EZUSB_WriteI2C(LED_ADDR, 0x01, &(Digit[waiting_inpkts]));
  EZUSB_WaitForEEPROMWrite(LED_ADDR);
}
#endif

// Transfer EP6-OUT buffer to EP2-IN buffer when there is a packet in one of the EP6-OUT buffers, AND
// there is an available EP2-IN buffer. The FIFO status flags update after full packets are transferred.
// Therefore EP2-OUT "Not Empty" means a packet is available, and "EP6-IN "Not Full" means there is an
// available buffer. Using the flags this way handles any packet size and takes multiple buffering
// into account.   

    if(!(EP2468STAT & bmEP2EMPTY))        // Is EP2-OUT buffer not empty (has at least one packet)?
    {
        if(!(EP2468STAT & bmEP6FULL))    // YES: Is EP6-IN buffer not full (room for at least 1 pkt)?
         { 
        APTR1H = MSB( &EP2FIFOBUF );
        APTR1L = LSB( &EP2FIFOBUF );
        AUTOPTRH2 = MSB( &EP6FIFOBUF );
        AUTOPTRL2 = LSB( &EP6FIFOBUF );

        count = (EP2BCH << 8) + EP2BCL;

        // loop EP2OUT buffer data to EP6IN
        for( i = 0; i < count; i++ )
        {
            EXTAUTODAT2 = EXTAUTODAT1;    // Autopointers make block transfers easy...
        }
        EP6BCH = EP2BCH;        // Send the same number of bytes as received  
        SYNCDELAY;  
        EP6BCL = EP2BCL;        // arm EP6IN
        SYNCDELAY;                    
        EP2BCL = 0x80;          // arm EP2OUT
     }
  }
}

BOOL TD_Suspend(void)          // Called before the device goes into suspend mode
{
   return(TRUE);
}

BOOL TD_Resume(void)          // Called after the device resumes
{
   return(TRUE);
}

//-----------------------------------------------------------------------------
// Device Request hooks
//   The following hooks are called by the end point 0 device request parser.
//-----------------------------------------------------------------------------

BOOL DR_GetDescriptor(void)
{
   return(TRUE);
}

BOOL DR_SetConfiguration(void)   // Called when a Set Configuration command is received
{
   Configuration = SETUPDAT[2];
#ifdef ENABLE_7_SEG_DISPLAY

  EZUSB_INITI2C();                // for the 7-seg readout
  start_7_seg_display = 1;

#endif
   return(TRUE);            // Handled by user code
}

BOOL DR_GetConfiguration(void)   // Called when a Get Configuration command is received
{
   EP0BUF[0] = Configuration;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_SetInterface(void)       // Called when a Set Interface command is received
{
   AlternateSetting = SETUPDAT[2];
   return(TRUE);            // Handled by user code
}

BOOL DR_GetInterface(void)       // Called when a Set Interface command is received
{
   EP0BUF[0] = AlternateSetting;
   EP0BCH = 0;
   EP0BCL = 1;
   return(TRUE);            // Handled by user code
}

BOOL DR_GetStatus(void)
{
   return(TRUE);
}

BOOL DR_ClearFeature(void)
{
   return(TRUE);
}

BOOL DR_SetFeature(void)
{
   return(TRUE);
}

BOOL DR_VendorCmnd(void)
{
  return(TRUE);
}

//-----------------------------------------------------------------------------
// USB Interrupt Handlers
//   The following functions are called by the USB interrupt jump table.
//-----------------------------------------------------------------------------

// Setup Data Available Interrupt Handler
void ISR_Sudav(void) interrupt 0
{
   GotSUD = TRUE;            // Set flag
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUDAV;         // Clear SUDAV IRQ
}

// Setup Token Interrupt Handler
void ISR_Sutok(void) interrupt 0
{
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUTOK;         // Clear SUTOK IRQ
}

void ISR_Sof(void) interrupt 0
{
   BYTE dum;
   BYTE Led_Flag = 0;
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSOF;              // Clear SOF IRQ

       if(--inblink == 0)            // IN and OUT LED extinguishers
        dum = D2OFF;
    if(--outblink == 0)    
        dum = D3OFF;

   // *** Blink the LED with one second period. At High-Speed the
   // microSOF's occur every 125 usec. Flash the LED 8 times per sec for High-Speed,
   // 1 per sec for Full-Speed. 

   LEDCounter++;
   if(LEDCounter > 1000)
        LEDCounter = 0;        // 1 sec period
           if(LEDCounter < 500)
            dum = D5OFF;
        else
            dum = D5ON;
}

void ISR_Ures(void) interrupt 0
{
   // whenever we get a USB reset, we should revert to full speed mode
   pConfigDscr = pFullSpeedConfigDscr;
   ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
   pOtherConfigDscr = pHighSpeedConfigDscr;
   ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;

   EZUSB_IRQ_CLEAR();
   USBIRQ = bmURES;         // Clear URES IRQ
}

void ISR_Susp(void) interrupt 0
{
   Sleep = TRUE;
   EZUSB_IRQ_CLEAR();
   USBIRQ = bmSUSP;
}

void ISR_Highspeed(void) interrupt 0
{
   if (EZUSB_HIGHSPEED())
   {
      pConfigDscr = pHighSpeedConfigDscr;
      ((CONFIGDSCR xdata *) pConfigDscr)->type = CONFIG_DSCR;
      pOtherConfigDscr = pFullSpeedConfigDscr;
      ((CONFIGDSCR xdata *) pOtherConfigDscr)->type = OTHERSPEED_DSCR;
   }

   EZUSB_IRQ_CLEAR();
   USBIRQ = bmHSGRANT;
}
void ISR_Ep0ack(void) interrupt 0
{
}
void ISR_Stub(void) interrupt 0
{
}
void ISR_Ep0in(void) interrupt 0
{
}
void ISR_Ep0out(void) interrupt 0
{
}
void ISR_Ep1in(void) interrupt 0
{
}
void ISR_Ep1out(void) interrupt 0
{
}
void ISR_Ep2inout(void) interrupt 0
{
    BYTE dum;       
    EZUSB_IRQ_CLEAR();
       EPIRQ = bmEP2IRQ;         // Clear IRQ
    dum = D3ON;
    outblink = 200;
}
void ISR_Ep4inout(void) interrupt 0
{
}
void ISR_Ep6inout(void) interrupt 0
{
    BYTE dum;
    EZUSB_IRQ_CLEAR();
       EPIRQ = bmEP6IRQ;         // Clear IRQ     dum = D2OFF;
    dum = D2ON;
    inblink = 200;
}
void ISR_Ep8inout(void) interrupt 0
{
}
void ISR_Ibn(void) interrupt 0
{
}
void ISR_Ep0pingnak(void) interrupt 0
{
}
void ISR_Ep1pingnak(void) interrupt 0
{
}
void ISR_Ep2pingnak(void) interrupt 0
{
}
void ISR_Ep4pingnak(void) interrupt 0
{
}
void ISR_Ep6pingnak(void) interrupt 0
{
}
void ISR_Ep8pingnak(void) interrupt 0
{
}
void ISR_Errorlimit(void) interrupt 0
{
}
void ISR_Ep2piderror(void) interrupt 0
{
}
void ISR_Ep4piderror(void) interrupt 0
{
}
void ISR_Ep6piderror(void) interrupt 0
{
}
void ISR_Ep8piderror(void) interrupt 0
{
}
void ISR_Ep2pflag(void) interrupt 0
{
}
void ISR_Ep4pflag(void) interrupt 0
{
}
void ISR_Ep6pflag(void) interrupt 0
{
}
void ISR_Ep8pflag(void) interrupt 0
{
}
void ISR_Ep2eflag(void) interrupt 0
{
}
void ISR_Ep4eflag(void) interrupt 0
{
}
void ISR_Ep6eflag(void) interrupt 0
{
}
void ISR_Ep8eflag(void) interrupt 0
{
}
void ISR_Ep2fflag(void) interrupt 0
{
}
void ISR_Ep4fflag(void) interrupt 0
{
}
void ISR_Ep6fflag(void) interrupt 0
{
}
void ISR_Ep8fflag(void) interrupt 0
{
}
void ISR_GpifComplete(void) interrupt 0
{
}
void ISR_GpifWaveform(void) interrupt 0
{
}


在TD_Poll函数中的这段代码


#ifdef ENABLE_7_SEG_DISPLAY
if(start_7_seg_display)
{
// update 7-seg readout with number of IN packets waiting for transfer to the host
  waiting_inpkts = (EP6CS & 0xF0)>>4;
  EZUSB_WriteI2C(LED_ADDR, 0x01, &(Digit[waiting_inpkts]));
  EZUSB_WaitForEEPROMWrite(LED_ADDR);
}
#endif

这段代码中的EZUSB_WaitForEEPROMWrite函数,如果删除这个函数,这个固件就不会输出内部时钟,如果保留固件就会卡死,想请问一下怎能解决。

  • 写回答

1条回答 默认 最新

  • 小ᶻ☡꙳ᵃⁱᵍᶜ꙳ 优质创作者: 人工智能技术领域 2024-09-03 18:49
    关注

    该回答引用自GPT-4o,由博主小ᶻZ࿆编写:

    问题分析

    这个问题主要涉及到在使用 CY7C68013A-56PVXI 芯片时,修改 Bulkloop 固件后导致陷入死循环的问题,尤其是在调用 EZUSB_WaitForEEPROMWrite 函数时出现卡死现象。

    原因分析

    EZUSB_WaitForEEPROMWrite 是一个同步函数,它用于等待 EEPROM 的写入操作完成。如果该函数被调用时,系统处于某些不可预见的状态(如 FPGA 内部时钟信号不稳定或出现错误),就可能会导致整个系统陷入死循环。

    解决方案

    1. 检查时钟信号: 确保 FPGA 内部的时钟信号是稳定的,并且在调用该函数时没有被中断或干扰。

    2. 使用异步调用: 如果可能的话,可以尝试使用异步方式来处理 EEPROM 的写操作,这样可以避免因等待操作卡死系统。

    3. 硬件调试: 使用示波器或逻辑分析仪检查信号线,特别是检查时钟信号在操作过程中是否保持正常。

    4. 优化代码逻辑: 检查代码逻辑,特别是调用 EZUSB_WaitForEEPROMWrite 的位置,是否可以在此处添加一些超时机制,防止长期等待导致系统卡死。

    结论

    通过以上几个步骤,应该可以找到并解决导致 Bulkloop 固件陷入死循环的问题。如果问题依然存在,建议联系 Cypress 的技术支持,获得更详细的调试帮助。

    如有帮助,可以采纳一下嘛,谢谢~


    希望这个回答对你有帮助!如果有更多问题,欢迎继续提问。

    评论

报告相同问题?

问题事件

  • 创建了问题 8月28日