Easyelectronics.ru

Электроника для всех
Текущее время: 24 окт 2020, 19:53

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 7 ] 
Автор Сообщение
 Заголовок сообщения: stm32 и retarget printf
СообщениеДобавлено: 14 сен 2012, 09:20 
Только пришел

Зарегистрирован: 01 апр 2011, 18:32
Сообщения: 14
Здравствуйте. Встала задача привязать printf к USART1
Камень STM32f103ZE, IDE - CooCox. нашёл статейку http://we.easyelectronics.ru/CADSoft/za ... coide.html
CooCox-ы тоже на этот код ссылаются. Вот только с компиляцией проблемы.
Через Repository подключил библиотеки: C library, USART, GPIO, RCC - всё собирается без проблем, но естественно printf не работает.
Как только подключаю Retarget printf (не важно - сразу компилю или меняю код по статье) начинает ругаться:

Код:
compile:
    [mkdir] Created dir: C:\CoIDE\workspace\print\Debug\bin
    [mkdir] Created dir: C:\CoIDE\workspace\print\Debug\obj
       [cc] 9 total files to be compiled.
       [cc] arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Wall -ffunction-sections -O0 -g -c -DSTM32F10X_HD -DUSE_STDPERIPH_DRIVER -D__ASSEMBLY__ -DSTM32F103ZE -IC:\CoIDE\workspace\print -IC:\CoIDE\workspace\print\stm_lib -IC:\CoIDE\workspace\print\stm_lib\inc -IC:\CoIDE\workspace\print\cmsis_boot -IC:\CoIDE\workspace\print\cmsis C:\CoIDE\workspace\print\cmsis\core_cm3.c C:\CoIDE\workspace\print\cmsis_boot\system_stm32f10x.c C:\CoIDE\workspace\print\cmsis_boot\startup\startup_stm32f10x_hd.c C:\CoIDE\workspace\print\stm_lib\src\stm32f10x_gpio.c C:\CoIDE\workspace\print\main.c C:\CoIDE\workspace\print\stdio\printf.c C:\CoIDE\workspace\print\stm_lib\src\stm32f10x_rcc.c C:\CoIDE\workspace\print\stm_lib\src\stm32f10x_usart.c C:\CoIDE\workspace\print\syscalls\syscalls.c
       [cc] Starting link
       [cc] arm-none-eabi-gcc -O0 -nostartfiles -Wl,-Map=print.map -mcpu=cortex-m3 -mthumb -LC:\CoIDE\workspace\print -Wl,--gc-sections -Wl,-TC:\CoIDE\workspace\print\link.ld -g -o print.elf ..\obj\core_cm3.o ..\obj\system_stm32f10x.o ..\obj\startup_stm32f10x_hd.o ..\obj\stm32f10x_gpio.o ..\obj\main.o ..\obj\printf.o ..\obj\stm32f10x_rcc.o ..\obj\stm32f10x_usart.o ..\obj\syscalls.o
       [cc] c:/coide/arm-2011.03-coocox/bin/../lib/gcc/arm-none-eabi/4.5.2/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-impure.o):(.data+0x0): multiple definition of `_impure_ptr'
       [cc] collect2: ld returned 1 exit status
       [cc] ..\obj\printf.o:(.data+0xf0): first defined here

BUILD FAILED
Total time: 3 seconds


мой код:
Код:
#include <stm32f10x.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_usart.h>
#include <stdio.h>

void USART_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;

  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate = 115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART1, &USART_InitStructure);
  USART_ClearFlag(USART1,USART_FLAG_TC);
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
  USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
  USART_Cmd(USART1, ENABLE);
}

void Delay_ms(uint32_t ms)
{
    volatile uint32_t nCount;
    RCC_ClocksTypeDef RCC_Clocks;
    RCC_GetClocksFreq (&RCC_Clocks);

    nCount = (RCC_Clocks.HCLK_Frequency/10000)*ms;
    for (; nCount!=0; nCount--);
}

int main(void)
{
   USART_Configuration();
   while (1)
   {
       printf("t");
       Delay_ms(1000);
   }
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 14 сен 2012, 17:14 
Старожил

Зарегистрирован: 28 май 2012, 09:26
Сообщения: 229
Пробовал на коксе, размер прошивки резко возрастает, по этому не пользуюсь, проще написать самому то, что нужно.
Если есть проблемы с переводом числа в стринг, как целого так и с п\з есть у меня исходники простых функций.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 14 сен 2012, 17:55 
Только пришел

Зарегистрирован: 01 апр 2011, 18:32
Сообщения: 14
makser писал(а):
Пробовал на коксе, размер прошивки резко возрастает, по этому не пользуюсь, проще написать самому то, что нужно.
Если есть проблемы с переводом числа в стринг, как целого так и с п\з есть у меня исходники простых функций.

есть проблема с кучей уже написанных функций, использующих printf. поэтому нужно завести printf


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 14 сен 2012, 19:45 
Старожил
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:48
Сообщения: 3965
Откуда: Звенигород
Сделай перегрузку:) printf.

_________________
От Парижа до Находки с водкой лучше, чем без водки!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 15 сен 2012, 07:04 
Только пришел

Зарегистрирован: 01 апр 2011, 18:32
Сообщения: 14
PRC писал(а):
Сделай перегрузку:) printf.

ну вот меня и терзает мысль, что проблема чисто синтаксическая, но как это сделать - найти не могу. Вернее "перезагрузка операторов" вообще к Си неприменима, а вот как переопределить функцию.
Нашёл вот такой tip http://microsin.ru/content/view/432/44/ , но вроде по нему и так всё сделано


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 17 сен 2012, 13:49 
Заглядывает иногда

Зарегистрирован: 29 апр 2012, 14:20
Сообщения: 123
define ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 и retarget printf
СообщениеДобавлено: 20 сен 2012, 16:44 
Только пришел

Зарегистрирован: 01 апр 2011, 18:32
Сообщения: 14
В общем победил проблему. Если вдруг кому понадобиться рабочий printf - вот мой костыль. Он жестко привязан к USART1 (все потоки выводятся в него, если нужен другой USART - меняем в функции fputc). Итак, код файла 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>
#include <stm32f10x_usart.h>

/** 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)
{
   USART_SendData(USART1, (uint8_t) c);
   while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET){};
   return c;
}


/**
* @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 ------------------------------ */



Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 7 ] 


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: t0xin


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB