This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

about scanf retarget in Cortexm3 of SmartFuson of Actel

Hi,

I have one question about Cortexm3 from smartfusion device from actel. Could you pls help me?
I add follwing codes into retarget.c and then add retarget.c into source code group and find :
printf function works.however scanf function doesn't. anybody knows why?

int fputc(int ch, FILE *f) {
return ((int)ITM_SendChar(ch));
}

int fgetc(FILE *f) {
int i=0;
i=ITM_ReceiveChar();
if((-1)!=i)
        return ((int)ITM_SendChar((uint32_t)i));
else
        return (0);
}
  printf("hello world\n\r"); // when executed, string displayed in debug(printf)window
  scanf("%s",str);                // when executed, hard fault occurs

  • here, str is defined as an array.for example

    unsigned char str[10];
    

  • So how do you ensure that the data returned by scanf doesn't exceed 9 characters (or whatever your array size happens to be) ?

    Surely, this is a fundamental flaw with using scanf ?!

    Try searching the forum for "scanf"...

  • hi, it is just a test since it is myself who is clicking the keyboard.

    I don't know when the PC will point to hardfault handler once defined scanf function is executed.

    I had searched "scanf" in this forum and find no similar thread.

    Looking forward to help.

    thanks.

    Fisher

  • You missed the point!

    The point is that scanf is, generally, a Bad Thing to be using in such a situation - there are plenty of threads that illustriate this point.

  • Did you ever implement success scanf function in Cortexm3 in smartFusion? I guess you didn't. otherwise you will find that those scanf examples found in another thereads don't work in Cortexm3 within smartFusion!

  • Well known dangerous functions that stands for a large number of buffer overflows in this world includes:
    scanf()
    gets()
    sprintf()
    strcpy()

    Note that Keil doesn't have the standard gets() but have duplicated the fix from fgets(), i.e. added a size parameter telling the max number of characters that may be handled.

  • Why not?

    Is it really anything specifically to do with Cortex-M3 and/or SmartFusion?

  • Could you please post your scanf() here?
    I know how to retarget to real UART connected to PC via Hypertermial using retarget.c.
    However I don't know how to retarget to debug(printf) windows via ITM.

  • Hello Fisher Cheng,

    µVision provides for a CM3/CM4 debug support via ITM (Instrumented Trace Macrocell).
    In a debug session the Debug (printf) Viewer window is used to display the debug data.

    Direction: Microcontroller -> µVision:
    * Characters received via ITM communication channel 0 are written in a printf style to Debug (printf) Viewer window.

    Direction: µVision -> Microcontroller:
    * variable ITM_RxBuffer is used for data transfer.
    * Check if ITM_RxBuffer variable is available (only performed once).
    * Read character from Debug (printf) Viewer window.
    * If ITM_RxBuffer empty write character to ITM_RxBuffer.

    Note: Current solution does not use a buffer mechanism for transmitting the characters.

    For my tests (only simulation) I used following code in retarget.c

    #include <stdio.h>
    #include <rt_misc.h>
    #include "a2fxxxm3.h"
    
    #pragma import(__use_no_semihosting_swi)
    
    volatile int ITM_RxBuffer = ITM_RXBUFFER_EMPTY;       /* used for Debug Input */
    
    struct __FILE { int handle; };
    FILE __stdout;
    FILE __stdin;
    
    
    int fputc(int ch, FILE *f) {
      return (ITM_SendChar(ch));
    }
    
    int fgetc(FILE *f) {                /* blocking */
      while (ITM_CheckChar() != 1);
      return (ITM_ReceiveChar());
    }
    
    int ferror(FILE *f) {
      /* Your implementation of ferror */
      return EOF;
    }
    
    void _ttywrch(int ch) {
      ITM_SendChar(ch);
    }
    
    void _sys_exit(int return_code) {
    label:  goto label;  /* endless loop */
    }
    

    Do not use MicroLib if you are using scanf(..)

    Best Regards,
    Martin Günther

  • Hello Martin Günther,

    Thank you very much for your help. I add your retarget.c into my project and use following codes:

    volatile unsigned char str='\0';
    main()
    {
      for (;;)
      {
        scanf("%s\n",&str);
        ITM_SendChar(str);
      }
    }
    

    I connect A2F dev kit to PC using ulink2 first.
    when the program runs in flash target, I place mouse in debug(pringf) windows and then click the key "p" in the keyboard and find :

    (1) no character displayed in debug(pringf) windows
    (2) when I open memory window 1 and try to observe it using &str commander, I still find that the data is always 0

    it seems that no character from Debug (printf) Viewer window is read to ITM_RxBuffer.

    Could you please post your test codes here? can scanf() be used in simulation mode only? thanks a lot.

    Fisher Cheng

  • So all do ever do is to get a single string for each input line? Why then don't you use the gets() function, that (in Keils edition) takes a parameter specifying the size of your buffer?

    But the worst problem - str is expected to be a string. But your declaration is a character. Taking the address of the character and send into sprintf() means that sprintf() only have a valid if it is expected to retrieve a zero-length string (i.e. a string only storing the termination character).

    You must definitely need to make:

    enum {
        BUF_SIZE = 64,
    };
    char str[BUF_SIZE];
    


    Now you have a buffer that can fit 0 to 63 characters + a termination.

    And with gets() you can send BUF_SIZE as parameter, making sure that gets() does never allow you to overflow the buffer.

  • Hello Fischer Cheng,

    I only tested the code using the uVision simulator. But if I get a SamrtFusion board I will test it of course using real HW.

    I used the following test code:

    #include <stdio.h>
    #include "a2fxxxm3.h"                   /* A2FxxxM3x definitions              */
    
    
    
    volatile uint32_t msTicks;                            /* counts 1ms timeTicks */
    /*----------------------------------------------------------------------------
      SysTick_Handler
     *----------------------------------------------------------------------------*/
    void SysTick_Handler(void) {
      msTicks++;                        /* increment counter necessary in Delay() */
    }
    
    /*------------------------------------------------------------------------------
      delays number of tick Systicks (happens every 1 ms)
     *------------------------------------------------------------------------------*/
    __INLINE static void Delay (uint32_t dlyTicks) {
      uint32_t curTicks;
    
      curTicks = msTicks;
      while ((msTicks - curTicks) < dlyTicks);
    }
    
    
    /*----------------------------------------------------------------------------
      MAIN function
     *----------------------------------------------------------------------------*/
    int main (void) {
      FILE *dbgIn;
      unsigned char c;
      unsigned char str[20];
    
    
      SysTick_Config(SystemCoreClock / 1000);
    
      printf ("Example demonstrating CMSIS Debug Functions\r\n\r\n");
    
      while(1) {
        printf ("Press a key. ");
        c = fgetc(dbgIn);
        printf ("\r\n");
        printf ("You pressed '%c'.\r\n\r\n", c);
    
        Delay(10);
    
        printf ("Enter string (press Return to finish) ");
        scanf("%s", str);
        printf ("\r\n");
        printf ("You entered '%s'.\r\n\r\n", str);
    
        Delay(10);
      }
    
    }
    
    

    Best Regards,
    Martin Guenther

  • Hello Martin Günther,

    Thank you very much. Yes, It works even in real hardware.

    You are so kind.

    Have a nice weekend.

    Hello Per Westermark and Andrew Neil,

    also, Thank a lot for your kindly help.
    wish you both a nice weekend.

    Best regards,
    Fisher Cheng

  • So how do you ensure that the data returned by scanf doesn't exceed 9 characters (or whatever your array size happens to be) ?

    "%9s"

  • I asked how he did ensure it - not how he could (or should) have ensured it...