I'm trying to learn about embedded programming, so I bought an arduino mega2560. I didn't really like the arduino IDE (Because it feels a little too basic and abstracted, at least for me :)) so I started programming it using pure C and the avr toolkit (avrdude and such). I'm trying to write a program that reads your name, and then blinks the LED for each character in your name.
The program's basic outline is:
- Turn the LED pin to output mode
- **printf() "Enter your name"
- **Read the user's name using fgetc, realloc and such (I'm not using scanf() because scanf() with a buffer can cause a buffer overflow)
- Blink the LED for each character in the user's name
The problems (Indicated by **) are that I can't see printf's output and fgetc asking for input. How to fix this?
Thanks!
Edit: Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/io.h>
#include <util/delay.h>
#ifndef STDIN
#define STDIN 0
#endif
int main(void) {
char *name = (char *)malloc((int)NULL);
char c;
int cnt;
int i;
cnt = 1;
DDRB |= (1 << DDB7);
printf("Enter your name: ");
while ((c = fgetc(STDIN)) != '\n') {
name = (char *)realloc(name, cnt);
strncat(name, &c, 1);
cnt ;
}
for (i = 0; i < strlen(name); i) {
PORTB |= (1 << PB7);
_delay_ms(1000);
PORTB &= ~(1 << PB7);
}
return 0;
}
CodePudding user response:
char *name = (char *)malloc((int)NULL);
this makes no sense at all. You basically allocated 0 bytes to name. Also do not cast malloc results.- On this micros never use
malloc
type dynamic allocation. It is not a PC computer and you need to forget many "large" computer stuff; - What is your STDIN on such a target?
- What is your stdout on this micro?
strncat(name, &c, 1);
it's weird. And it will not work as nono of your parameters are C strings. Do you know what the last parameter is?strlen
will not work as you do not pass C string.
I didn't really like the arduino IDE (Because it feels a little too basic and abstracted, at least for me :))
I think at your level of knowledge it is the correct direction. Arduino is C libraries and it is not "simple"
Yeah I got no errors. I included stdio.h which implements printf and fgetc
Adding the header file does not sort the problem. You need to write some low-level functions to stdio
functions start to work. stdout
and stdin
do not communicate via UART by default. Read some more: https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#ga4c04da4953607fa5fa4d3908fecde449
CodePudding user response:
The stdio library for MCUs where the stdout
, stdin
need not exist at all and where they do they are necessarily dependent on the hardware and available I/O and are design decisions of the project developer not the responsibility of the library designer.
Typically for an embedded library there will be a porting or "glue" layer to map the library to the hardware dependencies, and if you do not supply the necessary functions they will be linked to generic "do nothing" stubs.
The specific stub-function overrides you need to provide will depend of the toolchain and specifically the C library you are using. And the means by which you "install" them differs depending on the toolchain. Some use "weak-links" that you simply provide overrides with the same signature, others use structures with function pointers to the low-level I/O functions.
For example if you are using AVR Libc, you simply need to provide a get-char / put-char functions use them in a FILE
structure assigned ot the stdin
, stdout
streams as described in the documentation.
For example:
#include <stdio.h>
// Output character to stdout device
static int std_putchar(char c, FILE *stream)
{
...
return 0;
}
// Input character from stdin device
static int std_getchar(char c, FILE *stream)
{
...
return rxchar ;
}
// Create stdio stream
static FILE stdio_stream = FDEV_SETUP_STREAM( std_putchar, std_getchar,
_FDEV_SETUP_RW ) ;
int main(void)
{
stdout = &stdio_stream ;
stdin = &stdio_stream ;
stderr = &stdio_stream ;
printf( "System Start - hello\n") ;
// Echo input
for(;;)
{
putchar( getchar() ) ;
}
}
You can implement the low level character I/O functions in any way you wish to suit your system, to use a UART, keypad, LCD display, debugger interface - whatever.