pic24_stdio_uart.c

Go to the documentation of this file.
00001 /*
00002  * "Copyright (c) 2009 David Weaver ("AUTHORS")"
00003  * All rights reserved.
00004  *
00005  * Permission to use, copy, modify, and distribute this software and its
00006  * documentation for any purpose, without fee, and without written agreement is
00007  * hereby granted, provided that the above copyright notice, the following
00008  * two paragraphs and the authors appear in all copies of this software.
00009  *
00010  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
00011  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00012  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
00013  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00014  *
00015  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00016  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00017  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00018  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
00019  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
00020  *
00021  * Please maintain this header in its entirety when copying/modifying
00022  * these files.
00023  *
00024  *
00025  */
00026 
00027 
00028 // Documentation for this file. If the \file tag isn't present,
00029 // this file won't be documented.
00063 #include "pic24_all.h"
00064 #include <stdio.h>
00065 
00066 // These definitions for translation mode
00067 // Also see SERIAL_EOL_DEFAULT setting in pic_24libconfig.h for output translation 
00068 #define SERIAL_BREAK_CR // Break input stream on CR if specified
00069 #define SERIAL_BREAK_NL // Break input stream on NL if specified
00070 
00071 // These definitions are for libc placement and compatibility
00072 #define _LIBC_FUNCTION __attribute__((__weak__, __section__(".libc")))
00073 #define SUCCESS 0
00074 #define FAIL -1
00075 #define CHAR_ACCESS 0x4000
00076 #define DATA_ACCESS 0x8000  //this flag assumed if CHAR_ACCESS not set
00077 #define READ_ACCESS 0x0
00078 #define WRITE_ACCESS 0x1
00079 #define READ_WRITE_ACCESS 0x2
00080 #define ACCESS_RW_MASK 0x3 // bits set to 0 or 2 for read and 1 or 2 for write
00081 #define ACCESS_SET_OPEN DATA_ACCESS // expedient - reuse bit position to indicate open
00082 
00083 //set default baudrate as needed for each of four UARTs
00084 #ifndef DEFAULT_BAUDRATE1
00085 #define DEFAULT_BAUDRATE1 DEFAULT_BAUDRATE
00086 #endif
00087 #ifndef DEFAULT_BAUDRATE2
00088 #define DEFAULT_BAUDRATE2 DEFAULT_BAUDRATE
00089 #endif
00090 #ifndef DEFAULT_BAUDRATE3
00091 #define DEFAULT_BAUDRATE3 DEFAULT_BAUDRATE
00092 #endif
00093 #ifndef DEFAULT_BAUDRATE4
00094 #define DEFAULT_BAUDRATE4 DEFAULT_BAUDRATE
00095 #endif
00096 
00097 #define MAX_ALLOWED_HANDLES (NUM_UART_MODS+3) // number of handles allowed
00098 #define RANGECK_HANDLE(xxhandlexx) ((xxhandlexx >= 0) && (xxhandlexx < MAX_ALLOWED_HANDLES))
00099 enum ALLOWED_HANDLES {
00100         HANDLE_STDIN=0,
00101         HANDLE_STDOUT=1,
00102         HANDLE_STDERR=2,
00103         HANDLE_UART1,
00104         HANDLE_UART2,
00105         HANDLE_UART3,
00106         HANDLE_UART4
00107 };
00108 
00109 struct {
00110         void (*pfnv_outChar)(); // pointers to functions returning void need casts when set (why?)
00111         uint8 (*pfn_inChar)();
00112         uint16 u16_read_access;
00113         uint16 u16_write_access;
00114 } FILES[MAX_ALLOWED_HANDLES] = {
00115         { 0, 0 }, //stdin
00116         { 0, 0 }, //stdout
00117         { 0, 0 }, //stderr
00118 #if (NUM_UART_MODS >= 1)
00119         { (void *)&outChar1, &inChar1 },
00120 #if (NUM_UART_MODS >= 2)
00121         { (void *)&outChar2, &inChar2 },
00122 #if (NUM_UART_MODS >= 3)
00123         { (void *)&outChar3, &inChar3 },
00124 #if (NUM_UART_MODS >= 4)
00125         { (void *)&outChar4, &inChar4 }
00126 #endif
00127 #endif
00128 #endif
00129 #endif
00130 };
00131 
00132 /**********************************
00133  * Functions private to this file *
00134  **********************************/
00135 
00143 static int16 stdioOpen(void)
00144 {
00145 #if (NUM_UART_MODS >= 1)
00146         if (__C30_UART == 1) {
00147                 FILES[HANDLE_STDERR].pfnv_outChar = (void *)&outChar1;
00148                 FILES[HANDLE_STDOUT].pfnv_outChar = (void *)&outChar1;
00149                 FILES[HANDLE_STDIN].pfn_inChar = &inChar1;
00150                 if (!U1MODEbits.UARTEN) {
00151                         configUART1(DEFAULT_BAUDRATE1);
00152                 }
00153                 return SUCCESS;
00154         }
00155 #if (NUM_UART_MODS >= 2)
00156         if (__C30_UART == 2) {
00157                 FILES[HANDLE_STDERR].pfnv_outChar = (void *)&outChar2;
00158                 FILES[HANDLE_STDOUT].pfnv_outChar = (void *)&outChar2;
00159                 FILES[HANDLE_STDIN].pfn_inChar = &inChar2;
00160                 if (!U2MODEbits.UARTEN) {
00161                         configUART2(DEFAULT_BAUDRATE2);
00162                 }
00163                 return SUCCESS;
00164         }
00165 #if (NUM_UART_MODS >= 3)
00166         if (__C30_UART == 3) {
00167                 FILES[HANDLE_STDERR].pfv_outChar = (void *)&outChar3;
00168                 FILES[HANDLE_STDOUT].pfv_outChar = (void *)&outChar3;
00169                 FILES[HANDLE_STDIN].pfui8_inChar = &inChar3;
00170                 if (!U3MODEbits.UARTEN) {
00171                         configUART3(DEFAULT_BAUDRATE3);
00172                 }
00173                 return SUCCESS;
00174         }
00175 #if (NUM_UART_MODS >= 4)
00176         if (__C30_UART == 4) {
00177                 FILES[HANDLE_STDERR].pfv_outChar = (void *)&outChar4;
00178                 FILES[HANDLE_STDOUT].pfv_outChar = (void *)&outChar4;
00179                 FILES[HANDLE_STDIN].pfui8_inChar = &inChar4;
00180                 if (!U4MODEbits.UARTEN) {
00181                         configUART4(DEFAULT_BAUDRATE4);
00182                 }
00183                 return SUCCESS;
00184         }
00185 #endif
00186 #endif
00187 #endif
00188 #endif
00189         return FAIL;
00190 }
00191 
00192 /*********************************************************
00193  * Public functions intended to be called by other files *
00194  *********************************************************/
00195 
00215 int _LIBC_FUNCTION
00216 open(const char *name, int access, int mode)
00217 {
00218         enum ALLOWED_HANDLES ie_handle;
00219         uint16 u16_masked_access;
00220         uint16 u16_set_access;
00221 
00222         switch (name[4]) { // Expedient - name[4] is unique for the allowed file names
00223         case 'n': //stdin
00224                 if (stdioOpen()) return FAIL;
00225                 ie_handle = HANDLE_STDIN;
00226                 break;
00227         case 'u': //stdout
00228                 if (stdioOpen()) return FAIL;
00229                 ie_handle = HANDLE_STDOUT;
00230                 break;
00231         case 'r': //stderr
00232                 if (stdioOpen()) return FAIL;
00233                 ie_handle = HANDLE_STDERR;
00234                 break;
00235     #if (NUM_UART_MODS >= 1)
00236         case '1': //uart1
00237         if (__C30_UART == 1) return FAIL;
00238                 if (!U1MODEbits.UARTEN) {
00239                         configUART1(DEFAULT_BAUDRATE1);
00240                 }
00241                 ie_handle = HANDLE_UART1;
00242                 break;
00243     #endif
00244         #if (NUM_UART_MODS >= 2)
00245         case '2': //uart2
00246         if (__C30_UART == 2) return FAIL;
00247                 if (!U2MODEbits.UARTEN) {
00248                         configUART2(DEFAULT_BAUDRATE2);
00249                 }
00250                 ie_handle = HANDLE_UART2;
00251                 break;
00252         #endif
00253         #if (NUM_UART_MODS >= 3)
00254         case '3': //uart3
00255         if (__C30_UART == 3) return FAIL;
00256                 if (!U3MODEbits.UARTEN) {
00257                         configUART3(DEFAULT_BAUDRATE3);
00258                 }
00259                 ie_handle = HANDLE_UART3;
00260                 break;
00261     #endif
00262     #if (NUM_UART_MODS >= 4)
00263         case '4': //uart4
00264         if (__C30_UART == 4) return FAIL;
00265                 if (!U4MODEbits.UARTEN) {
00266                         configUART4(DEFAULT_BAUDRATE4);
00267                 }
00268                 ie_handle = HANDLE_UART4;
00269                 break;
00270          #endif
00271         default:
00272                 return FAIL; // name not recognized
00273         }
00274 
00275         u16_masked_access = access & ACCESS_RW_MASK;
00276         u16_set_access = ACCESS_SET_OPEN | access;
00277         if ((u16_masked_access == READ_ACCESS) || (u16_masked_access == READ_WRITE_ACCESS)) {
00278                 FILES[ie_handle].u16_read_access = u16_set_access;
00279         }
00280         if ((u16_masked_access == WRITE_ACCESS) || (u16_masked_access == READ_WRITE_ACCESS)) {
00281                 FILES[ie_handle].u16_write_access = u16_set_access;
00282         }
00283         return ie_handle;
00284 }
00285 
00296 int _LIBC_FUNCTION
00297 read(int handle, void *buffer, unsigned int len)
00298 {
00299         uint16 u16_char_count;
00300 
00301         if(!RANGECK_HANDLE(handle)) return FAIL; // invalid handle
00302         if ((handle == HANDLE_STDIN) && !(FILES[HANDLE_STDIN].u16_read_access & ACCESS_SET_OPEN)) {
00303                 open("stdin", (CHAR_ACCESS | READ_ACCESS), 0);
00304         }
00305         if (!FILES[handle].u16_read_access) return FAIL; // not open
00306         for (u16_char_count = 0; u16_char_count < len; u16_char_count++) {
00307                 ((unsigned char *)buffer)[u16_char_count] = (*FILES[handle].pfn_inChar)();
00308                 #ifdef SERIAL_BREAK_NL
00309                 if ((FILES[handle].u16_read_access & CHAR_ACCESS) && (((unsigned char *)buffer)[u16_char_count] == '\n')) {
00310                         ++u16_char_count;
00311                         break;
00312                 }
00313                 #endif
00314                 #ifdef SERIAL_BREAK_CR
00315                 if ((FILES[handle].u16_read_access & CHAR_ACCESS) && (((unsigned char *)buffer)[u16_char_count] == '\r')) {
00316                         ++u16_char_count;
00317                         break;
00318                 }
00319                 #endif
00320         }
00321 
00322         return u16_char_count;
00323 }
00324 
00335 int _LIBC_FUNCTION
00336 write(int handle, void *buffer, unsigned int len)
00337 {
00338         uint16 u16_char_count;
00339 
00340         if(!RANGECK_HANDLE(handle)) return FAIL; // invalid handle
00341         if ((handle == HANDLE_STDOUT) && !(FILES[HANDLE_STDOUT].u16_write_access & ACCESS_SET_OPEN)) {
00342                 open("stdout", (CHAR_ACCESS | WRITE_ACCESS), 0);
00343         }
00344         if ((handle == HANDLE_STDERR) && !(FILES[HANDLE_STDERR].u16_write_access & ACCESS_SET_OPEN)) {
00345                 open("stderr", (CHAR_ACCESS | WRITE_ACCESS), 0);
00346         }
00347         if (!FILES[handle].u16_write_access) return FAIL; // not open
00348         for (u16_char_count = 0; u16_char_count < len; u16_char_count++) {
00349                 if ((FILES[handle].u16_write_access & CHAR_ACCESS) && (((unsigned char *)buffer)[u16_char_count] == '\n')) {
00350            #if (SERIAL_EOL_DEFAULT==SERIAL_EOL_CR)
00351                     (*FILES[handle].pfv_outChar)('\r');
00352                         continue;
00353            #endif
00354            #if (SERIAL_EOL_DEFAULT==SERIAL_EOL_CR_LF)
00355                      (*FILES[handle].pfv_outChar)('\r');
00356            #endif
00357                     (*FILES[handle].pfnv_outChar)('\n');
00358                         continue;
00359                 }
00360                 (*FILES[handle].pfnv_outChar)(((unsigned char *)buffer)[u16_char_count]);
00361         }
00362 
00363         return u16_char_count;
00364 }
00365 
00372 int _LIBC_FUNCTION
00373 close(int handle) {
00374         return SUCCESS;
00375 }
00376 
00385 long _LIBC_FUNCTION
00386 lseek(int handle, long offset, int origin) {
00387         return SUCCESS;
00388 }

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9