We are having a prosject at school, and are currently testing the Infineon C167 µC with Tasking EDE compiler (C). But we get some problems using the serial interface. I think the initialization of the registers and so on actually are correct. This because we've tried to force both receive- and transmit-interrupts by setting those flags, and made the interrupt routines to give out different LED-blinks on a parallel port pin (different blinking depending on which routine that is present). This works. The idea of the program is to receive (constantly) a character from hypeterminal, and then send it back to hyperterminal again (so that we get familiar with the basic intstructions). There must be something wrong with the line "c=getchar()" I guess? I've read the discussions that are here on the google-groups, but I can't find the solutions there. Could anyone help?
thanks.
Howard
The code:
// Asynchronous Serial Interface
#include #include
#define BAUDRATE 19200 // Baudrate 19200 bps #define CPU_FREQUENCY 20 // Frequency (MHz) #define RELOAD_VALUE (((CPU_FREQUENCY * 1E6)/(32UL * BAUDRATE))-1) // Value to be loaded into baudrate-generator
void serial_initialisation(void) { S0BG = RELOAD_VALUE; // Serial port 0 baudrate generator reload register DP3 |= 0x0400; // Setting TxD to output DP3 &= 0xF7FF; // Setting RxD to input P3 |= 0x0400; // Setting TxD high S0CON = 0x8011; /* Serial port 0 control register Baudrate generator enabled Standard transmit/receive mode Divide clock by reload-value + constant (depending on mode) Even parity (parity bit set on odd number of '1's in data) Overrun Error Flag cleared Framing Error Flag cleared Parity Error Flag cleared Ignore overrun errors Ignore framing errors Ignore parity Receiver enabled One stop bit 8-bit data, async. operation */
S0RIC = 0x0044; /* Serial port 0 receive interrupt control register Interrupt enabled Interrupt level 1 */
S0TIC = 0x0048; /* Serial port 0 transmit interrupt control register Interrupt enabled Interrupt level 2 */ }
void main(void) { char c; serial_initialisation(); // Initializes the serial communication DP2=0xFFFF; P2=0xFFFF; IEN=1; // Global interrupt enable while(1) { char c; c=getchar(); printf("%c",c);
One of the things about embedded systems is that they can be very different from each other, even if they use the same microcontroller. You may have to change the library code for getchar (or whatever getchar uses) to use the serial port you want.
Have you followed your code's execution in a debugger to see what is actually happening?
I worked with C165/Tasking some time ago, maybe I can help you in this case...
I once had a problem with the initialisation of the serial interface. Please check your code if you do this correctly (an example is given in the processors manual).
You can try to work without getchar(), write directly to the buffers (transmit/receive) instead.
O.k., here is the answer to all who are interested in C16x using TASKING: (taken from the C166/examples/IO directory that is also available with the demo version)
It is a simple polled serial IO application that is implemented for the C16x (i.e. C161,164,165,167 extended core CPU) (The XC16x implementation looks a bit different) The example also shows how to utilize user low-level routines with the ANSI I/O system of the ANSI runtime library.
** DESCRIPTION : Implementation of _ioread() and _iowrite() *
** using the low level I/O functions getch(), putch(), *
** kbhit() and init_serio() working with serial *** channel 0 or channel 1 of the C166. *
** Default is serial channel 0 used for I/O. *
** If serial channel 1 is wanted for I/O compile *
** "serio.c" with the -DSER_PORT_1 option. **
/* * Read character from serial channel */ int getch( void ) { int c = EOF;
if ( SXEIR ) { SXPE = 0; SXFE = 0; SXEIR = 0; SXRIR = 0; } else if ( SXRIR ) { c = SXRBUF & 0x7F; SXRIR = 0; } return ( c ); }
/* * Return 1 if character available, otherwise 0 */ int kbhit( void ) { if ( SXRIR ) return ( 1 ); return ( 0 ); }
/* * Write character to serial channel */ int putch( int c ) { while ( ! SXTIR ) ; SXTIR = 0; SXTBUF = c; return ( c ); }
int _ioread( int fd ) { /* At this point, it is known that 'fin' is a file opened for */ /* reading, and is not in error yet. */ /* This routine should read the input for the given filehandle */ /* (in the standard version only 'stdin') from the required */ /* hardware. */ /* Whenever an error occurs, 'EOF' should be returned */ /* and fin->_flag should be set to the proper error value */ /* i.e. _IOEOF on end of FILE */ /* _IOERR on any other error */ /* Note that when a read is done on 'stdin', this routine */ /* should do the scanning, and whenever neccessary, do the */ /* echoing to stdout */
int c = EOF;
if ( fd == 0 ) { /* * Assume terminal sending either CR or CRLF. Allow * only LF as valid delimiter, so translate CR into LF * and ignore received LF's */ do /* blocking read from serial channel 0 */ { c = getch(); /* without echo */ if ( c == 0x0a ) /* LF */ c = EOF; /* ignore it */ else if ( c == 0x0d ) /* CR */ c = 0x0a; /* turn into LF */ } while ( c < 0 );
/* * when reading 'stdin', echo to 'stdout' * performing LF ==> CR-LF translation */ _iowrite( c, 1 ); } return( c ); /* return read character on succes */ }
int _iowrite( int c, int fd ) { /* At this point, it is known that 'fout' is a file opened for */ /* writing, and is not in error yet. */ /* This routine should write the output for the given filehandle*/ /* (in the standard version only 'stdout' or 'stderr') */ /* to the required hardware. */ /* Whenever an error occurs, 'EOF' should be returned */ /* and fout->_flag should be set to the proper error value */ /* i.e. _IOEOF on end of FILE */ /* _IOERR on any other error */
if ( fd == 1 || fd == 2 ) { if ( c == '\n' ) putch( '\r' ); putch( c ); }
return( c ); /* return written character on success */ }
size_t _read( int fd, char * base, size_t size ) { int c; size_t cnt = 0;
/* At this point, it is known that 'fin' is a file opened for */ /* reading, and is not in error yet. */ /* This routine should read the input for the given filehandle */ /* from the required hardware. */ /* when nothing is read, '0' should be returned, meaning EOF */ /* is found */ /* On any other error, the routine should return non zero */ /* Note that when a read is done on 'stdin', this routine */ /* should do the scanning, and whenever neccessary, do the */ /* echoing to stdout */
for( ; size; size--,cnt++ ) { /* _ioread will echo to stdout when neccessary */ if( (c = _ioread( fd )) == EOF ) break; /* Nothing more read */ *base++ = c; }
for( ; size--; base++,cnt++ ) { /* Each character must be correctly written */ if( _iowrite( *base, fd ) != *base ) break; } return( cnt ); /* nr of characters correctly written */ }
void init_serio ( void ); int getch ( void ); int kbhit ( void ); int putch ( int c ); int _ioread ( int fd ); int _iowrite ( int c, int fd ); size_t _read ( int fd, char * base, size_t size ); size_t _write ( int fd, char * base, size_t size );
** DESCRIPTION : Program to test _ioread() and _iowrite() *
** implementation. If used with serial I/O, compile *
** this file using the -DSERIAL option. Compile the *** file serio.c using the correct memory model and *
** link serio.obj with the application. **
*
** If used with CrossView Pro File System Simulation, *
** omit the -DSERIAL option when compiling this file. **
*
** Copyright 1996-2003 Altium BV
*
*
*
**************************************************************************/ #include #ifdef SERIAL #include "serio.h" #endif
#define MXLINE 80 static char line[ MXLINE ];
void main( void ) { char c; int i; long l; int yn = 'y';
#ifdef SERIAL init_serio(); #endif
do { printf( "\nPlease enter a (decimal) number : " ); fgets( line, MXLINE, stdin ); if ( sscanf( line, "%ld", &l ) != 1 ) { printf( "Invalid input ...\n" ); continue; } printf( "Number is : %ld\n", l );
printf( "\nPlease enter characters : " ); for ( i = 0; (i < MXLINE-1) && (c = getchar()) != '\n'; i++ ) { line[i] = c; } line[i] = '\0'; printf( "Characters are : \"%s\"\n", line );
printf( "\nAgain (y/n) ? " ); yn = getchar(); getchar(); // read '\n' } while ( yn == 'y' );
printf( "End of program.\n" ); }
/* EOF testio.c */
=================== SNIP SNIP ===================
grtnx /jan
Howard schrieb in im Newsbeitrag: snipped-for-privacy@posting.google.com...
2 weeks ago I tried to write the exactly same program with a few assembly lines for the XC164 demo board from Infineon. (See the thread Infineon XC164 setup from 16/1 down in this group)
Soon I found out the complete uC runs with diffrent clock speed and only the baudrate is diffrent and very odd from what I expect. This way, the PC was not able to handle incoming bytes and the other way round.
(using whatever the Compiler is, I wrote assembly)
The XC16x architecture is a multiscalar CPU running with up to 40 MC and zero cycle jumps. My final bug was a false setup of the clock dividers but after many days I recently understood why I calculated the speed wrong.
For 40 Mhz I expect a single cycle instruction in 25nS. The false assumption was single word = single cycle. Therefore a bitset / bitclear instruction sequence was expected to make a 25 nS pulse at the IO pin to my scope. What I saw were always 175nS why I assumed false clock frequency. But this is really ok if calculating correct.
To run the XC16x from internal flash you need one wait cycle at 40 MC becouse the flash access time is 50nS. Now the instruction needs obviously 7 clock cycles to execute by the microprogram sequencer:
2 cycles to fetch the 16 bit instruction word,
2 cycles to fetch the 16 bit operand word
1 cycle to modify the bit
2 cycles to write the result back.
This makes 7 * 25 nS = 175 nS what can be shortened to
4 cycles = 100nS if the code runs in internal SRAM without any wait cycles. Becouse the next bitclear instruction uses the same IO bit, the parallel executing queue is flushed, The state of the bit what has been changed by the previous instruction mades following operand read false becouse the RD was too early. From this reason, the next assembly instruction also occupies 7 clock cycles again.
This was clearly not the expected result becouse a 8 bit HC08 running at 8 Mhz can do a bit set or bit clear in one clock cycle faster within 125 nS using single bit latch lines. However, the XC16x has other benefits and if you consider using it, read the 1200 pages manual carefully before doing the decision but for school and education I would not take that beast.
Actually I've tried that. So therefore I'm pretty sure that the initialization is right. The interrupt routines for the TxD and RxD don't need any content, since the flags are reset during these routines automaticly. But to give myself an indication of which routine that was actually running, I initialized a LED to blink. If the TxD_irq routine was running, it would blink once and slow. If the RxD_irq was running, it would blink twice and faster. The TxD interrupt works - writing directly into the TxD buffer. With the RxD I had to do it different, since the RxD buffer is a read-only. Therefore I had to set the RxD_irq-flag. This worked too. So in the whole I suppose the main code works, but I get problems when i use these higher-level commands like getchar() and printf(). Jan Homuth (Altium) told me that I maybe had to implement my own lower-level function equivalent to these already meantioned. I guess I'll have to do that. But I've implemented serial interface with Atmel µC, and that could be done as simple as in the code I attached earlier. Thanks for the help.
What is meant by "changing the library code for getchar"? Would I have to edit the code that implement getchar, in some of the header-files? I've tried to follow the code with a debugger, but I guess I'm still a newbie on the Tasking environment. Though the debugger/simulator has some limitations on the number of executions, and I've had some problems with that so far.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.