We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I've created a little test program that runs fine in the simulator, but causes the hardware (80C390) to reset when a function with multiple long parameters is called. This is with v6.22. Am I missing something obvious? Running in the large memory model in a new project (I.E. all other settings as defaults.)
#include <REG390.H> #include <absacc.h> #include <stdio.h> void wait (void) { /* wait function */ int i; for (i=0;i<20000;i++) { ; } } void Serial0_Initialize(void) { // init serial interface 38400 baud @ 20MHz PCON |= 0x80; /* Double serial port 0 baud rate */ SCON0 = 0x50; /* Async receiver serial port 0 enable */ TMOD |= 0x21; /* Timer 0 16 bits, Timer 1 8 bits with auto reload mode */ TH1 = 0xF8; /* Load MSB of Timer 1 */ CKCON |= 0x10; /* Timer 1 clock select divide by 4 of xtal freq */ TCON = 0x50; /* Timer 0 run enable, Timer 1 run enable */ TI = 1; /* Serial port 0 transmitter interrupt flag set */ } unsigned char xdata* egdBufferGetInt(int buffer, int width, int height, int depth) { unsigned char xdata *curBuf = 0; return curBuf; } unsigned char xdata* egdBufferGet(long buffer, long width, long height, long depth) { unsigned char xdata *curBuf = 0; return curBuf; } long egdDrawInt(unsigned char xdata *buffer, int width, int height) { ; } long egdDraw(unsigned char xdata *buffer, long width, long height) { ; } void main (void) { unsigned char xdata *b; // Initialize serial port 0 Serial0_Initialize(); printf("Serial initialized!\n"); wait(); printf("Trying BufferGetInt...\n"); b=egdBufferGetInt(0, 320, 240, 1); printf("BufferGetInt success\n"); wait(); printf("Trying BufferGet...\n"); b=egdBufferGet(0, 320, 240, 1); printf("BufferGet success\n"); wait(); printf("Trying Draw Int...\n"); egdDrawInt(b, 320, 240); printf("Draw Int success\n"); wait(); printf("Trying Draw...\n"); egdDraw(b, 320, 240); printf("Draw success\n"); wait(); while (1) { printf("Waiting...\n"); wait(); } }
Serial initialized! Trying BufferGetInt... BufferGetInt success Trying BufferGet... erial initialized! Trying BufferGetInt... BufferGetInt success Trying BufferGet... erial initialized! Trying BufferGetInt... BufferGetInt success Trying BufferGet... erial initialized! Trying BufferGetInt... BufferGetInt success Trying BufferGet... erial initialized!
The reset problem is that the C390 has an internal 22 bit address bus and that the long parameter calls "C?LSTKXDATA" which uses a "JMP @A+DPTR" for a pseudo "RET" instruction. The address bits[21:16] are not set correctly for this pseudo "RET" instruction. So this "return" jumps off the end of the code and eventually the micro executes at 0x00000 and then soft reset. This problem could extend to "switch" statements and other C constructs. The bottom line is that the Keil compiler, as far as I know, does not support this chip. If all your addressing needs is less than 16k, you probably need just to set the PDX & AP registers to get things working.
... the C390 has an internal 22 bit address bus and ... the long parameter calls "C?LSTKXDATA" ... uses a "JMP @A+DPTR" for a pseudo "RET" instruction. The address bits[21:16] are not set correctly for this pseudo "RET" instruction. So this "return" jumps off the end of the code and eventually the micro executes at 0x00000 and then soft reset. This is NOT technically accurate. 1. If you check your settings, you will find that the JMP @A+DPTR instruction is used in C?LSTKXDATA ONLY in the 16-bit mode. It is NOT used in the contiguous modes. So, the 22-bit address bus is not used. 2. According to the Dallas Data book: Data Pointer Extended Register 0 This register contains the high-order byte of the 22-bit address (or 23-bit address when CMA=1) when performing operations with Data Pointer 0. This register is ignored when addressing data memory in the 16-bit addressing mode. 3. In CONTIGUOUS mode, the C?LSTKXDATA function uses a RET statement to return from the function call. So, the 22-bus issue is solved there. 4. In the original posting, it is mentioned that the program works OK in the simulator. Since the simulator exactly simulates the instruction set of the 390 in every way, I think that there is some other issue at work here. 5. I have tested this program in ROM(LARGE), CONTIGUOUS: 512K, and CONTIGUOUS: 16M ROM models and it works AOK in the simulator. However, I do not have access to 390 hardware at this time. If some else does, let me know and I can send you my project to test. The last time we had a problem like this involved a government contractor who eventually sent a group of engineers to demonstrate the problem. After we cleaned up the 2.5 volt spikes on VCC, we requested that they buy the marguiritas. They did. :-) Jon
Ths point is that Kevin states that: "The target is a 80C390, but I'm not running in contiguous mode (yet), just in the large memory model." So the C?LSTKXDATA is being emitted.
Ths point is that Kevin states that: "The target is a 80C390, but I'm not running in contiguous mode (yet), just in the large memory model." So the C?LSTKXDATA is being emitted. OK, then what's the problem with the JMP @A+DPTR instruction in 16-bit mode? Jon
Here's a simple program with which Kevin can test the "jmp @a+dptr" instruction. File: Sub.c Options: Generate SRC, Assemble SRC
void PseudoRet( void ) { #pragma asm pop dph pop dpl clr a jmp @a+dptr #pragma endasm }
#include <REG390.H> #include <stdio.h> void Serial0_Initialize(void) { // init serial interface 38400 baud @ 20MHz PCON |= 0x80; /* Double serial port 0 baud rate */ SCON0 = 0x50; /* Async receiver serial port 0 enable */ TMOD |= 0x21; /* Timer 0 16 bits, Timer 1 8 bits with auto reload mode */ TH1 = 0xF8; /* Load MSB of Timer 1 */ CKCON |= 0x10; /* Timer 1 clock select divide by 4 of xtal freq */ TCON = 0x50; /* Timer 0 run enable, Timer 1 run enable */ TI = 1; /* Serial port 0 transmitter interrupt flag set */ } void PseudoRet( void ); void main (void) { Serial0_Initialize(); printf("Serial initialized!\n"); PseudoRet(); printf("Nope, this is not the problem.\n"); while (1) ; }
By the way, if the user is optimizing for speed, the compiler can get massive speed/size impovements by not calling routines like C?LSTKXDATA.
OK, more information. I noticed that our HEX file loader in EPROM is leaving the processor in 22 bit paged mode before jumping to my program in flash. I.E.
TA = 0xAA; TA = 0x55; ACON = 1;
TA = 0xAA; TA = 0x55; ACON = 0;