6.18.1.4 Customizing Helper Functions for XC32
The standard I/O relies on helper functions described in Syscall Interface. These functions
include read()
, write()
, open()
, and
close()
which are called to read, write, open or close handles that
are associated with standard I/O FILE
pointers. The sources for these
libraries are provided for you to customize as you wish.
The simplest way to redirect standard I/O to the peripheral of your choice is to select
one of the default handles already in use. Also, you could open files with a specific
name via fopen()
by rewriting open()
to return a new
handle to be recognized by read()
or write()
as
appropriate.
If only a specific peripheral is required, then you could associate handle 1 ==
stdout
or 2 == stderr
to another peripheral by writing the
correct code to talk to the interested peripheral.
A complete generic solution might be:
/* should be in a header file */
enum my_handles {
handle_stdin,
handle_stdout,
handle_stderr,
handle_peripheral1,
handle_peripheral2,
};
int
open(const char *name, int access, int mode) {
switch (name[0]) {
case 'i': return handle_stdin;
case 'o': return handle_stdout;
case 'e': return handle_stderr;
case 'c': return handle_peripheral1;
case 'C': return handle_peripheral2;
default: return handle_stderr;
}
}
Single letters were used in this example because they are faster to check and use less
memory. However, if memory is not an issue, you could use strcmp
to
compare full names.
In write()
, you would write:
int write(int handle, void *buffer, unsigned int len) {
int i;
/* Do not try to output an empty string */
if (!buffer || (len == 0))
return 0;
switch (handle) {
case 0:
case 1:
case 2:
for (i = len; i; --i) {
/* place code here to write the next byte of buffer to the desired peripheral */
PERIPH1 = *(char*) buffer;
buffer++;
}
break;
case handle_peripheral1:
for (i = len; i; --i) {
/* place code here to write the next byte of buffer to the desired peripheral */
PERIPH2 = *(char*) buffer;
buffer++;
}
break;
case handle_peripheral2:
/* place code here to write the buffer to the desired peripheral */
break;
default:
{
break;
}
}
return (len);
}
where you would fill in the appropriate code as specified in the comments.
Now you can use the generic C standard I/O features to write to another port:
#include <xc.h>
#include <stdio.h>
int main(void) {
char my_string[] = "count";
int count = 0;
for (count = 0; count < 5; count++) {
printf("%s: %d\n", my_string, count);
}
FILE * peripheral = fopen("c", "w");
fprintf(peripheral, "This will be output through the peripheral\n");
__builtin_software_breakpoint();
while (1);
}