[应用相关]

在LwIP中不使用MicroLIB

[复制链接]
536|8
手机看帖
扫描二维码
随时随地手机跟帖
wowu|  楼主 | 2019-7-4 10:15 | 显示全部楼层 |阅读模式
如果在项目中使用LwIP的话,默认是使用microLIB的,如果不勾选microLIB选项,则程序不能够正常运行,其主要原因在于LwIP使用了microLIB提供的标准输入和输出函数。但是,非常遗憾的是microLIB不支持C++,如果在应用程序中希望使用C++进行程序设计,则不能勾选microLIB,否则在链接的时候会出现问题,本文提供解决这一问题的方法。

不勾选microLIB,keil将使用标准C库函数进行链接,这就需要我们提供相应的低层支持才可以。ARM公司提供了相应的模版,我们可以通过http://infocenter.arm.com/help/topic/com.arm.doc.faqs/attached/3844/retarget.c找到该文件。然后将其加入到keil项目中,仔细分析这个文件可以看出,其只需要我们完成2个函数即可,程序如下。我在这里将其映射到了UART1。

/*
* UART prototype functions
*/
char UART_read(void)
{
        return 0;
}

void UART_write(char ch)
{
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 10);
}


使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:15 | 显示全部楼层
下面,我给出完整的程序,如果希望使用,将其直接拷贝即可。

/*
* Copyright (C) ARM Limited, 2006. All rights reserved.
*
* This is a retargeted I/O example which implements the functions required
* for communication through an UART. The implementation relies on two UART
* functions which the user must provide (UART_write and UART_read) for
* sending and receiving single characters to and from the UART.
*
* See the "rt_sys.h" header file for complete function descriptions.
*/

#include <rt_sys.h>
#include "main.h"

#ifdef __cplusplus
extern "C" {
#endif

#define DEFAULT_HANDLE 0x100;

extern UART_HandleTypeDef huart1;

/*
* UART prototype functions
*/
char UART_read(void)
{
        return 0;
}

void UART_write(char ch)
{
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 10);
}



使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:16 | 显示全部楼层

/*
* These names are special strings which will be recognized by
* _sys_open and will cause it to return the standard I/O handles, instead
* of opening a real file.
*/
const char __stdin_name[] ="STDIN";
const char __stdout_name[]="STDOUT";
const char __stderr_name[]="STDERR";

/*
* Open a file. May return -1 if the file failed to open. We do not require
* this function to do anything. Simply return a dummy handle.
*/
FILEHANDLE _sys_open(const char * name, int openmode)
{
    return DEFAULT_HANDLE;  
}

/*
* Close a file. Should return 0 on success or a negative value on error.
* Not required in this implementation. Always return success.
*/
int _sys_close(FILEHANDLE fh)
{
    return 0; //return success
}


使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:17 | 显示全部楼层
/*
* Write to a file. Returns 0 on success, negative on error, and the number
* of characters _not_ written on partial success. This implementation sends
* a buffer of size 'len' to the UART.
*/
int _sys_write(FILEHANDLE fh, const unsigned char * buf,
               unsigned len, int mode)
{
    int i;
    for(i=0;i<len;i++)
    {
        UART_write(buf[i]);

        // Fix for HyperTerminal   
        if(buf[i]=='\n') UART_write('\r');
    }

    return 0;   
}


使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:17 | 显示全部楼层
/*
* Read from a file. Can return:
*  - zero if the read was completely successful
*  - the number of bytes _not_ read, if the read was partially successful
*  - the number of bytes not read, plus the top bit set (0x80000000), if
*    the read was partially successful due to end of file
*  - -1 if some error other than EOF occurred
* This function receives a character from the UART, processes the character
* if required (backspace) and then echo the character to the Terminal
* Emulator, printing the correct sequence after successive keystrokes.  
*/
int _sys_read(FILEHANDLE fh, unsigned char * buf,
              unsigned len, int mode)
{
    int pos=0;

    do {


        buf[pos]=UART_read();

        // Advance position in buffer
        pos++;

        // Handle backspace
        if(buf[pos-1] == '\b')
        {
            // More than 1 char in buffer
            if(pos>1)
            {
                // Delete character on terminal
                UART_write('\b');
                UART_write(' ');
                UART_write('\b');         

                // Update position in buffer
                pos-=2;   
            }
            else if (pos>0) pos--; // Backspace pressed, empty buffer
        }
        else UART_write(buf[pos-1]); // Echo normal char to terminal


    }while(buf[pos-1] != '\r');

    buf[pos]= '\0'; // Ensure Null termination

    return 0;      
}



使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:17 | 显示全部楼层
/*
* Writes a character to the output channel. This function is used
* for last-resort error message output.
*/
void _ttywrch(int ch)
{
    // Convert correctly for endianness change
    char ench=ch;

    UART_write(ench);
}

/*
* Return non-zero if the argument file is connected to a terminal.
*/
int _sys_istty(FILEHANDLE fh)
{
    return 1; // no interactive device present
}


使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:18 | 显示全部楼层
/*
* Move the file position to a given offset from the file start.
* Returns >=0 on success, <0 on failure. Seeking is not supported for the
* UART.
*/
int _sys_seek(FILEHANDLE fh, long pos)
{
    return -1; // error
}

/*
* Flush any OS buffers associated with fh, ensuring that the file
* is up to date on disk. Result is >=0 if OK, negative for an
* error.
*/
int _sys_ensure(FILEHANDLE fh)
{
    return 0; // success
}


使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:18 | 显示全部楼层
/*
* Return the current length of a file, or <0 if an error occurred.
* _sys_flen is allowed to reposition the file pointer (so Unix can
* implement it with a single lseek, for example), since it is only
* called when processing SEEK_END relative fseeks, and therefore a
* call to _sys_flen is always followed by a call to _sys_seek.
*/
long _sys_flen(FILEHANDLE fh)
{
    return 0;
}



使用特权

评论回复
wowu|  楼主 | 2019-7-4 10:19 | 显示全部楼层
/*
* Return the name for temporary file number sig in the buffer
* name. Returns 0 on failure. maxlen is the maximum name length
* allowed.
*/
int _sys_tmpnam(char * name, int sig, unsigned maxlen)
{
    return 0; // fail, not supported
}

/*
* Terminate the program, passing a return code back to the user.
* This function may not return.
*/
void _sys_exit(int returncode)
{
    while(1) {};
}

#ifdef __cplusplus
}
#endif


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

80

主题

3852

帖子

1

粉丝