Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

USB low-full-high speed peripherals Forum Discussions

not_A_quitter
Level 1
Level 1
5 replies posted 10 sign-ins 5 sign-ins

I'v been working on trying to establish serial communication using FX2LP via the virtual com approach as discussed in AN58764. The problem is when I enable the serial port 0 interrupt by setting ES0=1 the device disconnects and does not come back to the USB Control Center after being programed.  A snippet of the code is shown below( the entire code can be found in the attachment).

Since I'm compiling my project using SDCC I'm aware of few issues that have to be taken care of which have to do with  the interrupt vector table not being overwritten. I'v wrote the following command in the Sdcc linker command line:

sdcc --xram-loc 0x3000 --code-size 0x2FFF

to make sure data written into external ram do not corrupt the interrupt vector. I have also made sure that the register XPAGE is in location 92 in the memory by inserting the following line in fx2regs.h

__sfr __at (0x92) _XPAGE; 

In addition,  I have made sure that I'm using a .inf file that is compatible with the virtual com aspect. Yet, I haven't been able to sort out the problem. Any thoughts are appreciated. 

 

#pragma noiv // Do not generate interrupt vectors
//-----------------------------------------------------------------------------
// File: bulkloop.c
// Contents: Hooks required to implement USB peripheral function.
//
// Copyright (c) 2000 Cypress Semiconductor All rights reserved
//-----------------------------------------------------------------------------
#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;


__xdata volatile unsigned char D3ON;
__xdata volatile unsigned char D3OFF;

static int x;
unsigned char duk;
static int bcl,i;


__xdata volatile unsigned char D5ON;
__xdata volatile unsigned char D5OFF;

unsigned char dum;
static int z;

extern __xdata volatile unsigned char LineCode[7];


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

void display_product(void);
void TD_Poll(void);


//-----------------------------------------------------------------------------
// Task Dispatcher hooks
// The following hooks are called by the task dispatcher.
//-----------------------------------------------------------------------------
BOOL DR_SetConfiguration();


BYTE TxByte0,RxByte0;
BYTE TxByte1,RxByte1;

void transmit(void)// Sends data to SBUF0
{
if (!(EP1OUTCS & 0x02))
{

if(i<bcl)
{

SBUF0=EP1OUTBUF[i];
i++;

dum=D5ON;
z^=1;
if (z)
{dum=D5OFF;}
}
else
{
EP1OUTBC = 0x04;// Arms EP1 endpoint
}
}
}


void Serial0Init () // serial UART 0 with Timer 2 in mode 1 or high speed baud rate generator
{

SCON0 = 0x5A; // Set Serial Mode = 1, Recieve enable bit = 1
T2CON = 0x34; // Int1 is detected on falling edge, Enable Timer0, Set Timer overflow Flag

if ((LineCode[0] == 0x60) && (LineCode[1] == 0x09 )) // 2400

{
RCAP2H = 0xFD; // Set TH2 value for timer2
RCAP2L = 0x90; // baud rate is set to 2400 baud
}
else if ((LineCode[0] == 0xC0) && (LineCode[1] == 0x12 )) // 4800

{
RCAP2H = 0xFE; // Set TH2 value for timer2
RCAP2L = 0xC8; // baud rate is set to 4800 baud
}
else if ((LineCode[0] == 0x80) && (LineCode[1] == 0x25 )) // 9600

{
RCAP2H = 0xFF; // Set TH2 value for timer2
RCAP2L = 0x64; // baud rate is set to 9600 baud
}
else if ((LineCode[0] == 0x00) && (LineCode[1] == 0x4B )) // 19200

{
RCAP2H = 0xFF; // Set TH2 value for timer2
RCAP2L = 0xB2; // baud rate is set to 19200 baud
}
else if ((LineCode[0] == 0x80) && (LineCode[1] == 0x70 )) // 28800

{
RCAP2H = 0xFF; // Set TH2 value for timer2
RCAP2L = 0xCC; // baud rate is set to 28800 baud
}
else if ((LineCode[0] == 0x00) && (LineCode[1] == 0x96 )) // 38400

{
RCAP2H = 0xFF; // Set TH2 value for timer2
RCAP2L = 0xD9; // baud rate is set to 38400 baud
}
else if ((LineCode[0] == 0x00) && (LineCode[1] == 0xE1 )) // 57600

{
RCAP2H = 0xFF; // Set TH2 value for timer2
RCAP2L = 0xE6; // baud rate is set to 57600 baud
}

else //if ((LineCode[0] == 0x21) && (LineCode[1] == 0x20 )) // 115200 (LineCode[0] == 0x00) && (LineCode[1] == 0xC2 ))

{
RCAP2L = 0xF3;
RCAP2H = 0xFF;
}

TH2 = RCAP2H; // Upper 8 bit of 16 bit counter to FF
TL2 = RCAP2L; // value of the lower 8 bits of timer set to baud rate

}


void TD_Init(void) // Called once at startup
{


// set the CPU clock to 48MHz
CPUCS = ((CPUCS & ~bmCLKSPD) | bmCLKSPD1) ;

// set the slave FIFO interface to 48MHz
IFCONFIG |= 0x40;
SYNCDELAY;
REVCTL = 0x03;
SYNCDELAY;

 

FIFORESET = 0x80; // activate NAK-ALL to avoid race conditions
SYNCDELAY; // see TRM section 15.14
FIFORESET = 0x08; // reset, FIFO 8
SYNCDELAY; //
FIFORESET = 0x00; // deactivate NAK-ALL
SYNCDELAY;


EP1OUTCFG = 0xA0; // Configure EP1OUT as BULK EP
SYNCDELAY;
EP1INCFG = 0xB0; // Configure EP1IN as BULK IN EP
SYNCDELAY; // see TRM section 15.14
EP2CFG = 0x7F; // Invalid EP
SYNCDELAY;
EP4CFG = 0x7F; // Invalid EP
SYNCDELAY;
EP6CFG = 0x7F; // Invalid EP
SYNCDELAY;


EP8CFG = 0xE0; // Configure EP8 as BULK IN EP
SYNCDELAY;

EP8FIFOCFG = 0x00; // Configure EP8 FIFO in 8-bit Manual Commit mode
SYNCDELAY;
T2CON = 0x34;


EPIE |= bmBIT3 ; // Enable EP1 OUT Endpoint interrupts
AUTOPTRSETUP |= 0x01; // enable dual autopointer feature
Rwuen = TRUE; // Enable remote-wakeup
EP1OUTBC = 0x04;

ES0 = 1; /* enable serial interrupts */
PS0 = 0; /* set serial interrupts to low priority */

TI = 1; /* clear transmit interrupt */
RI = 0; /* clear receiver interrupt */
EA = 1; /* Enable Interrupts */

Serial0Init(); // Initialize the Serial Port 0 for the Communication SCO

 

}

void TD_Poll(void) // Called repeatedly while the device is idle
{

// Serial State Notification that has to be sent periodically to the host

if (!(EP1INCS & 0x02)) // check if EP1IN is available
{
EP1INBUF[0] = 0x0A; // if it is available, then fill the first 10 bytes of the buffer with
EP1INBUF[1] = 0x20; // appropriate data.
EP1INBUF[2] = 0x00;
EP1INBUF[3] = 0x00;
EP1INBUF[4] = 0x00;
EP1INBUF[5] = 0x00;
EP1INBUF[6] = 0x00;
EP1INBUF[7] = 0x02;
EP1INBUF[8] = 0x00;
EP1INBUF[9] = 0x00;
EP1INBC = 10; // manually commit once the buffer is filled
}

// recieving the data from the USB Host and send it out through UART

 

// recieve the data from UART and send it out to the USB Host

 

}

0 Likes
5 Replies
MallikaK_22
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 250 replies posted

Hi,

Could you please let me know how is the device coming up in the device manager?

Also, which driver is it bound to?

Regards,

Mallika

0 Likes

Hi Mallikak- For the following sequence of code lines in TD_Init:

 ES0 = 1; /* enable serial interrupts */
PS0 = 0; /* set serial interrupts to low priority */

TI = 1; /* clear transmit interrupt */
RI = 0; /* clear receiver interrupt */

EA = 1; /* Enable Interrupts */

I do not get any thing back on my device manger once the device is programmed. But if i comment out ES0=1; then I get back a com port connection on my device manger which indicates the device is working properly I guess.  The weird thing is by setting EA to '1' all interrupts are enabled including serial port 0 interrupt and it works fine but if I explicitly set ES0=1; then this problem pops up!!

My feeling is it has to do with the sdcc compiler and the reason is say that is I have the hex file for the same code generated by keil compiler and it works just fine. So I don't  know, could it be the sdcc linker is overriding/overwriting some critical pieces of code over each other or misplacing  them? 

0 Likes
MallikaK_22
Moderator
Moderator
Moderator
250 solutions authored 500 replies posted 250 replies posted

Hi, 

EA is for external access. This pin determines where the 8051 fetches code between addresses 0x0000 and
0x3FFF. If EA = 0 the 8051 fetches this code from its internal RAM. IF EA = 1 the 8051 fetches this code from external memory. Are you talking about this EA?

It seems that some overwriting is happening as you suggested. Can you try increasing the <value> where XREG is placed.

Could you please also share the linker script file for the project.

Regards,

Mallika

0 Likes

I believe EA controls the whole gamut of "interrupts" and "external memory access" (for the 128pin). On page 61, table 4-2 of EZ-USB Technical Reference Manual says the following :  

"EA - Global interrupt enable. Controls masking of all interrupts except USB wakeup (resume). EA = 0 disables all interrupts except USB wakeup. When EA = 1, interrupts are enabled or masked by their individual enable bits."

and It does talk about EA=1 providing access to the external memory for 128 pin package which I am not using(I'm working on 56 and 100 pin only).

With regards to the linker I did not write an elaborate linker script. I just wrote 

sdcc --xram-loc 0x3000 --code-size 0x2FFF

in the linker command line as shown on the attached figure. 

Any further suggestions will be appreciated. 

0 Likes
not_A_quitter
Level 1
Level 1
5 replies posted 10 sign-ins 5 sign-ins

I did a simple hack that solved the problem and it also confirms that it is a memory management issue. What I did in the fx2regs.h file is I changed the IE register allocation from 

__sfr __at 0xA8 IE ;
/* IE */
__sbit __at (0xA8+0) EX0 ;
__sbit __at (0xA8+1) ET0 ;
__sbit __at (0xA8+2) EX1 ;
__sbit __at (0xA8+3) ET1 ;
__sbit __at (0xA8+4) ES0 ;
__sbit __at (0xA8+5) ET2 ;
__sbit __at (0xA8+6) ES1 ;
__sbit __at (0xA8+7) EA ;

to become 

__sfr __at 0xA8 IE ;
/* IE */
__sbit __at (0xA8+0) EX0 ;
__sbit __at (0xA8+1) ET0 ;
__sbit __at (0xA8+2) EX1 ;
__sbit __at (0xA8+3) ET1 ;
__sbit __at (0xA8+6) ES0 ;
__sbit __at (0xA8+5) ET2 ;
__sbit __at (0xA8+4) ES1 ;
__sbit __at (0xA8+7) EA ;

basically I swapped ES0 and ES1 bit locations. 

But what I have done is more of a hack than a good reliable solution. I hope someone else comes up with a better suggestion. 

0 Likes