2013-10-22

CooCox CoIDE v1.7.4 Semihosting testing notes
































Coocox Implementation of Semihosting GetChar/SendChar - CooCox 2011-10-19

Components Views (2577) Semihosting Committer: CooCox Updated: 2011-10-19 11:20:25

http://www.coocox.org/show_comp/semihosting-c33.html

Description:

Implementation of Semihosting GetChar/SendChar

Support Chip:

Cortex-M0  Cortex-M0Plus  Cortex-M3  Cortex-M4  ...

Dependency:

Overview

Implementation of Semihosting GetChar/SendChar.

What is Semihosting?

Semihosting provides a mechanism for code running on the MCU to put/get data to/from IDE through USB Adapter.

How to use:

1. Enable Semihosting Project properties.

2. Check "Semihosting" in components page [Not for (v.17.4]

CooCox CoIDE > View > Configuration > Link > Library > Semihosting [For CoIDE v1.7.4]
CooCox CoIDE > View > Configuration > Advance > Semihosting Enable [For CoIDE v1.7.4]

3. Check "Retarget printf" in components page,  <Optional > [Not for (1.7.4]

Then implement PrintChar in printf.c

/**************************************************************************//*****
 * @file     printf.c
 * @brief    Implementation of several stdio.h methods, such as printf(), 
 *           sprintf() and so on. This reduces the memory footprint of the
 *           binary when using those methods, compared to the libc implementation.
 ********************************************************************************/
#include <stdio.h>
#include <stdarg.h>


/**
 * @brief  Transmit a char, if you want to use printf(), 
 *         you need implement this function
 *
 * @param  pStr Storage string.
 * @param  c    Character to write.
 */
void PrintChar(char c)
{
/* Send a char like: 
  while(Transfer not completed);
  Transmit a char;
*/

// Add SH_SendChar(c); to function Printchar()

SH_SendChar(c); // tlfong01 2013oct22
}

4. Use Semihostting API or Retargeted printf/scanf to transmit data between MCU & IDE

Example

// ***********************************************************************
// Program  - Fong EKG v5.0
// Function - Olimex EKG Board Evaluation
// Author   - TL Fong
// Build    - 2013.10.22.01
// Date     - 2013oct22hkt0955
// Hardware - Olimex/CooCox/MagicBlue/WHUT/Somy LPC1114/C14/301/FN28
//            Olimex EKG board (SHIELD-EKG/EMG Rev B, Bulgaria 2011)
// Software - GCC ARM 4.7, CoIDE 1.7.4,  CoLinkEx 1.1, Flash Magic v7.51
// ***********************************************************************

#include "semihosting.h"
#include "stdio.h"

int main()
{
    SH_SendString("test string");

    printf("\n\nHello world! - tlfong01 2013oct22hkt1012. \n\r");

API Reference

SH_SendChar
Transmit a char on semihosting mode.

SH_SendString
Transmit a null-terminated string on semihosting mode.

SH_GetChar
Read a char on semihosting mode.

SH_DoCommand
Semihosting functions prototype

.END


Coocox Implementation of Semihosting GetChar/SendChar - CooCox 11 months ago 2013oct22 

http://www.coocox.org/forum/topic.php?id=835

This semihosting instruction was usefull only in two versions of CoIDE: 1.3.1 and 1.5.1. It don't works with other versions.

Chloe 1 year ago Hi brian.dance,

To use the function of Semihosting, you need to:

1. Select component Semihosting in Repository page;

2. Enable Semihosting in Debug Configuration;

3. Add SH_SendChar(c); to function Printchar() in file printf.c, and add #include "semihosting.h" to the top of the file;

4. Add printf("Hello world!\n\r"); (for example) where you want, and include <stdio.h> at the top of the file.

Ps: For most chips the steps above are suitable, for others like AT91SAM3Uxx, step 3 is a little different. You can view the example for component Semihosting and follow the instruction in the file comment.

Thanks for your support, regards


Retarget printf: Implementation of printf(), sprintf() to reduce memory footprint [CooCox Help]

Overview

Implementation of several stdio.h methods, such as printf(), sprintf() and so on. This reduces the memory footprint of the binary when using those methods, compared to the libc implementation. For using printf function: You need to Implement function PrintChar(). It is a lite printf() function, you can implement other functions if you want to achieve more complex function.


API Reference

PrintChar Transmit a char, if you want to use 

PutChar Writes a character inside the given string. Returns 1. 

PutString Writes a string inside the given string. 

PutUnsignedInt Writes an unsigned int inside the given string, using the provided fill & width parameters. 

PutSignedInt Writes a signed int inside the given string, using the provided fill & width parameters. 

PutHexa Writes an hexadecimal value into a string, using the given fill, width & capital parameters. 

vsnprintf Stores the result of a formatted string into another string. Format arguments are given in a va_list instance. 

snprintf Stores the result of a formatted string into another string. Format arguments are given in a va_list instance. 

vsprintf Stores the result of a formatted string into another string. Format arguments are given in a va_list instance. 

vfprintf Outputs a formatted string on the given stream. Format arguments are given in a va_list instance. 

vprintf Outputs a formatted string on the DBGU stream. Format arguments are given in a va_list instance. 

fprintf Outputs a formatted string on the given stream, using a variable number of arguments. 

printf Outputs a formatted string on the DBGU stream, using a variable number of arguments. 

sprintf Writes a formatted string inside another string. 

puts Outputs a string on stdout. 

fputc Implementation of fputc using the DBGU as the standard output. Required for 

fputs Implementation of fputs using the DBGU as the standard output. Required for 


Source files

printf.c 

Dependency

C Library    



/**************************************************************************//*****
 * @file     printf.c
 * @brief    Implementation of several stdio.h methods, such as printf(), 
 *           sprintf() and so on. This reduces the memory footprint of the
 *           binary when using those methods, compared to the libc implementation.
 ********************************************************************************/
#include <stdio.h>
#include <stdarg.h>


/**
 * @brief  Transmit a char, if you want to use printf(), 
 *         you need implement this function
 *
 * @param  pStr Storage string.
 * @param  c    Character to write.
 */
void PrintChar(char c)
{
/* Send a char like: 
  while(Transfer not completed);
  Transmit a char;
*/
}

/** Maximum string size allowed (in bytes). */
#define MAX_STRING_SIZE         100


/** Required for proper compilation. */
struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
struct _reent *_impure_ptr = &r;

/**
 * @brief  Writes a character inside the given string. Returns 1.
 *
 * @param  pStr Storage string.
 * @param  c    Character to write.
 */
signed int PutChar(char *pStr, char c)
{
    *pStr = c;
    return 1;
}


/**
 * @brief  Writes a string inside the given string.
 *
 * @param  pStr     Storage string.
 * @param  pSource  Source string.
 * @return  The size of the written
 */
signed int PutString(char *pStr, const char *pSource)
{
    signed int num = 0;

    while (*pSource != 0) {

        *pStr++ = *pSource++;
        num++;
    }

    return num;
}


/**
 * @brief  Writes an unsigned int inside the given string, using the provided fill &
 *         width parameters.
 *
 * @param  pStr  Storage string.
 * @param  fill  Fill character.
 * @param  width  Minimum integer width.
 * @param  value  Integer value.   
 */
signed int PutUnsignedInt(
    char *pStr,
    char fill,
    signed int width,
    unsigned int value)
{
    signed int num = 0;

    /* Take current digit into account when calculating width */
    width--;

    /* Recursively write upper digits */
    if ((value / 10) > 0) {

        num = PutUnsignedInt(pStr, fill, width, value / 10);
        pStr += num;
    }
    
    /* Write filler characters */
    else {

        while (width > 0) {

            PutChar(pStr, fill);
            pStr++;
            num++;
            width--;
        }
    }

    /* Write lower digit */
    num += PutChar(pStr, (value % 10) + '0');

    return num;
}


/**
 * @brief  Writes a signed int inside the given string, using the provided fill & width
 *         parameters.
 *
 * @param pStr   Storage string.
 * @param fill   Fill character.
 * @param width  Minimum integer width.
 * @param value  Signed integer value.
 */
signed int PutSignedInt(
    char *pStr,
    char fill,
    signed int width,
    signed int value)
{
    signed int num = 0;
    unsigned int absolute;

    /* Compute absolute value */
    if (value < 0) {

        absolute = -value;
    }
    else {

        absolute = value;
    }

    /* Take current digit into account when calculating width */
    width--;

    /* Recursively write upper digits */
    if ((absolute / 10) > 0) {

        if (value < 0) {
        
            num = PutSignedInt(pStr, fill, width, -(absolute / 10));
        }
        else {

            num = PutSignedInt(pStr, fill, width, absolute / 10);
        }
        pStr += num;
    }
    else {

        /* Reserve space for sign */
        if (value < 0) {

            width--;
        }

        /* Write filler characters */
        while (width > 0) {

            PutChar(pStr, fill);
            pStr++;
            num++;
            width--;
        }

        /* Write sign */
        if (value < 0) {

            num += PutChar(pStr, '-');
            pStr++;
        }
    }

    /* Write lower digit */
    num += PutChar(pStr, (absolute % 10) + '0');

    return num;
}


/**
 * @brief  Writes an hexadecimal value into a string, using the given fill, width &
 *         capital parameters.
 *
 * @param pStr   Storage string.
 * @param fill   Fill character.
 * @param width  Minimum integer width.
 * @param maj    Indicates if the letters must be printed in lower- or upper-case.
 * @param value  Hexadecimal value.
 *
 * @return  The number of char written
 */
signed int PutHexa(
    char *pStr,
    char fill,
    signed int width,
    unsigned char maj,
    unsigned int value)
{
    signed int num = 0;

    /* Decrement width */
    width--;

    /* Recursively output upper digits */
    if ((value >> 4) > 0) {

        num += PutHexa(pStr, fill, width, maj, value >> 4);
        pStr += num;
    }
    /* Write filler chars */
    else {

        while (width > 0) {

            PutChar(pStr, fill);
            pStr++;
            num++;
            width--;
        }
    }

    /* Write current digit */
    if ((value & 0xF) < 10) {

        PutChar(pStr, (value & 0xF) + '0');
    }
    else if (maj) {

        PutChar(pStr, (value & 0xF) - 10 + 'A');
    }
    else {

        PutChar(pStr, (value & 0xF) - 10 + 'a');
    }
    num++;

    return num;
}



/* Global Functions ----------------------------------------------------------- */


/**
 * @brief  Stores the result of a formatted string into another string. Format
 *         arguments are given in a va_list instance.
 *
 * @param pStr    Destination string.
 * @param length  Length of Destination string.
 * @param pFormat Format string.
 * @param ap      Argument list.
 *
 * @return  The number of characters written.
 */
signed int vsnprintf(char *pStr, size_t length, const char *pFormat, va_list ap)
{
    char          fill;
    unsigned char width;
    signed int    num = 0;
    signed int    size = 0;

    /* Clear the string */
    if (pStr) {

        *pStr = 0;
    }

    /* Phase string */
    while (*pFormat != 0 && size < length) {

        /* Normal character */
        if (*pFormat != '%') {

            *pStr++ = *pFormat++;
            size++;
        }
        /* Escaped '%' */
        else if (*(pFormat+1) == '%') {

            *pStr++ = '%';
            pFormat += 2;
            size++;
        }
        /* Token delimiter */
        else {

            fill = ' ';
            width = 0;
            pFormat++;

            /* Parse filler */
            if (*pFormat == '0') {

                fill = '0';
                pFormat++;
            }

            /* Parse width */
            while ((*pFormat >= '0') && (*pFormat <= '9')) {
        
                width = (width*10) + *pFormat-'0';
                pFormat++;
            }

            /* Check if there is enough space */
            if (size + width > length) {

                width = length - size;
            }
        
            /* Parse type */
            switch (*pFormat) {
            case 'd': 
            case 'i': num = PutSignedInt(pStr, fill, width, va_arg(ap, signed int)); break;
            case 'u': num = PutUnsignedInt(pStr, fill, width, va_arg(ap, unsigned int)); break;
            case 'x': num = PutHexa(pStr, fill, width, 0, va_arg(ap, unsigned int)); break;
            case 'X': num = PutHexa(pStr, fill, width, 1, va_arg(ap, unsigned int)); break;
            case 's': num = PutString(pStr, va_arg(ap, char *)); break;
            case 'c': num = PutChar(pStr, va_arg(ap, unsigned int)); break;
            default:
                return EOF;
            }

            pFormat++;
            pStr += num;
            size += num;
        }
    }

    /* NULL-terminated (final \0 is not counted) */
    if (size < length) {

        *pStr = 0;
    }
    else {

        *(--pStr) = 0;
        size--;
    }

    return size;
}


/**
 * @brief  Stores the result of a formatted string into another string. Format
 *         arguments are given in a va_list instance.
 *
 * @param pStr    Destination string.
 * @param length  Length of Destination string.
 * @param pFormat Format string.
 * @param ...     Other arguments
 *
 * @return  The number of characters written.
 */
signed int snprintf(char *pString, size_t length, const char *pFormat, ...)
{
    va_list    ap;
    signed int rc;

    va_start(ap, pFormat);
    rc = vsnprintf(pString, length, pFormat, ap);
    va_end(ap);

    return rc;
}


/**
 * @brief  Stores the result of a formatted string into another string. Format
 *         arguments are given in a va_list instance.
 *
 * @param pString  Destination string.
 * @param length   Length of Destination string.
 * @param pFormat  Format string.
 * @param ap       Argument list.
 *
 * @return  The number of characters written.
 */
signed int vsprintf(char *pString, const char *pFormat, va_list ap)
{
   return vsnprintf(pString, MAX_STRING_SIZE, pFormat, ap);
}

/**
 * @brief  Outputs a formatted string on the given stream. Format arguments are given
 *         in a va_list instance.
 *
 * @param pStream  Output stream.
 * @param pFormat  Format string
 * @param ap       Argument list. 
 */
signed int vfprintf(FILE *pStream, const char *pFormat, va_list ap)
{
    char pStr[MAX_STRING_SIZE];
    char pError[] = "stdio.c: increase MAX_STRING_SIZE\n\r";

    /* Write formatted string in buffer */
    if (vsprintf(pStr, pFormat, ap) >= MAX_STRING_SIZE) {

        fputs(pError, stderr);
        while (1); /* Increase MAX_STRING_SIZE */
    }

    /* Display string */
    return fputs(pStr, pStream);
}


/**
 * @brief  Outputs a formatted string on the DBGU stream. Format arguments are given
 *         in a va_list instance.
 *
 * @param pFormat  Format string.
 * @param ap  Argument list.
 */
signed int vprintf(const char *pFormat, va_list ap)
{
    return vfprintf(stdout, pFormat, ap);
}


/**
 * @brief  Outputs a formatted string on the given stream, using a variable 
 *         number of arguments.
 *
 * @param pStream  Output stream.
 * @param pFormat  Format string.
 */
signed int fprintf(FILE *pStream, const char *pFormat, ...)
{
    va_list ap;
    signed int result;

    /* Forward call to vfprintf */
    va_start(ap, pFormat);
    result = vfprintf(pStream, pFormat, ap);
    va_end(ap);

    return result;
}


/**
 * @brief  Outputs a formatted string on the DBGU stream, using a variable number of
 *         arguments.
 *
 * @param  pFormat  Format string.
 */
signed int printf(const char *pFormat, ...)
{
    va_list ap;
    signed int result;

    /* Forward call to vprintf */
    va_start(ap, pFormat);
    result = vprintf(pFormat, ap);
    va_end(ap);

    return result;
}


/**
 * @brief  Writes a formatted string inside another string.
 *
 * @param pStr     torage string.
 * @param pFormat  Format string.
 */
signed int sprintf(char *pStr, const char *pFormat, ...)
{
    va_list ap;
    signed int result;

    // Forward call to vsprintf
    va_start(ap, pFormat);
    result = vsprintf(pStr, pFormat, ap);
    va_end(ap);

    return result;
}


/**
 * @brief  Outputs a string on stdout.
 *
 * @param pStr  String to output. 
 */
signed int puts(const char *pStr)
{
    return fputs(pStr, stdout);
}


/**
 * @brief  Implementation of fputc using the DBGU as the standard output. Required
 *         for printf().
 *
 * @param c        Character to write.
 * @param pStream  Output stream.
 * @param The character written if successful, or -1 if the output stream is
 *        not stdout or stderr.
 */
signed int fputc(signed int c, FILE *pStream)
{
    if ((pStream == stdout) || (pStream == stderr)) {

    PrintChar(c);

        return c;
    }
    else {

        return EOF;
    }
}


/**
 * @brief  Implementation of fputs using the DBGU as the standard output. Required
 *         for printf().
 *
 * @param pStr     String to write.
 * @param pStream  Output stream.
 *
 * @return  Number of characters written if successful, or -1 if the output
 *          stream is not stdout or stderr.
 */
signed int fputs(const char *pStr, FILE *pStream)
{
    signed int num = 0;

    while (*pStr != 0) {

        if (fputc(*pStr, pStream) == -1) {

            return -1;
        }
        num++;
        pStr++;
    }

    return num;
}

/* --------------------------------- End Of File ------------------------------ */

.END

No comments:

Post a Comment