Last active
August 7, 2016 03:34
-
-
Save lixingcong/dac60bb8ca4610a994ddd2fefc7bb5b9 to your computer and use it in GitHub Desktop.
Redirect std stream to USARTx for STM32F103 device
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# toolchain: gcc-arm-none-eabi(Linux), pleas use newlib_stubs.c | |
OBJS += newlib_stubs.o | |
CFLAGS += -ffunction-sections -fdata-sections -fno-builtin | |
LDFLAGS += --specs=nano.specs -lc -lnosys | |
# toolchain: keil MDK(Windows), please use redirect_file_stream.c | |
# Please check 'USE MicroLIB' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* newlib_stubs.c | |
* Created on: 2 Nov 2010 Author: nanoage.co.uk | |
http://svn.clifford.at/handicraft/2015/c3demo/app_primes/syscalls.c | |
https://sourceware.org/newlib/libc.html | |
*/ | |
#include <errno.h> | |
#include <sys/stat.h> | |
#include <sys/times.h> | |
#include <sys/unistd.h> | |
#include "stm32f10x.h" | |
#include "stm32f10x_usart.h" | |
#ifndef STDOUT_USART | |
#define STDOUT_USART 1 | |
#endif | |
#ifndef STDERR_USART | |
#define STDERR_USART 1 | |
#endif | |
#ifndef STDIN_USART | |
#define STDIN_USART 1 | |
#endif | |
#undef errno | |
extern int errno; | |
/* | |
- File management functions | |
+ open : (v) open file | |
+ lseek : (v) set position in file | |
+ read : (v) read from file | |
+ write : (v) write to file | |
+ fstat : (z) status of an open file | |
+ stat : (z) status of a file by name | |
+ close : (z) close a file | |
+ link : (z) rename a file | |
+ unlink : (z) remote file's directory entry | |
- Process management functions | |
+ execve : (z) transfer control to new proc | |
+ fork : (z) create a new process | |
+ getpid : (v) get process id | |
+ kill : (z) send signal to child process | |
+ wait : (z) wait for a child process | |
- Misc functions | |
+ isatty : (v) query whether output stream is a terminal | |
+ times : (z) timing information for current process | |
+ sbrk : (v) increase program data space | |
+ _exit : (-) exit program without cleaning up files | |
*/ | |
/* | |
environ | |
A pointer to a list of environment variables and their values. | |
For a minimal environment, this empty list is adequate: | |
*/ | |
char *__env[1] = { 0 }; | |
char **environ = __env; | |
int _write(int file, char *ptr, int len); | |
void _exit(int status) { | |
_write(1, "exit", 4); | |
while (1) { | |
; | |
} | |
} | |
int _close(int file) { | |
return -1; | |
} | |
/* | |
execve | |
Transfer control to a new process. Minimal implementation (for a system without processes): | |
*/ | |
int _execve(char *name, char **argv, char **env) { | |
errno = ENOMEM; | |
return -1; | |
} | |
/* | |
fork | |
Create a new process. Minimal implementation (for a system without processes): | |
*/ | |
int _fork() { | |
errno = EAGAIN; | |
return -1; | |
} | |
/* | |
fstat | |
Status of an open file. For consistency with other minimal implementations in these examples, | |
all files are regarded as character special devices. | |
The `sys/stat.h' header file required is distributed in the `include' subdirectory for this C library. | |
*/ | |
int _fstat(int file, struct stat *st) { | |
st->st_mode = S_IFCHR; | |
return 0; | |
} | |
/* | |
getpid | |
Process-ID; this is sometimes used to generate strings unlikely to conflict with other processes. Minimal implementation, for a system without processes: | |
*/ | |
int _getpid() { | |
return 1; | |
} | |
/* | |
isatty | |
Query whether output stream is a terminal. For consistency with the other minimal implementations, | |
*/ | |
int _isatty(int file) { | |
switch (file) { | |
case STDOUT_FILENO: | |
case STDERR_FILENO: | |
case STDIN_FILENO: | |
return 1; | |
default: | |
//errno = ENOTTY; | |
errno = EBADF; | |
return 0; | |
} | |
} | |
/* | |
kill | |
Send a signal. Minimal implementation: | |
*/ | |
int _kill(int pid, int sig) { | |
errno = EINVAL; | |
return (-1); | |
} | |
/* | |
link | |
Establish a new name for an existing file. Minimal implementation: | |
*/ | |
int _link(char *old, char *new) { | |
errno = EMLINK; | |
return -1; | |
} | |
/* | |
lseek | |
Set position in a file. Minimal implementation: | |
*/ | |
int _lseek(int file, int ptr, int dir) { | |
return 0; | |
} | |
/* | |
sbrk | |
Increase program data space. | |
Malloc and related functions depend on this | |
*/ | |
caddr_t _sbrk(int incr) { | |
extern char _ebss; // Defined by the linker | |
static char *heap_end; | |
char *prev_heap_end; | |
if (heap_end == 0) { | |
heap_end = &_ebss; | |
} | |
prev_heap_end = heap_end; | |
char * stack = (char*) __get_MSP(); | |
if (heap_end + incr > stack) { | |
_write(STDERR_FILENO, "Heap and stack collision\n", 25); | |
errno = ENOMEM; | |
return (caddr_t) - 1; | |
//abort (); | |
} | |
heap_end += incr; | |
return (caddr_t) prev_heap_end; | |
} | |
/* | |
read | |
Read a character to a file. `libc' subroutines will use this system routine for input from all files, including stdin | |
Returns -1 on error or blocks until the number of characters have been read. | |
About function _read(): | |
In this script, you should input ends with '\r\n' ! | |
For linux or Mac, the EOL is LF (Line feed, '\n', 0x0AH) | |
For Windows, the EOL is CR+LF (Carriage return+Line feed, '\r\n', 0x0D0AH) | |
Please view it in function void _read() | |
*/ | |
int _read(int file, char *ptr, int len) { | |
int n; | |
char c; | |
int num = 0; | |
switch (file) { | |
case STDIN_FILENO: | |
for (n = 0; n < len; n++) { | |
#if STDIN_USART == 1 | |
while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t) RESET) { | |
} | |
c = (char) (USART1->DR & (uint16_t) 0x01FF); | |
#elif STDIN_USART == 2 | |
while ((USART2->SR & USART_FLAG_RXNE) == (uint16_t) RESET) {} | |
c = (char) (USART2->DR & (uint16_t) 0x01FF); | |
#elif STDIN_USART == 3 | |
while ((USART3->SR & USART_FLAG_RXNE) == (uint16_t)RESET) {} | |
c = (char)(USART3->DR & (uint16_t)0x01FF); | |
#endif | |
if (c == '\n') | |
return num; | |
// LF means newline, CR means had pressed ENTER key, | |
// CR tells scanf that user has finished input | |
*ptr++ = c; | |
num++; | |
} | |
break; | |
default: | |
errno = EBADF; | |
return -1; | |
} | |
return num; | |
} | |
/* | |
stat | |
Status of a file (by name). Minimal implementation: | |
int _EXFUN(stat,( const char *__path, struct stat *__sbuf )); | |
*/ | |
int _stat(const char *filepath, struct stat *st) { | |
st->st_mode = S_IFCHR; | |
return 0; | |
} | |
/* | |
times | |
Timing information for current process. Minimal implementation: | |
*/ | |
clock_t _times(struct tms *buf) { | |
return -1; | |
} | |
/* | |
unlink | |
Remove a file's directory entry. Minimal implementation: | |
*/ | |
int _unlink(char *name) { | |
errno = ENOENT; | |
return -1; | |
} | |
/* | |
wait | |
Wait for a child process. Minimal implementation: | |
*/ | |
int _wait(int *status) { | |
errno = ECHILD; | |
return -1; | |
} | |
/* | |
write | |
Write a character to a file. `libc' subroutines will use this system routine for output to all files, including stdout | |
Returns -1 on error or number of bytes sent | |
*/ | |
int _write(int file, char *ptr, int len) { | |
int n; | |
switch (file) { | |
case STDOUT_FILENO: /*stdout*/ | |
for (n = 0; n < len; n++) { | |
#if STDOUT_USART == 1 | |
while ((USART1->SR & USART_FLAG_TC) == (uint16_t) RESET) { | |
} | |
USART1->DR = (*ptr++ & (uint16_t) 0x01FF); | |
#elif STDOUT_USART == 2 | |
while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { | |
} | |
USART2->DR = (*ptr++ & (uint16_t) 0x01FF); | |
#elif STDOUT_USART == 3 | |
while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} | |
USART3->DR = (*ptr++ & (uint16_t)0x01FF); | |
#endif | |
} | |
break; | |
case STDERR_FILENO: /* stderr */ | |
for (n = 0; n < len; n++) { | |
#if STDERR_USART == 1 | |
while ((USART1->SR & USART_FLAG_TC) == (uint16_t) RESET) { | |
} | |
USART1->DR = (*ptr++ & (uint16_t) 0x01FF); | |
#elif STDERR_USART == 2 | |
while ((USART2->SR & USART_FLAG_TC) == (uint16_t) RESET) { | |
} | |
USART2->DR = (*ptr++ & (uint16_t) 0x01FF); | |
#elif STDERR_USART == 3 | |
while ((USART3->SR & USART_FLAG_TC) == (uint16_t)RESET) {} | |
USART3->DR = (*ptr++ & (uint16_t)0x01FF); | |
#endif | |
} | |
break; | |
default: | |
errno = EBADF; | |
return -1; | |
} | |
return len; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* redirect_file_stream.c | |
* | |
* Created on: 2016年8月2日 | |
* Author: li | |
* | |
* redirect stdout and stderr to USART1 and USART2 seperately | |
* use Micro Lib | |
* For Windows Keil only | |
*/ | |
#include "stdio.h" | |
#include "stm32f10x_usart.h" | |
struct __FILE{ | |
int handle; | |
}; | |
enum{ | |
STDOUT_HANDLE, | |
STDERR_HANDLE | |
}; | |
// USART1: stderr | |
// USART1: stdin | |
// USART2: stdout | |
FILE __stdout={STDOUT_HANDLE}; | |
FILE __stderr={STDERR_HANDLE}; | |
int fputc(int ch,FILE *f) | |
{ | |
int ret = EOF ; | |
switch( f->handle ){ | |
case STDOUT_HANDLE: | |
ret = ch ; | |
USART_SendData(USART2,(uint8_t)ch); | |
while((USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET)); | |
break ; | |
case STDERR_HANDLE: | |
ret = ch ; | |
USART_SendData(USART1,(uint8_t)ch); | |
while((USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)); | |
break ; | |
default: | |
break ; | |
} | |
return ret; | |
} | |
int fgetc(FILE *f){ | |
unsigned short c; | |
while ((USART1->SR & USART_FLAG_RXNE) == (uint16_t) RESET); | |
c = (char) (USART1->DR & (uint16_t) 0x01FF); | |
return c; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment