Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

ATMEGA328-PU EEPROM programming

Status
Not open for further replies.

ynos0104

Newbie level 6
Joined
Sep 12, 2012
Messages
14
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,432
Hi Everyone,

I am new to microcontrollers and by following some online tutorials I was able to make an embedded webserver using ATmega328-pu and ENC28J60 chips. The webserver is working fine with a basic passcode authentication.

My problem now is I want the user to be able to change the passcode. Currently the passcode is hardcoded in the system. I search google and found out that I can use EEPROM as a storage for the new passcode.

I also found some basic tutorial using EEPROM but for some reasons it is not working well for me.

Here are some of the codes that I used:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uint16_t EEMEM e_newpass[10]; //eeprom variable
static char mypass[10] = "secret"; //default passcode
 
 
//inside main()
char newpass[10] = "test";
 
//write to eeprom
eeprom_write_block((void *)newpass,(void *)&e_newpass,sizeof(newpass));
 
//read from eeprom
eeprom_read_block((void *)mypass,(void*)&e_newpass,sizeof(mypass)); 
 
//code for webserver and simple authentication below...



I am replacing the value of newpass to mypass from eeprom but for some reason this is not working for me. I would appreciate any help.

Also, it is not clear to me where in the uC the codes (c language --> hex) are being saved. Is it also saved in the eeprom?

Thanks.
 

Code:
(void *)&e_newpass

That is not correct , e_newpass already point to the address of the array , you either use e_newpass or &e_newpass[0]

Also, it is not clear to me where in the uC the codes (c language --> hex) are being saved. Is it also saved in the eeprom?
Not sure what you mean, the hex content is stored in the flash memory, the eeprom data are in the eep file and saved in the eeprom (when there are initialization values)

- - - Updated - - -

That is not correct , e_newpass already point to the address of the array , you either use e_newpass or &e_newpass[0]

Actually I have tested both read and write and it works both ways, using e_newpass or &e_newpass
 

Interesting...

I just can't figure out what seems to be the problem. Using the code above, when I displayed mypass on the webpage, if I'm not getting garbage characters, I am getting different values from my html code...

I am quite new with C language programming especially with microcontrollers so I might be displaying it wrong. Would you be able to share a function to display mypass on a web page?

Will this kind of code will work:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
//display mypass
uint8_t print_webpage_mypass(char *str)
gPlen = fill_tcp_data_p(buf,gPlen,PSTR("<h1>str:"));
gPlen = fill_tcp_data_p(buf,gPlen,str);
gPlen = fill_tcp_data_p(buf,gPlen,PSTR("</h1>"));
}
 
//inside main()
 
print_webpage_mypass(mypass); //mypass from eeprom



I just can't provide the actual codes that I'm using as my board accidentally burned (wrong power adapter :( ). Once I finished rebuilding it, I will paste the actual codes here and the result I am getting.

Thanks for getting back at me. Hopefully this week I can finish rebuilding my board.
 

You didn't provide a function definition but I was able to find it in the tuxgraphics project http://tuxgraphics.org/electronics/200905/embedded-tcp-ip-stack.shtml

Is it this one?

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// fill in tcp data at position pos. pos=0 means start of
// tcp data. Returns the position at which the string after
// this string could be filled.
uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const prog_char *progmem_s)
{
        char c;
        // fill in tcp data at position pos
        //
        // with no options the data starts after the checksum + 2 more bytes (urgent ptr)
        while ((c = pgm_read_byte(progmem_s++))) {
                buf[TCP_CHECKSUM_L_P+3+pos]=c;
                pos++;
        }
        return(pos);
}

 

Yes that's it. Sorry I am not aware that it is tuxgraphics only library, I thought it is part of the AVRlib.
I am using the codes from tuxgraphics for the webserver with enc28j60. Also, I am using crosspack for mac and xcode.

Other than the missing bracket, is there something wrong on what I'm doing?

The new components will be coming in today, so hopefully, I can finish rebuilding my board by tomorrow.

Until then...
 

The function is intended to read flash located arrays
Code:
c = pgm_read_byte(progmem_s++)

For RAM located array the pgm_read_byte should be removed
Code:
c = *progmem_s++
 

Finally, I managed to to rebuild my board.

It seems that reading and writing to EEPROM was not the problem but how I display it.

This code worked for me!

Code C - [expand]
1
c = *progmem_s++



My question now is how can I check if eeprom is empty or not.

I need to check if e_passcode[10] is empty or not. If it is not empty, read e_passcode then assign it to passcode else use the default passcode then use the code below for authentication.

Here is my code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
static char passcode[10]="secret"; //default passcode
static char EEMEM e_passcoed[10];
 
//if condition goes here...
 
uint8_t verify_password(char *str)
{
    if (strncmp(mp,str,strlen(mp))==0){
        return(1);
    }
    return(0);
}



Thanks in advance.
 

My question now is how can I check if eeprom is empty or not.

You can create another eeprom byte variable and use it as a flag, for example set it to 1 when you write the password and then check if it is 1 to see if a password has been written
Note that the default content of the eeprom is 0xff.
 
Sorry to be a pain, but I ran into another problem. I can write to eeprom with the codes below without any problem but I am having a difficulty reading it and use for authentication:


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#define read_eeprom_byte(address) eeprom_read_byte ((const uint8_t*)address) //any other way to do this other than declare?
#define write_eeprom_byte(address,value) eeprom_update_byte ((uint8_t*)address,(uint8_t)value) //this as well?
static char passcode[10] = "secret" //default password
static char EEMEM e_passcode[10];
static char EEMEM e_passcode_check_byte;
 
uint8_t verify_password(char *str)
{
    if (strncmp(passcode,str,strlen(passcode))==0){
        return(1);
    }
    return(0);
}
 
void eeprom_set_newpasscode(char *pass)
{
    uint8_t c=1;
    write_eeprom_byte(&e_passcode_check_byte,c);
    eeprom_update_block((void *)pass,(void *)e_passcode,sizeof(pass));       
}
 
void eeprom_get_newpasscode(void)
{
    char c[10];
    if(read_eeprom_byte(&e_passcode_check_byte)==1){
        eeprom_read_block((void *)c,(void *)e_passcode,sizeof(c));
        return(c);
    }
}
 
//inside main
 
char newpass[10] = "test";
 
eeprom_set_newpasscode(newpass);
 
passcode = eeprom_get_newpasscode();  //set the new passcode from eeprom to passcode



This code won't compile with this error message:

avr-gcc -g -mmcu=atmega328p -Wall -W -Os -mcall-prologues -I. -Os -c main.c
In file included from main.c:19:0:
ip_arp_udp_tcp.h:46:1: warning: 'prog_char' is deprecated: prog_char type is deprecated. [-Wdeprecated-declarations]
main.c:74:1: warning: 'prog_char' is deprecated: prog_char type is deprecated. [-Wdeprecated-declarations]
main.c: In function 'eeprom_get_newpasscode':
main.c:119:9: warning: 'return' with a value, in function returning void [enabled by default]
main.c: In function 'main':
main.c:307:7: error: void value not ignored as it ought to be
make: *** [main.o] Error 1

I tried changing the function from void to char


Code C - [expand]
1
2
3
4
5
6
7
8
char eeprom_get_newpasscode(void)
{
    char c[10];
    if(read_eeprom_byte(&e_passcode_check_byte)==1){
        eeprom_read_block((void *)c,(void *)e_passcode,sizeof(c));
        return(c);
    }
}



and here is the error message that I got:

avr-gcc -g -mmcu=atmega328p -Wall -W -Os -mcall-prologues -I. -Os -c main.c
In file included from main.c:19:0:
ip_arp_udp_tcp.h:46:1: warning: 'prog_char' is deprecated: prog_char type is deprecated. [-Wdeprecated-declarations]
main.c:74:1: warning: 'prog_char' is deprecated: prog_char type is deprecated. [-Wdeprecated-declarations]
main.c: In function 'eeprom_get_newpasscode':
main.c:119:9: warning: return makes integer from pointer without a cast [enabled by default]
main.c:119:9: warning: function returns address of local variable [enabled by default]
main.c: In function 'main':
main.c:307:7: error: incompatible types when assigning to type 'char[10]' from type 'char'
main.c: In function 'eeprom_get_newpasscode':
main.c:121:1: warning: control reaches end of non-void function [-Wreturn-type]
make: *** [main.o] Error 1


I only wanted to be able to save a new passcode to eeprom. If the new passcode is set, use it, if not use the default.

Thanks again and sorry for testing your patience.
 

In the first line you are missing a semicolon, I hope this is just a type in this post and not in the code
Code:
static char passcode[10] = "secret" //default password

Code:
char eeprom_get_newpasscode(void)
{
    char c[10];
    if(read_eeprom_byte(&e_passcode_check_byte)==1){
        eeprom_read_block((void *)c,(void *)e_passcode,sizeof(c));
        return(c);
    }
}

There are a couple of problems with that.

main.c:119:9: warning: return makes integer from pointer without a cast [enabled by default]
main.c:119:9: warning: function returns address of local variable [enabled by default]
The return type of the function is char but what you return is a pointer to array c which is incompatible.
The pointer to array c is invalid as soon as you exit the function because c is an local array.

warning: control reaches end of non-void function [-Wreturn-type]
You have placed the return inside an in condition blobk, if the condition is false then the return will never be reached

warning: 'prog_char' is deprecated: prog_char type is deprecated
You get the warning for use of prog_char in
Code:
uint16_t fill_tcp_data_p(uint8_t *buf,uint16_t pos, const [COLOR="#FF0000"]prog_char[/COLOR] *progmem_s)
{
        char c;
        // fill in tcp data at position pos
        //
        // with no options the data starts after the checksum + 2 more bytes (urgent ptr)
        while ((c = pgm_read_byte(progmem_s++))) {
                buf[TCP_CHECKSUM_L_P+3+pos]=c;
                pos++;
        }
        return(pos);
}
This can be omitted but the code will compile as it is without a problem , you will just get a few warnings.

The reported error is
main.c:307:7: error: incompatible types when assigning to type 'char[10]' from type 'char'
and you get is for this line
Code:
passcode = eeprom_get_newpasscode();
because you try to assign a char (that is the return type of the function) to an array pointer (passcode)
 

Thanks for the reply.

For now, I can live with the warnings :), my main concern is how can I assign the value of the eeprom_get_newpasscode() to a variable so I can use it for my authentication?

Is there anything I need to change on my function in order to do this:

Code C - [expand]
1
passcode = eeprom_get_newpasscode();



Or some other way to achieve what I'm trying to do.

Sorry for asking too much and thanks a lot for all the help.
 

passcode is a global variable so you can access it from within the function.
Maybe something like
Code:
unsigned char eeprom_get_newpasscode(void)
{
    if(read_eeprom_byte(&e_passcode_check_byte) == 1)
    {
        eeprom_read_block((void *)passcode, (void *)e_passcode, sizeof(passcode));  // read code directly to passcode
        return(1);  // return 1 if passcode was changed
    }
    else
    {
        return 0;  // return 0 is passcode was not changed
    }
}

Then you can use
Code:
if (eeprom_get_newpasscode())
{
// new pass has been loaded to passcode
}
else
{
// no new passcode (default used)
}
 

Thanks.

Will give it a try tonight.
 

Sorry for the very late reply, been busy with school and work.

For some reasons this function is not working for me:

Code C - [expand]
1
2
3
4
5
void eeprom_set_passcode(char * pass)
{
         eeprom_update_block((void *)pass,(void *)&e_passcode,sizeof(pass));
         write_eeprom_byte(&e_passcode_check_byte,1);
}



But if I use this command directly, outside the function, it works.


Code C - [expand]
1
2
3
char * pass[10]="test";
eeprom_update_block((void *)pass,(void *)&e_passcode,sizeof(pass));
write_eeprom_byte(&e_passcode_check_byte,1);


Anyway, the code is working now, I just can't use a function to make it reusable so thanks a lot for all the help!

I am now working on putting my webserver behind a router then just do port forwarding to access from the internet. Will open a new thread for this.
 

Code:
char * pass[10]="test";
This an array of 10 pointers , is this what you want?

I would use a char array
Code:
char pass[10]="test";

Then call the function using the address of the first character
Code:
eeprom_set_passcode(pass);
//or
eeprom_set_passcode(&pass[0]);
 

Code:
char * pass[10]="test";

Sorry this is a typo. It should be

Code C - [expand]
1
char pass[10];


Code:
eeprom_set_passcode(&pass[0]);
I think this is what I need.

Can you please recommend any good book for this. It seems that most of my problems are syntax related.

Thanks.
 


Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top