2016-11-10 06:33 AM
Hi,
I'mworking on a project which is based on STM32F7. In order to get used to the F7 architecture, I am usingSTM32F746 Disco. board with Gnu-Arm-Gcc-Toolchain with Eclipse Ide on Windows instead of Keil. I managed to run FreeRtos and LCD without a problem. While I am trying to implement the LwIP stack asexemplified by the ''LwIP_HTTP_Server_Netconn_RTOS'' examplein the STM32F7Cube package, I have faced with a problem. I noticed that lcd_log layer halts the system whenever I call the ''LCD_UsrLog'' function. LCD_UsrLog function is calling the printf. The printf seems that it iscalling ''__io_putch'' if we use GCC, and ''fputc''if we use Keil as seen below: (lcd_log_conf.h)/* Redirect the printf to the LCD */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define LCD_LOG_PUTCHAR int __io_putchar(int ch)
#else
#define LCD_LOG_PUTCHAR int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/
* Redirect the printf to the LCD */
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define LCD_LOG_PUTCHAR int __io_putchar(int ch)
#else
#define LCD_LOG_PUTCHAR int fputc(int ch, FILE *f)
#endif /* __GNUC__ *
And then it continues like this in lcd_log.c:
LCD_LOG_PUTCHAR
{
sFONT *cFont = BSP_LCD_GetFont();
uint32_t idx;
if(LCD_Lock == DISABLE)
{
if(LCD_ScrollActive == ENABLE)
{
LCD_CacheBuffer_yptr_bottom = LCD_CacheBuffer_yptr_bottom_bak;
LCD_CacheBuffer_yptr_top = LCD_CacheBuffer_yptr_top_bak;
LCD_ScrollActive = DISABLE;
...
LCD_LOG_PUTCHAR
{
sFONT *cFont = BSP_LCD_GetFont();
uint32_t idx;
if(LCD_Lock == DISABLE)
{
if(LCD_ScrollActive == ENABLE)
{
LCD_CacheBuffer_yptr_bottom = LCD_CacheBuffer_yptr_bottom_bak;
LCD_CacheBuffer_yptr_top = LCD_CacheBuffer_yptr_top_bak;
LCD_ScrollActive = DISABLE;
....
The example is working well in Keil as expected. I don't know how to enable small printfoption as noted in the file lcd_log_conf. What is the flag of that option for linker? Or is there any other thing that I should do like changing syscalls.c? By the way, I don't have the file ''syscalls.c'' added to the project. ST dropped a ''syscalls.c'' for SW4ST but I don't know how to use it because it caused another problems when I added it to my project.
Any help will be appreciated. Thanks in advance..
#stm32f7-lcd_log-gcc-printf
2016-11-14 06:16 AM
Here is the solution:
BecauseLCD_UsrLog() function calls printf(), then printf() calls _write(), and then _write() calls__io_putchar(); somehow GCC couldn't find the function _write(). So what I have done is just importing syscalls.c file with some modifications in order to prevent from multiple definitions of some functions. This is the syscalls.c file that I used:/* Support files for GNU libc. Files in the system namespace go here.
Files in the C namespace (ie those that do not start with an
underscore) go in .c. */
#include <
_ansi.h
>
#include <
sys
/types.h>
#include <
sys
/stat.h>
#include <
sys
/fcntl.h>
#include <
stdio.h
>
#include <
string.h
>
#include <
time.h
>
#include <
sys
/time.h>
#include <
sys
/times.h>
#include <
errno.h
>
#include <
reent.h
>
#include <
unistd.h
>
#include <
sys
/wait.h>
#define FreeRTOS
#define MAX_STACK_SIZE 0x2000
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
#ifndef FreeRTOS
register char * stack_ptr asm(''sp'');
#endif
caddr_t _sbrk(int incr)
{
extern char end asm(''end'');
static char *heap_end;
char *prev_heap_end,*min_stack_ptr;
if (heap_end == 0)
heap_end = &end;
prev_heap_end = heap_end;
#ifdef FreeRTOS
/* Use the NVIC offset register to locate the main stack pointer. */
min_stack_ptr = (char*)(*(unsigned int *)*(unsigned int *)0xE000ED08);
/* Locate the STACK bottom address */
min_stack_ptr -= MAX_STACK_SIZE;
if (heap_end + incr > min_stack_ptr)
#else
if (heap_end + incr > stack_ptr)
#endif
{
// write(1, ''Heap and stack collision
'', 25);
// abort();
errno = ENOMEM;
return (caddr_t) -1;
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
//
///*
// * _gettimeofday primitive (Stub function)
// * */
//int _gettimeofday (struct timeval * tp, struct timezone * tzp)
//{
// /* Return fixed data for the timezone. */
// if (tzp)
// {
// tzp->tz_minuteswest = 0;
// tzp->tz_dsttime = 0;
// }
//
// return 0;
//}
//void initialise_monitor_handles()
//{
//}
int _getpid(void)
{
return 1;
}
//
//int _kill(int pid, int sig)
//{
// errno = EINVAL;
// return -1;
//}
//
//void _exit (int status)
//{
// _kill(status, -1);
// while (1) {}
//}
int _write(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx <
len
; DataIdx++)
{
__io_putchar( *ptr++ );
}
return len;
}
//int _close(int file)
//{
// return -1;
//}
int _fstat(int file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
//int _isatty(int file)
//{
// return 1;
//}
//
//int _lseek(int file, int ptr, int dir)
//{
// return 0;
//}
int _read(int file, char *ptr, int len)
{
int DataIdx;
for (DataIdx = 0; DataIdx <
len
; DataIdx++)
{
*ptr++ = __io_getchar();
}
return len;
}
//int _open(char *path, int flags, ...)
//{
// /* Pretend like we always fail */
// return -1;
//}
int _wait(int *status)
{
errno
=
ECHILD
;
return -1;
}
//int _unlink(char *name)
//{
//
errno
=
ENOENT
;
// return -1;
//}
//
//int _times(struct tms *buf)
//{
// return -1;
//}
int _stat(char *file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
int _link(char *old, char *new)
{
errno = EMLINK;
return -1;
}
int _fork(void)
{
errno = EAGAIN;
return -1;
}
int _execve(char *name, char **argv, char **env)
{
errno = ENOMEM;
return -1;
}