/* p4_6.c C library Console I/O using UART3 at 9600 Baud * * This program demonstrates the use of C library console I/O. * The functions _write() and _read() are implemented using * UART3Tx() and UART3Rx() for character I/O. * In the _read(), it always reads only a single character. The * received character is echoed and if a '\r' is received, * it is substituted with a '\n' but both characters are echoed. * In _write() and _read(), the file descripter is not checked. All * file I/O's are directed to the console. * * By default, the clock is running at 1 MHz. * * Tested with Atmel Studio 7 v7.0.1006 */ #include "samd21.h" #include void UART3_init(void); int UART3Tx(unsigned char c); unsigned char* ARRAY_PORT_PINCFG0 = (unsigned char*)®_PORT_PINCFG0; unsigned char* ARRAY_PORT_PMUX0 = (unsigned char*)®_PORT_PMUX0; int main(void) { int n = 0; char str[80]; UART3_init(); printf("Test stdio library console I/O functions\r\n\n"); fprintf(stdout, " test for stdout\r\n"); fprintf(stderr, " test for stderr\r\n\n"); while (1) { printf("please enter a number: \r\n"); scanf("%d", &n); printf("the number entered is:\r\n%d\r\n\n", n); getchar(); /* discard the EOL */ printf("please type a string: \r\n"); gets(str); printf("the string entered is: \r\n"); puts(str); printf("\r\n\n"); } } /* initialize UART3 to 9600 Baud at 1 MHz core clock */ void UART3_init(void) { REG_PM_APBCMASK |= 0x00000020; /* enable bus clock for SERCOM3 */ REG_GCLK_CLKCTRL = 0x4017; /* GCLK0 to SERCOM3 */ REG_SERCOM3_USART_CTRLA |= 1; /* reset SERCOM3 */ while (REG_SERCOM3_USART_SYNCBUSY & 1) {} /* wait for reset to complete */ REG_SERCOM3_USART_CTRLA = 0x40106004; /* LSB first, async, no parity, PAD[0]-TxD, PAD[1]-RxD BAUD uses fraction, 8x oversampling, internal clock */ REG_SERCOM3_USART_CTRLB = 0x00030000; /* enable Tx/Rx, one stop bit, 8 bit */ REG_SERCOM3_USART_BAUD = 13; /* 1000000/8/9600 = 13.02 */ REG_SERCOM3_USART_CTRLA |= 2; /* enable SERCOM3 */ while (REG_SERCOM3_USART_SYNCBUSY & 2) {} /* wait for enable to complete */ ARRAY_PORT_PINCFG0[22] |= 1; /* allow pmux to set PA22 pin configuration */ ARRAY_PORT_PINCFG0[23] |= 1; /* allow pmux to set PA23 pin configuration */ ARRAY_PORT_PMUX0[11] = 0x22; /* PA22 = TxD, PA23 = RxD */ } /* read a character from UART3 */ unsigned char UART3Rx(void) { char c; while(!(REG_SERCOM3_USART_INTFLAG & 4)) {} /* wait until receive buffer is full */ c = REG_SERCOM3_USART_DATA; /* read the receive char */ return c; } /* write a character to UART */ int UART3Tx(unsigned char c) { while(!(REG_SERCOM3_USART_INTFLAG & 1)) {} /* wait for data register empty */ REG_SERCOM3_USART_DATA = c; /* send a char */ return c; } int _write(FILE *f, char *buf, int n) { int m = n; for (; n > 0; n--) UART3Tx(*buf++); return m; } int _read(FILE *f, char *buf, int n) { *buf = UART3Rx(); if (*buf == '\r') { *buf = '\n'; _write(f,"\r", 1); } _write(f, buf, 1); return 1; } int _close(FILE *f) { return 0; } int _fstat(FILE *f, void *p) { *((int*)p + 4) = 0x81b6; // enable read/write return 0; } int _isatty(FILE *f) { return 1; } int _lseek(FILE *f, int o, int w) { return 0; } void* _sbrk(int i) { return (void*)0x20006000; } /* _fstat() returns with permisson 666, that might not make a difference. * _sbrk() returns an address of RAM that might be free. * When scanf() is called, _read() gets a size of 400. * When prinft() is called, an extra '\n' at the end of format is required * for some reason, otherwise the last char is truncated. */