Serial communication with Infineon C167 (Tasking Compiler)

Hi.

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 interrupt(42) serial_TX_interrupt(void) // Interrupt Routine TxD { }

void interrupt(43) serial_RX_interrupt(void) // Interrupt Routine RxD { }

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);

// S0RIR = 1; // Forcing interrupts // S0TIR = 1;

} }

Reply to
Howard
Loading thread data ...

contact snipped-for-privacy@altium.com

-- with kind regards

--

----------------------------------------- Jan Homuth Senior Application Engineer Technical Support , Embedded Tools

Altium - Making Electronics Design Easier

Altium Europe GmbH Technologiepark Karlsruhe Alber-Nestler Str. 7 D-76131 Karlsruhe Phone: +49 721 8244 310 Fax: +49 721 8244 320

E-Mail: snipped-for-privacy@altium.com WWW:

formatting link

----------------------------------------- Howard schrieb in im Newsbeitrag: snipped-for-privacy@posting.google.com...

Reply to
Jan Homuth

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?

Reply to
Gary Kato

Hello Howard,

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.

I hope this helps, Tankred.

Reply to
Tankred Mueller

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.

=================== SNIP SNIP =================== /* serio.c */

/* * Version : @(#)serio.c 1.11 */

/**************************************************************************

*
  • *
** FILE : serio.c * *
  • *
** 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. * *
  • *
** Copyright 1996-2003 Altium BV * *
  • *
**************************************************************************/ #include

#define REG166_NOADC /* exclude ADC SFRs */ #define REG166_NOCAPCOM /* exclude CAPCOM SFRs */ #define REG166_NOCPU /* exclude CPU SFRs */ #define REG166_NOPEC /* exclude PEC SFRs */ #define REG166_NOTIMER /* exclude timer SFRs */ #include

#include "serio.h"

/* S0/1 port: * 8 bit, asynchronuous operation, one stopbit, * receive enable, no parity/frame/overrun check * baud rate generator enable */ #define SXCON_MODE 0x8011 #define FREQUENCY 19.6608 /* Frequency 19.6608 MHz */ #define BAUDRATE 19200 /* Baudrate 19200 */

void init_serio( void ) { _bfld( DP3, MSK_TDX_RDX, DP3_TDX_RDX ); /* direction bits */ _putbit( 1, P3, P3_TXD ); /* enable TXD0/TXD1 output */ SXBG = RELOAD_VALUE; SXTIC = 0; /* clear errorflags */ SXRIC = 0; SXEIC = 0; SXTIR = 1; SXCON = SXCON_MODE; }

/* * 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 */ }

/*************************************************************************

  • *
  • DESCRIPTION : Reads a block of characters from the given stream *
  • returns nr of read characters *
  • *
*************************************************************************/

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; }

return( cnt ); }

/*************************************************************************

  • *
  • DESCRIPTION : Write a block of data to the given file *
  • As a working example, this routine just calls the low *
  • level routine to write one character, but a faster *
  • implementation is often possible. *
  • returns 0 on success, nonzero on error *
  • *
  • This routine should be customised. *
  • *
*************************************************************************/

size_t _write( int fd, char * base, size_t size ) { size_t cnt = 0;

for( ; size--; base++,cnt++ ) { /* Each character must be correctly written */ if( _iowrite( *base, fd ) != *base ) break; } return( cnt ); /* nr of characters correctly written */ }

/* EOF serio.c*/

/* serio.h */ /* * Version : @(#)serio.h 1.10 */

/**************************************************************************

*
  • *
** FILE : serio.h * *
  • *
** DESCRIPTION : Include file with prototypes for "serio.c" * *
  • *
** Copyright 1996-2003 Altium BV * *
  • *
**************************************************************************/

#ifndef SERIO_INC

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 );

#define RELOAD_VALUE ( ((FREQUENCY * 1E6) / (32UL * BAUDRATE)) - 1 )

#ifdef SER_PORT_1 #define DP3_TDX_RDX 0x0100 /* TDX1 = output, RDX1 = input */ #define MSK_TDX_RDX 0x0300 /* DP3.9= DRXD1, DP3.8 = DTXD1 */ #define P3_TXD 8 /* P3.8 = TXD1 */ #define SXBG S1BG /* baud rate generator/reload register */ #define SXTBUF S1TBUF /* transmit buffer register (write only)*/ #define SXRBUF S1RBUF /* receive buffer register (read only) */ #define SXCON S1CON /* control register */ #define SXTIC S1TIC /* transmit interrupt control register */ #define SXRIC S1RIC /* receive interrupt control register */ #define SXEIC S1EIC /* error interrupt control register */ #define SXEIR S1EIR /* error interrupt request flag */ #define SXRIR S1RIR /* receive interrupt request flag */ #define SXTIR S1TIR /* transmit interrupt request flag */ #define SXFE S1FE /* framing error flag */ #define SXPE S1PE /* parity error flag */ #else #define P3_TXD 10 /* P3.10 = TXD1 */ #define DP3_TDX_RDX 0x0400 /* TDX0 = output, RDX0 = input */ #define MSK_TDX_RDX 0x0C00 /* DP3.11= DRXD1, DP10.8= DTXD1 */ #define SXBG S0BG /* baud rate generator/reload register */ #define SXTBUF S0TBUF /* transmit buffer register (write only)*/ #define SXRBUF S0RBUF /* receive buffer register (read only) */ #define SXCON S0CON /* control register */ #define SXTIC S0TIC /* transmit interrupt control register */ #define SXRIC S0RIC /* receive interrupt control register */ #define SXEIC S0EIC /* error interrupt control register */ #define SXEIR S0EIR /* error interrupt request flag */ #define SXRIR S0RIR /* receive interrupt request flag */ #define SXTIR S0TIR /* transmit interrupt request flag */ #define SXFE S0FE /* framing error flag */ #define SXPE S0PE /* parity error flag */ #endif

#define SERIO_INC #endif

/* EOF serio.h*/

/* testio.c */ /* * Version : @(#)testio.c 1.10 */

/**************************************************************************

*
  • *
** FILE : testio.c * *
  • *
** 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...

Reply to
Jan Homuth
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.

Reply to
Janvi

Hi.

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.

Howard

Reply to
Howard

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.

Thank you for you time.

Howard

Reply to
Howard

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.