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
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
"%9s"
I asked how he did ensure it - not how he could (or should) have ensured it...