- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
}
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem turns out to be related to the sdcc compiler where other people have also reported similar problems with other interrupts. I have in the beginning suggested that it is a memory management problem. It turns out not to be true after spending some time analyzing the generated hex file and assembly files. To solve the problem ES0 cannot be set in the initialization part TD_Init( ). For the example covered in application note AN58764 I postponed setting ES0 till the host writes to EP1OUT which causes the interrupt ISR_Ep1out to kick in and in that subroutine I activate ES0 with the following code snippet
if(Initilization==1){ //only do it once
ES0=1;
PS0 = 0;
TI = 1;
RI = 0;
SYNCDELAY;
Initilization=0;
}
One can also perhaps set ES0 in TD_Poll( ) after checking the appropriate status registers.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Apologies for the delay in my response.
The linker script file is generated when you build your project with extension .map.
Can you also try increasing the <value> in the linker command line.
As pointed out by you, it appears to be a memory issue only.
Regards,
Mallika
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The problem turns out to be related to the sdcc compiler where other people have also reported similar problems with other interrupts. I have in the beginning suggested that it is a memory management problem. It turns out not to be true after spending some time analyzing the generated hex file and assembly files. To solve the problem ES0 cannot be set in the initialization part TD_Init( ). For the example covered in application note AN58764 I postponed setting ES0 till the host writes to EP1OUT which causes the interrupt ISR_Ep1out to kick in and in that subroutine I activate ES0 with the following code snippet
if(Initilization==1){ //only do it once
ES0=1;
PS0 = 0;
TI = 1;
RI = 0;
SYNCDELAY;
Initilization=0;
}
One can also perhaps set ES0 in TD_Poll( ) after checking the appropriate status registers.