[En-Nut-Discussion] Problem with write eeprom

Brett Abbott Brett.Abbott at digital-telemetry.com
Mon Jan 9 00:46:29 CET 2006


Stoffel

Im unsure if this has been replied to as Im a bit behind in my list 
reading.  Im unsure of your symptoms but I have resolved an issue which 
may happen with your code.

If you are finding the watchdog is resetting during your eeprom 
write/read, you may find that this is due to the size of your eeprom 
writes.  Often a WDR is not issued in the middle of large eeprom writes 
or reads.  By comparison to sram, eeprom activities are extremly slow 
and you may find that you get Watch dog resets, often at different 
times.  Have a look at the atmel data sheet and multiply the write time 
by the number of bytes, you will be surprised at how long it takes - it 
can be easy to even exceed the longest watch dog timeout.

Quick fix is to WDR before and after.  More rugged solution and for 
larger eeprom string/records, you need to WDR more often, ie. in between 
each (or group of) byte.

Cheers
Brett

Stoffel Armin wrote:

> I have still a problem with the EEPROM.
> I arranged a test routine.
> Problems:
> 1. The restart (wdt_reset) after the SetIP functioned not
> 2. After Ethernut switch off/on are again the default values
> 3. With NutRegisterAuth give there it with the password also a problem
>
> The whole must be connected nevertheless with the EEPROM.
> Can someone the program look at itself and me help?
> Ethernut2.1b Nut/OS 3.9.9
>
> Program:
> -------------------------------------------------------------------------------------------- 
>
>
> #define MYMAC       0x00, 0x06, 0x98, 0x21, 0x04, 0xB3
> #define MYIP        "192.168.1.2"
> #define MYMASK      "255.255.255.0"
> #define MYGATEWAY   "192.168.1.1"
>
>
> #include <cfg/os.h>
>
> #include <string.h>
> #include <io.h>
>
> #include <dev/board.h>
> #include <dev/urom.h>
>
> #include <sys/version.h>
> #include <sys/thread.h>
> #include <sys/timer.h>
> #include <sys/heap.h>
> #include <sys/confnet.h>
> #include <sys/socket.h>
>
> #include <arpa/inet.h>
>
> #include <pro/httpd.h>
> #include <pro/dhcp.h>
>
> #include <net/route.h>
>
> #include <avr/wdt.h>
>
> #define wdt_reset()   __asm__ __volatile__ ("wdr")
>
> #define EE_OFFSET   512
>
> static char *html_mt = "text/html";
>
> static prog_char navigation[] = "<td width=\"150\" valign=\"top\" 
> bgcolor=\"E6E6E6\">"
>    "<a href=\"/cgi-bin/setip.cgi\">Set IP</a><br>"
>    "<a href=\"/cgi-bin/allowip.cgi\">Allow IP</a><br>"
>    "<a href=\"/cgi-bin/password.cgi\">Change Password</a>"
>    
> "<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></td>" 
>
>    "<td valign=\"top\" align=\"center\">";
>
> static prog_char foot[] = "</table><br>"
>    " <input type=\"submit\" value=\" Set \"> "
>    " <input type=\"reset\" value=\" Cancel \"> "
>    "</form>\r\n</td>\r\n</tr>\r\n</table>\r\n</body>\r\n</html>";
>
> /*
> * Save a string into the EEPROM.
> */
> int ConfigSaveString(int addr, u_char * str)
> {
>    int rc = 0;
>    do {
>        if (eeprom_read_byte((void *) (EE_OFFSET + addr + rc)) != *str)
>            eeprom_write_byte((void *) (EE_OFFSET + addr + rc), *str);
>        rc++;
>    } while (*str++);
>
>    return rc;
> }
>
> /*
> * Read a string from EEPROM.
> */
> size_t ConfigLoadString(int addr, u_char * str, size_t size)
> {
>    size_t rc = 0;
>
>    while (rc < size) {
>        *str = eeprom_read_byte((void *) (EE_OFFSET + addr + rc));
>        rc++;
>        if (*str++ == 0)
>            break;
>    }
>    if (*str != 0)
>        *str++ = 0;
>    return rc;
> }
>   
> /********************************************************************************************************/ 
>
> /* CGI                                                                 
>                                    */
> /********************************************************************************************************/ 
>
>
> int SetIp(FILE * stream, REQUEST * req)
> {
>    static prog_char head[] = "<html>"
>                            "<head>"
>                            "<meta http-equiv=\"expires\" content=\"0\">"
>                            "<title>Set IP</title>"
>                            "</head>"
>                            "<body bgcolor=\"#FFFFFF\">"
>                            "<table width=\"100%\" border=\"0\">"
>                            "<tr>";
>    static prog_char thdr[] = "<form action=\"setip.cgi\" 
> enctype=\"text/plain\">"
>                              "<table border=\"0\" cellspacing=\"0\">\r\n"
>                              "<tr align=\"center\">\r\n<th 
> colspan=\"2\">Set IP</th>\r\n</tr>\r\n";
>
>
>    NutHttpSendHeaderTop(stream, req, 200, "Ok");
>    NutHttpSendHeaderBot(stream, html_mt, -1);
>
>    fputs_P(head, stream);
>    fputs_P(navigation, stream);
>      if (NutHttpGetParameterCount(req) == 3){
>        confnet.cdn_ip_addr = inet_addr(NutHttpGetParameterValue(req, 0));
>        confnet.cdn_ip_mask = inet_addr(NutHttpGetParameterValue(req, 1));
>        confnet.cdn_gateway = inet_addr(NutHttpGetParameterValue(req, 2));
>        NutNetSaveConfig();
>              fprintf(stream,"<b>New IP-Adress: <a 
> href=http://%s>%s</a><br>", NutHttpGetParameterValue(req, 0), 
> NutHttpGetParameterValue(req, 0));
>        fprintf(stream,"<b>New Mask: %s<br>", 
> NutHttpGetParameterValue(req, 1));
>        fprintf(stream,"<b>New Gateway: %s<br><br>REBOOT...</b>", 
> NutHttpGetParameterValue(req, 2));
>        fprintf(stream,"\r\n</div></body>\r\n</html>");
>        fflush(stream);
>        wdt_reset();
>        wdt_enable(1);
>        while(1);
>    } else{
>        fputs_P(thdr, stream);
>        fprintf(stream,"<tr align=\"left\">\r\n<th>IP</th><td><input 
> maxLength=\"15\" size=\"20\" name=\"ip\" value=\"");
>        fprintf(stream, "%s", inet_ntoa(confnet.cdn_ip_addr));
>        fprintf(stream,"\"></td></tr>");
>              fprintf(stream,"<tr 
> align=\"left\">\r\n<th>Mask</th><td><input maxLength=\"15\" 
> size=\"20\" name=\"mask\" value=\"");
>        fprintf(stream, "%s",inet_ntoa(confnet.cdn_ip_mask));
>        fprintf(stream,"\"></td></tr>");
>              fprintf(stream,"<tr 
> align=\"left\">\r\n<th>Gateway </th><td><input maxLength=\"15\" 
> size=\"20\" name=\"gateway\" value=\"");
>        fprintf(stream, "%s",inet_ntoa(confnet.cdn_gateway));
>        fprintf(stream,"\"></td></tr>");
>
>        fputs_P(foot, stream);
>    }
>    fflush(stream);
>    return 0;
> }
>
> int AllowIp(FILE *stream, REQUEST *req)
> {      static prog_char head[] = "<html>"
>                            "<head>"
>                            "<meta http-equiv=\"expires\" content=\"0\">"
>                            "<title>Set Allow IP</title>"
>                            "</head>"
>                            "<body bgcolor=\"#FFFFFF\">"
>                            "<table width=\"100%\" border=\"0\">"
>                            "<tr>";
>    static prog_char thdr[] = "<form action=\"allowip.cgi\" 
> enctype=\"text/plain\">"
>                              "<table border=\"0\" cellspacing=\"0\">\r\n"
>                              "<tr align=\"center\">\r\n<th 
> colspan=\"4\">Set Allow IP</th>\r\n</tr>\r\n";
>
>    int i;
>    NutHttpSendHeaderTop(stream, req, 200, "Ok");
>    NutHttpSendHeaderBot(stream, html_mt, -1);
>
>    fputs_P(head, stream);
>    fputs_P(navigation, stream);
>    fputs_P(thdr, stream);
>      char ip[16] = "000.000.000.000";
>      if (NutHttpGetParameterCount(req) == 10){          for(i=0; i < 
> 10; i++){
>            ConfigLoadString(5 + (i*20),ip,15);
>            if (strcmp(ip,NutHttpGetParameterValue(req, i))!=0)   
>                ConfigSaveString(5 + 
> (i*20),NutHttpGetParameterValue(req, i));
>        }
>    }
>      for(i=0; i < 5; i++){
>        fprintf(stream,"<tr align=\"left\">\r\n<th>IP 
> %i </th><td><input maxLength=\"15\" size=\"20\" name=\"ip%i\" 
> value=\"",i+1,i+1);
>        ConfigLoadString(5 + (i*40),ip,15);
>        fprintf(stream, "%s\"", ip);
>        fprintf(stream,"\"></td>");
>        fprintf(stream,"\r\n<th> Mask %i </th><td><input 
> maxLength=\"15\" size=\"20\" name=\"mask%i\" value=\"",i+1,i+1);
>        ConfigLoadString(25 + (i*40),ip,15);
>        fprintf(stream, "%s\"", ip);
>        fprintf(stream,"\"></td></tr>");
>    }
>      fputs_P(foot, stream);
>    fflush(stream);
>    return 0;
> }
>
> int Password(FILE *stream, REQUEST *req)
> {
>    static prog_char head[] = "<html>"
>                            "<head>"
>                            "<meta http-equiv=\"expires\" content=\"0\">"
>                            "<title>Set Password</title>"
>                            "</head>"
>                            "<body bgcolor=\"#FFFFFF\">"
>                            "<table width=\"100%\" border=\"0\">"
>                            "<tr>";
>    static prog_char thdr[] = "<form action=\"password.cgi\" 
> enctype=\"text/plain\">"
>                              "<table border=\"0\" cellspacing=\"0\">\r\n"
>                              "<tr align=\"center\">\r\n<th 
> colspan=\"2\">Set Password</th>\r\n</tr>\r\n";
>
>
>    NutHttpSendHeaderTop(stream, req, 200, "Ok");
>    NutHttpSendHeaderBot(stream, html_mt, -1);
>
>    fputs_P(head, stream);
>    fputs_P(navigation, stream);
>    fputs_P(thdr, stream);
>          if (NutHttpGetParameterCount(req) == 3){          char 
> password[16] = "";
>        ConfigLoadString(205,password,15);          if 
> (strcmp(NutHttpGetParameterValue(req, 0),password) == 0){
>            if (strcmp(NutHttpGetParameterValue(req, 1),"") != 0){
>                if (strcmp(NutHttpGetParameterValue(req, 
> 1),NutHttpGetParameterValue(req, 2)) == 0){
>                    ConfigSaveString(205,NutHttpGetParameterValue(req, 
> 1));
>                    fprintf(stream,"<tr align=\"left\">\r\n<td 
> align=\"center\" colspan=\"2\">Password 
> changed<br><br><b>REBOOT...</b></td></tr>");
>                    fflush(stream);
>                    wdt_enable(1);
>                    wdt_reset();
>                    while(1);
>                } else {
>                    fprintf(stream,"<tr align=\"left\">\r\n<td 
> align=\"center\" colspan=\"2\">Retype Password incorrect!</td></tr>");
>                }
>            } else {
>                fprintf(stream,"<tr align=\"left\">\r\n<td 
> align=\"center\" colspan=\"2\">New Password empty</td></tr>");
>            }
>        } else {
>                fprintf(stream,"<tr align=\"left\">\r\n<td 
> align=\"center\" colspan=\"2\">Password incorrect</td></tr>");
>        }
>    }
>                    fprintf(stream,"<tr align=\"left\">\r\n<th>Old 
> Password</th><td><input type=\"password\" maxLength=\"15\" size=\"20\" 
> name=\"old\" value=\"");
>    fprintf(stream,"\"></td></tr>");
>      fprintf(stream,"<tr align=\"left\">\r\n<th>New 
> Password</th><td><input type=\"password\" maxLength=\"15\" size=\"20\" 
> name=\"new1\" value=\"");
>    fprintf(stream,"\"></td></tr>");
>      fprintf(stream,"<tr align=\"left\">\r\n<th>Retype 
> Password</th><td><input type=\"password\" maxLength=\"15\" size=\"20\" 
> name=\"new2\" value=\"");
>    fprintf(stream,"\"></td></tr>");
>      fputs_P(foot, stream);
>    fflush(stream);
>    return 0;
> }
>
> /*! \fn Service(void *arg)
> * \brief HTTP service thread.
> *
> * The endless loop in this thread waits for a client connect,
> * processes the HTTP request and disconnects. Nut/Net doesn't
> * support a server backlog. If one client has established a
> * connection, further connect attempts will be rejected.
> * Typically browsers open more than one connection in order
> * to load images concurrently. So we run this routine by
> * several threads.
> *
> */
> THREAD(Service, arg)
> {
>    TCPSOCKET *sock;
>    FILE *stream;
>
>    /*
>     * Now loop endless for connections.
>     */
>    for (;;) {
>
>        /*
>         * Create a socket.
>         */
>        if ((sock = NutTcpCreateSocket()) == 0) {
>            NutSleep(5000);
>            continue;
>        }
>
>        /*
>         * Listen on port 80. This call will block until we get a 
> connection
>         * from a client.
>         */
>        NutTcpAccept(sock, 80);
>
>        /*
>         * Wait until at least 8 kByte of free RAM is available. This will
>         * keep the client connected in low memory situations.
>         */
>        while (NutHeapAvailable() < 8192) {
>            NutSleep(1000);
>        }
>
>        /*
>         * Associate a stream with the socket so we can use standard 
> I/O calls.
>         */
>        if ((stream = _fdopen((int) ((uptr_t) sock), "r+b")) != 0) {
>            /*
>             * This API call saves us a lot of work. It will parse the
>             * client's HTTP request, send any requested file from the
>             * registered file system or handle CGI requests by calling
>             * our registered CGI routine.
>             */
>            NutHttpProcessRequest(stream);
>
>            /*
>             * Destroy the virtual stream device.
>             */
>            fclose(stream);
>        }
>
>        /*
>         * Close our socket.
>         */
>        NutTcpCloseSocket(sock);
>    }
> }
>
> /*!
> * \brief Main application routine.
> *
> * Nut/OS automatically calls this entry after initialization.
> */
> int main(void)
> {
>    u_char i;
>
>    /*
>     * Register Ethernet controller.
>     */
>    NutRegisterDevice(&DEV_ETHER, 0, 0);
>
>    /*
>     * LAN configuration using EEPROM values or DHCP/ARP method.
>     * If it fails, use fixed values.
>     */
>          if (PIND & 0x01 || NutDhcpIfConfig("eth0", 0, 60000)) {
>        u_char mac[] = { MYMAC };
>        u_long ip_addr = inet_addr(MYIP);
>        u_long ip_mask = inet_addr(MYMASK);
>        u_long ip_gate = inet_addr(MYGATEWAY);
>        ConfigSaveString(5,"192.168.1.2");
>        ConfigSaveString(25,"255.255.255.0");
>        ConfigSaveString(45,"000.000.000.000");
>        ConfigSaveString(65,"000.000.000.000");
>        ConfigSaveString(85,"000.000.000.000");
>        ConfigSaveString(105,"000.000.000.000");
>        ConfigSaveString(125,"000.000.000.000");
>        ConfigSaveString(145,"000.000.000.000");
>        ConfigSaveString(165,"000.000.000.000");
>        ConfigSaveString(185,"000.000.000.000");
>        ConfigSaveString(205,"1234");
>        NutNetIfConfig2("eth0", mac, ip_addr, ip_mask, ip_gate);      }
>          /*
>     * Register our device for the file system.
>     */
>    NutRegisterDevice(&devUrom, 0, 0);
>
>    /*
>     * Finally a CGI example to process a form.
>     */
>    NutRegisterCgi("setip.cgi", SetIp);
>    NutRegisterCgi("allowip.cgi", AllowIp);
>    NutRegisterCgi("password.cgi", Password);
>
>    char password[16] = "";
>    char dummy[60]="";
>      ConfigLoadString(205,password,15);
>      sprintf(dummy,"root:%s", password);
>      NutRegisterAuth("cgi-bin", dummy);        /*
>     * Start four server threads.
>     */
>    for (i = 1; i <= 4; i++) {
>        char *thname = "httpd0";
>
>        thname[5] = '0' + i;
>        NutThreadCreate(thname, Service, (void *) (uptr_t) i, 
> NUT_THREAD_MAINSTACK);
>    }
>
>    /*
>     * We could do something useful here, like serving a watchdog.
>     */
>    NutThreadSetPriority(254);
>    for (;;)
>        NutSleep(60000);
> }
>
>
> _______________________________________________
> En-Nut-Discussion mailing list
> En-Nut-Discussion at egnite.de
> http://www.egnite.de/mailman/listinfo.cgi/en-nut-discussion
>
>

-- 
-----------------------------------------------------------------
Brett Abbott, Managing Director, Digital Telemetry Limited
Email: Brett.Abbott at digital-telemetry.com
PO Box 24 036 Manners Street, Wellington, New Zealand
Phone +64 (4) 5666-860  Mobile +64 (21) 656-144
------------------- Commercial in confidence --------------------





More information about the En-Nut-Discussion mailing list