]> rtime.felk.cvut.cz Git - CanFestival-3.git/commitdiff
ADDED LED to TESTMASTERSLAVE. It looks nice!
authororemeq <oremeq>
Fri, 12 May 2006 20:14:03 +0000 (20:14 +0000)
committeroremeq <oremeq>
Fri, 12 May 2006 20:14:03 +0000 (20:14 +0000)
Some code for the NVRAM support

17 files changed:
drivers/Makefile.in
drivers/can_virtual/Makefile.in
drivers/can_virtual/led_virtual.c
drivers/ecos_lpc2138_sja1000/canOpenDriver.c
drivers/ecos_lpc2138_sja1000/lpc2138.h
drivers/ecos_lpc2138_sja1000/lpc2138_pinout.h
drivers/ecos_lpc2138_sja1000/notes.txt [new file with mode: 0644]
drivers/ecos_lpc2138_sja1000/nvram.h [new file with mode: 0644]
drivers/ecos_lpc2138_sja1000/nvram_iap.c [new file with mode: 0644]
drivers/ecos_lpc2138_sja1000/nvram_iap.h [new file with mode: 0644]
drivers/ecos_lpc2138_sja1000/nvram_readme [new file with mode: 0644]
drivers/ecos_lpc2138_sja1000/sja1000.c
examples/TestMasterSlave/Makefile.in
include/can_driver.h
include/led.h
src/Makefile.in
src/led.c

index 3eca498f921f1e6d5692b1a074b833220a18d99c..68517cd5ca19ca091ca141bb764c3c3c97279c79 100644 (file)
@@ -24,6 +24,7 @@
 TARGET = SUB_TARGET
 CAN_DRIVER = SUB_CAN_DRIVER
 TIMERS_DRIVER = SUB_TIMERS_DRIVER
+LED_ENABLE = SUB_LED_ENABLE
 
 all: driver
 
index 7c49a2d3f1aea1bb3b3f2a7f862c6925a4fbb540..c79e8e0d0da9e444fde3a2613a9cf6e18be18747 100644 (file)
@@ -33,6 +33,7 @@ PREFIX = SUB_PREFIX
 TARGET = SUB_TARGET
 CAN_DRIVER = SUB_CAN_DRIVER
 TIMERS_DRIVER = SUB_TIMERS_DRIVER
+LED_ENABLE = SUB_LED_ENABLE
 
 INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER) -I../../include/$(TIMERS_DRIVER)
 
index ba28701ad6381397d1b8279f2afed363e56f4f31..271fcf12d0dae170b1efc855f3ca45ea8deff2bc 100644 (file)
@@ -1,20 +1,18 @@
 /***************************************************************************/
+#include <data.h>
 #include <led.h>
 
-void led_set_redgreen(CO_Data *d, int state)
+void led_set_redgreen(CO_Data *d, unsigned char state)
 {
-
-        printf("LEDS %d\n",bits);
-
-        if (bits & 0x01)
-                printf("\e[41m ERROR LED ON \e[m\n");
+        if (state & 0x01)
+                printf("\e[41m ERROR LED ON \e[m          ");
         else
-                printf("error led off\n");
+                printf("\e[31m error led off \e[m         ");
 
-        if (bits & 0x02)
+        if (state & 0x02)
                 printf("\e[34;42m RUN LED ON \e[m\n");
         else
-                printf("run led off\n");
+                printf("\e[32m run led off \e[m\n");
 }
 
 
index a359b5050e7e37a3e027715855b4a9ff1df3a141..ce94952443f7cf365417cc77c268e810b18d9c6d 100644 (file)
@@ -155,25 +155,66 @@ return : 0 if OK, 1 if error
 
 int nvram_open(void)
 {
+       int n = NVRAM_BLOCK_SIZE / sizeof(unsigned int);
+
        /* some actions to initialise the flash */
        data_len = 0;
+       data_num_pages = 0;
 
-       data_addr = 0; 
-
-       data_page = (unsigned int *)malloc(sizeof(unsigned int) * 64);
-       memset(data_page, 0, sizeof(unsigned int)*64);
+       data_page = (unsigned int *)malloc(sizeof(unsigned int) * n);
+       memset(data_page, 0, sizeof(unsigned int)*n);
 
        if (data_page == NULL)
                return -1;
 
+       regs_page = (unsigned int *)malloc(sizeof(unsigned int) * n);
+       memset(regs_page, 0, sizeof(unsigned int)*n);
+       if (regs_page == NULL)
+               return -2;
+
+       iat_flash_read_regs();
+
+       /* start the data at the location specified in the registers */ 
+       if (0) /* for now it is 0, but put here a test to know whether
+                  or not the NVRAM has been written before */
+               data_addr = regs_page[1];
+       else
+               data_addr = NVRAM_BLOCK_SIZE; /* let start at block 1 */
+
        return 0;
 }
 
 
 void nvram_close(void)
 {
+       /* write the last page before closing */
+       iat_flash_write_page(data_addr);
+
        /* some actions to end accessing the flash */
        free(data_page);
+
+       regs_page[4] = data_num_pages;
+       /* write the registers to the NVRAM before closing */
+       iat_flash_write_regs();
+       free(regs_page);
+}
+
+
+void nvram_set_pos(UNS32 pos)
+/* set the current position in the NVRAM to pos */
+{
+}
+
+
+void nvram_new_firmwave()
+{
+/*
+       this function is called whenever a new firmware is about
+       to be written in the NVRAM
+*/
+       data_addr = regs_page[1] + regs_page[4]*NVRAM_BLOCK_SIZE;
+       if (data_addr > NVRAM_MAX_SIZE)
+               data_addr = NVRAM_BLOCK_SIZE;
 }
 
 int _get_data_len(int type)
@@ -233,16 +274,22 @@ int _get_data_len(int type)
 }
 
 
-char nvram_write(int type, int access_attr, void *data)
+char nvram_write_data(int type, int access_attr, void *data)
 /* return 0 if successfull */
 {
        int len = _get_data_len(type);
 
-       if (data_len+len > 256)
+       if (data_len+len > NVRAM_BLOCK_SIZE)
        {
                iat_flash_write_page(data_addr);
                data_len = 0;
-               data_addr += 256;
+               data_addr += NVRAM_BLOCK_SIZE; 
+
+               /* wrap-around address pointer */
+               if (data_addr > NVRAM_MAX_SIZE)
+                       data_addr = NVRAM_BLOCK_SIZE;
+
+               data_num_pages++;
        }
                
        memcpy(((char *)data_page)+data_len, data, len);
@@ -253,14 +300,19 @@ char nvram_write(int type, int access_attr, void *data)
 }
 
 
-char nvram_read(int type, int access_attr, void *data)
+char nvram_read_data(int type, int access_attr, void *data)
 /* return 0 if successful */
 {
        int len = _get_data_len(type);
 
-       if (data_len+len > 256)
+       if (data_len+len > NVRAM_BLOCK_SIZE)
        {
-               data_addr += 256;
+               data_addr += NVRAM_BLOCK_SIZE;
+
+               /* wrap-around address pointer */
+               if (data_addr > NVRAM_MAX_SIZE)
+                       data_addr = NVRAM_BLOCK_SIZE;
+
                iat_flash_read_page(data_addr);
                data_len = 0;           
        }
@@ -272,12 +324,36 @@ char nvram_read(int type, int access_attr, void *data)
        return 0;
 }
 
+/*
+       NVRAM registers at block 0
+       pos        description
+       0          version of the current dictionnary
+       1          starting address for data block
+       2          date of last writing
+       3          address of the previous dictionnary          
+       4          size in pages of the current dict
+*/
+void nvram_write_reg(UNS32 reg, UNS16 pos)
+/* write reg at the position in the data block 0 */
+{
+       regs_page[pos] = reg;
+}
+
+UNS32 nvram_read_reg(UNS16 pos)
+/* read reg at the position in the data block 0 */
+{
+       return regs_page[pos];
+}
+
 
 /*
        LED
 */
 
-void led_set_redgreen(unsigned char bits)
+void led_set_redgreen(UNS8 bits)
+/* bits : each bit of this uns8 is assigned a led 
+          0=off, 1=on
+*/
 {
        lpc2138_redgreenled_set(bits);
 }
index 16b4f689bd218fb302aec441fdfc3709d3bb8d0a..90c2a6f5e9dd20a69805609c09eaff8eb38827ea 100644 (file)
@@ -25,10 +25,16 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #define _LPC2138_H_
 
 
+/* block and maximum size of NVRRAM in bytes */ 
+#define NVRAM_BLOCK_SIZE 256
+#define NVRAM_MAX_SIZE 1024*512
+
 extern short data_len;
+extern short data_num_pages;
 extern unsigned int *data_page;
 extern unsigned int data_addr;
 
+extern unsigned int *regs_page;
 
 void lpc2138_pinsel_set(int pin, LPC2138_PORT port, int size, int func); 
 void lpc2138_pinsel_clear(void); 
@@ -45,7 +51,9 @@ void sja1000_write(unsigned char addr8, unsigned char data);
 void iat_flash_erase(unsigned int command_ee,unsigned int result_ee[]);
 void iat_flash_write_page(unsigned int addr);
 void iat_flash_read_page(unsigned int addr);
-
+void iat_flash_write_regs(void);
+void iat_flash_read_regs(void);
 
 #endif
 
index 6e0c893880c2827d271d2b96e813dda59af339fe..56549762d77b4575e4345a0b86d175cf98d6ab74 100644 (file)
@@ -1,7 +1,19 @@
 /*
 This file is part of CanFestival, a library implementing CanOpen Stack.
-
- Author: Christian Fortin (canfestival@canopencanada.ca)
+  ____    _    _   _
+ / ___|  / \  | \ | | ___  _ __   ___ _ __
+| |     / _ \ |  \| |/ _ \| '_ \ / _ \ '_ \
+| |___ / ___ \| |\  | (_) | |_) |  __/ | | |
+ \____/_/   \_\_| \_|\___/| .__/ \___|_| |_|
+                          |_|
+          ____                      _
+         / ___|__ _ _ __   __ _  __| | __ _
+        | |   / _` | '_ \ / _` |/ _` |/ _` |
+        | |__| (_| | | | | (_| | (_| | (_| |
+         \____\__,_|_| |_|\__,_|\__,_|\__,_|
+
+                   canfestival@canopencanada.ca
+/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
 
 See COPYING file for copyrights details.
 
@@ -82,9 +94,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #define LPC2138_ale_PORT               P0
 #define LPC2138_ale_SIZE                1
 
-#define LPC2138_redgreenled             27 /* Pin 27 */
-#define LPC2138_redgreenled_PORT        P0
-#define LPC2138_redgreenled_SIZE        2
+#define LPC2138_redled                 27 /* Pin 27 */
+#define LPC2138_redled_PORT            P0
+#define LPC2138_redled_SIZE             1
+
+#define LPC2138_greenled               28 /* Pin 28 */
+#define LPC2138_greenled_PORT          P0
+#define LPC2138_greenled_SIZE           1
 
 #define LPC2138_rd                     29 /* Pin 29 */
 #define LPC2138_rd_PORT                P0
diff --git a/drivers/ecos_lpc2138_sja1000/notes.txt b/drivers/ecos_lpc2138_sja1000/notes.txt
new file mode 100644 (file)
index 0000000..2dc94ef
--- /dev/null
@@ -0,0 +1,18 @@
+canOpenDriver.c
+       f_can_send
+       f_can_receive
+       interrupts
+       nvram_save/load
+       baudrate
+
+sja1000.c
+       hardware init 
+       
+lpc2138.c
+       iat_flash
+
+time_slicer.c
+       settimer
+       alarm
+
+
diff --git a/drivers/ecos_lpc2138_sja1000/nvram.h b/drivers/ecos_lpc2138_sja1000/nvram.h
new file mode 100644 (file)
index 0000000..fdb52b5
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+  ____    _    _   _
+ / ___|  / \  | \ | | ___  _ __   ___ _ __
+| |     / _ \ |  \| |/ _ \| '_ \ / _ \ '_ \
+| |___ / ___ \| |\  | (_) | |_) |  __/ | | |
+ \____/_/   \_\_| \_|\___/| .__/ \___|_| |_|
+                          |_|
+          ____                      _
+         / ___|__ _ _ __   __ _  __| | __ _
+        | |   / _` | '_ \ / _` |/ _` |/ _` |
+        | |__| (_| | | | | (_| | (_| | (_| |
+         \____\__,_|_| |_|\__,_|\__,_|\__,_|
+
+                   canfestival@canopencanada.ca
+/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(_NVRAM_IO_H_)
+#define _NVRAM_IO_H_
+
+
+int    nvram_open(void);
+void   nvram_close(void);
+
+char nvram_write_data(int type, int access_attr, void *data);
+char nvram_read_data(int type, int access_attr, void *data);
+
+void nvram_write_regs(void);
+void nvram_read_regs(void);
+
+#endif
+
diff --git a/drivers/ecos_lpc2138_sja1000/nvram_iap.c b/drivers/ecos_lpc2138_sja1000/nvram_iap.c
new file mode 100644 (file)
index 0000000..bd50e71
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+                   canfestival@canopencanada.ca
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+flash.c
+       save to / retrieve from  the non-volatile memory
+       to be tested
+       - can we write/read into an address without working with the whole page (256bytes)
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "applicfg.h"
+#include "data.h"
+#include "objdictdef.h"
+
+#include "lpc2138_defs.h"                    /* LPC21xx definitions */
+
+#define IAP_LOCATION                   0x7ffffff1
+
+
+// define a page of data of NVRAM_BLOCK_SIZE bytes
+//
+short data_len; /* 0 to NVRAM_BLOCK_SIZE bytes */
+short data_num_pages;
+unsigned int *data_page = NULL;
+unsigned int data_addr;
+
+unsigned int *regs_page = NULL;
+
+// local definitons
+void ee_erase(unsigned int ,unsigned int[]);           //function erases EEPROM
+void ee_write_page(unsigned int);      //function adds a record in EEPROM
+void ee_read_page(unsigned int);       //function reads the latest valid record in EEPROM
+
+typedef void (*IAP)(unsigned int [],unsigned int[]);
+IAP iap_entry;
+
+
+
+/************************************************************************/
+/*                                                                     */
+/* function:                                                           */
+/*  void ee_erase(unsigned int command_ee,unsigned int result_ee[])    */
+/*                                                                             */
+/* type: void                                                                  */
+/*                                                                             */
+/* parameters:                                                                 */
+/*     command_ee   - Not used.                                        */
+/*  result_ee[0] - Returns a response to the last IAP command used.    */
+/*                 0 - EEPROM successfully erased.                     */
+/*                 For all other response values, see microcontroller  */
+/*                User Manual, IAP Commands and Status Codes Summary.  */
+/*  result_ee[1] - Not used.                                           */
+/*                                                                             */
+/* version: 1.1 (01/27/2006)                                                   */
+/*                                                                             */
+/* constants defined in LPC2k_ee.h used in this function:                      */
+/*  EE_SEC_L    - microcontroller's Flash sector where EEPROM begins   */
+/*  EE_SEC_H    - microcontroller's Flash sector where EEPROM ends     */
+/*  EE_CCLK             - microcontroller's system clock (cclk)        */
+/*                                                                             */
+/* description:                                                                */
+/*  This function erases LPC2000 on-chip Flash sectors selected to act         */
+/*  as an EEPROM. All Flash sectors between EE_SEC_L abd EE_SEC_H      */
+/*  (including these sectors) will be erased using the In Application  */
+/*  Programming (IAP) routines (see User Manual for more details).     */
+/*  Also, this function disables all interrupts while erasing the       */
+/*  EEPROM. If this is not needed, three lines of the ee_erase          */
+/*  subroutine can simply be commented-out without affecting the        */
+/*  routine performance at all.                                         */
+/*                                                                             */
+/* revision history:                                                           */
+/* - Rev. 1.1 adds interrupt disable feature.                          */
+/*                                                                             */
+/************************************************************************/
+void ee_erase(unsigned int command_ee,unsigned int result_ee[])
+{
+       unsigned int command_iap[5];
+       unsigned int result_iap[3];
+       unsigned long int enabled_interrupts;
+
+       enabled_interrupts = VICIntEnable;  //disable all interrupts
+       VICIntEnClr        = enabled_interrupts;
+
+       command_iap[0]=50;      // prepare sectors from EE_SEC_L to EE_SEC_H for erase
+       command_iap[1]=EE_SEC_L;
+       command_iap[2]=EE_SEC_H;
+       iap_entry=(IAP) IAP_LOCATION;
+       iap_entry(command_iap,result_iap);
+
+       command_iap[0]=52;      // erase sectors from EE_SEC_L to EE_SEC_H
+       command_iap[1]=EE_SEC_L;
+       command_iap[2]=EE_SEC_H;
+       command_iap[3]=EE_CCLK;
+       iap_entry=(IAP) IAP_LOCATION;
+       iap_entry(command_iap,result_iap);
+
+       command_iap[0]=53;      // blankcheck sectors from EE_SEC_L to EE_SEC_H
+       command_iap[1]=EE_SEC_L;
+       command_iap[2]=EE_SEC_H;
+       iap_entry=(IAP) IAP_LOCATION;
+       iap_entry(command_iap,result_iap);
+
+       VICIntEnable = enabled_interrupts;  //restore interrupt enable register
+
+       result_ee[0]=result_iap[0];
+       return;
+}
+
+/************************************************************************/
+/*                                                                     */
+/* function:                                                           */
+/*  void ee_write(unsigned int command_ee,unsigned int result_ee[])    */
+/*                                                                             */
+/* type: void                                                                  */
+/*                                                                             */
+/* parameters:                                                                 */
+/*     command_ee   - An address of a content of ee_data type that has */
+/*                 to be programmed into EEPROM.                               */
+/*  result_ee[0] - Returns a response to the last IAP command used.    */
+/*                 0 - data successfully programmed in EEPROM.         */
+/*               501 - no space in EEPROM to program data.                     */
+/*                 For all other response values, see microcontroller  */
+/*                User Manual, IAP Commands and Status Codes Summary.  */
+/*  result_ee[1] - Not used.                                                   */
+/*                                                                             */
+/* version: 1.1 (01/27/2006)                                                   */
+/*                                                                             */
+/* constants defined in LPC2k_ee.h used in this function:                      */
+/*  EE_BUFFER_SIZE        - IAP buffer size; must be 256 or 512        */
+/*  NO_SPACE_IN_EEPROM - EEPROM is full and no data can be programmed  */
+/*  EE_BUFFER_MASK        - parameter used for interfacing with IAP    */
+/*  EE_REC_SIZE           - ee_data structure size in bytes            */
+/*  EE_SEC_L              - micro's Flash sector where EEPROM begins   */
+/*  EE_SEC_H              - micro's Flash sector where EEPROM ends     */
+/*  EE_CCLK                       - micro's system clock (cclk)        */
+/*                                                                             */
+/* description:                                                                */
+/*  This function writes a single structure of ee_data type into the   */
+/*  EEPROM using an In Application     Programming (IAP) routines (see */
+/*  User Manual for more details). command_ee contains an address of   */
+/*  this structure. EEPROM is scanned for the last (if any) record     */
+/*  identifier (EE_REC_ID), and a new record is added next to it.              */
+/*  Also, this function disables all interrupts while erasing the       */
+/*  EEPROM. If this is not needed, three lines of the ee_write          */
+/*  subroutine can simply be commented-out without affecting the        */
+/*  routine performance at all.                                         */
+/*                                                                             */
+/* revision history:                                                           */
+/* - Rev. 1.1 fixes a bug related to verifying a content written into  */
+/*   the EEPROM. 1.0 was reporting missmatch even when there were no   */
+/*   problems at all.                                                  */
+/*   Rev. 1.1 adds interrupt disable feature.                          */
+/*                                                                             */
+/************************************************************************/
+
+void ee_write_page(unsigned int addr)
+{
+       unsigned long int enabled_interrupts;
+       // unsigned char ee_buffer[16];
+       unsigned int command_iap[5], result_iap[3];
+
+       enabled_interrupts = VICIntEnable;  //disable all interrupts
+       VICIntEnClr        = enabled_interrupts;
+
+       iap_entry = (IAP) IAP_LOCATION;
+
+       // prepare sectors from EE_SEC_L to EE_SEC_H for erase
+       command_iap[0] = 50;                    
+       command_iap[1] = EE_SEC_L;
+       command_iap[2] = EE_SEC_H;
+       iap_entry(command_iap, result_iap);
+
+       // copy RAM to flash/eeprom
+       command_iap[0] = 51;
+       command_iap[1] = (unsigned int) (addr & EE_START_MASK); // 256 kb boundary
+       command_iap[2] = (unsigned int) (data_page);            // should be on a word boundary
+       command_iap[3] = 256;
+       command_iap[4] = EE_CCLK;
+       iap_entry(command_iap, result_iap);
+
+#if 0 
+       // compare RAM and flash/eeprom
+       command_iap[0] = 56;
+       command_iap[1] = (unsigned int) data;
+       command_iap[2] = addr;
+       command_iap[3] = dlen;
+       iap_entry(command_iap, result_iap);
+#endif
+
+       VICIntEnable = enabled_interrupts;  //restore interrupt enable register
+}
+
+
+/************************************************************************/
+/*                                                                     */
+/* function:                                                           */
+/*  void ee_read(unsigned int command_ee,unsigned int result_ee[])     */
+/*                                                                             */
+/* type: void                                                                  */
+/*                                                                             */
+/* parameters:                                                                 */
+/*     command_ee   - Not used.                                        */
+/*  result_ee[0] - Returns a response.                                 */
+/*                 0 - data successfully found in EEPROM.              */
+/*               500 - no data/records available in EEPROM.            */
+/*  result_ee[1] - an address of the last record of ee_data type       */
+/*                                in EEPROM.                           */
+/*                                                                             */
+/* version: 1.1 (01/27/2006)                                                   */
+/*                                                                             */
+/* constants defined in LPC2k_ee.h used in this function:                      */
+/*  NO_RECORDS_AVAILABLE - EEPROM is empty/no records identifiable     */
+/*                        with a record identifier (EE_REC_ID) found   */
+/*  EE_ADR_L       - micro's Flash address from where EEPROM begins    */
+/*  EE_REC_SIZE    - size (in bytes) of a ee_data structure            */
+/*                                                                     */
+/* description:                                                                */
+/*  This function scans an EEPROM content looking for the last record  */
+/*  that can be identified with a record identifier (EE_REC_ID). When  */
+/*  such data is found, its address is passed as result_ee[1].         */
+/*                                                                             */
+/* revision history:                                                           */
+/* - Rev. 1.0 had problems with accessing the last record in a fully   */
+/*   occupied EEPROM. Rev. 1.1 fixes this.                             */
+/*                                                                             */
+/************************************************************************/
+void ee_read_page(unsigned int addr)
+{
+       memcpy(data_page, (unsigned int *)addr, sizeof(unsigned int)*64);
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+
+/*
+       CAN FESTIVAL interface functions
+*/
+
+
+int _get_data_len(int type)
+{
+       int len = 0; /* number of bytes */
+       switch(type)
+       {
+               case  boolean:
+                       len = 1;
+                       break;
+
+               case  int8:
+               case  uint8:
+                       len = 1;
+                       break;
+               case  int16:
+               case  uint16:
+                       len = 2;
+                       break;
+               case  int24:
+               case  uint24:
+                       len = 3;
+                       break;
+               case  int32:
+               case  uint32:
+               case  real32:
+                       len = 4;
+                       break;
+               case  int40:
+               case  uint40:
+                       len = 5;
+                       break;
+               case  int48:
+               case  uint48:
+                       len = 6;
+                       break;
+               case  int56:
+               case  uint56:
+                       len = 7;
+                       break;
+               case  int64:
+               case  uint64:
+               case  real64:
+                       len = 8;
+                       break;
+#if 0
+/* TO DO */
+               case  visible_string:
+               case  octet_string:
+               case  unicode_string:
+               case  time_of_day:
+               case  time_difference:
+#endif
+       }
+
+       return len;
+}
+
+
+
diff --git a/drivers/ecos_lpc2138_sja1000/nvram_iap.h b/drivers/ecos_lpc2138_sja1000/nvram_iap.h
new file mode 100644 (file)
index 0000000..88dabd6
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+This file is part of CanFestival, a library implementing CanOpen Stack.
+                   canfestival@canopencanada.ca
+
+See COPYING file for copyrights details.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/************************************************************************/
+/*                                                                     */
+/*     LPC2k_ee.H:  Header file enabling EEPROM support                */
+/*     for Philips LPC2000 microcontroller's on-chip Flash memory      */
+/*             (revision 1.0, May 13th, 2005.)                                 */
+/*                                                                             */
+/*     This file is to be used with LPC2k_ee.c file                    */
+/*                                                                             */
+/* IMPORTANT: on-chip Flash memory sector(s) intended to be used as    */
+/* an EEPROM will be unavailable for regular code storage! The smallest        */
+/* amount of Flash memory that can be used as an EEPROM is a single    */
+/* Flash sector (regardless of the Flash sector actual size).          */
+/*                                                                             */
+/* If size of desired EEPROM requires several Flash sectors, these     */
+/* sectors must be a consecutive ones.                                 */
+/*                                                                             */
+/************************************************************************/
+
+#define EE_SEC_L               1               //Flash sector where EEPROM begins (see UM for details)
+#define EE_SEC_H               3               //Flash sector where EEPROM ends (see UM for details)
+#define EE_ADDR_L              0x00001000      //Must match the EE_SEC_L Flash sector start address
+#define EE_ADDR_H              0x00003FFF      //Must match the EE_SEC_H Flash sector end address
+#define EE_CCLK                        60000           //system clock cclk expressed in kHz (5*12 MHz)
+
+/************************************************************************/
+/*                                                                     */
+/* ee_data structure can be defined differently from this example.     */
+/* The only requirement is to have _id field as it is defined here     */
+/* since EE_REC_ID character is used to identify a record's presence   */
+/* in the EEPROM memory.                                               */
+/*                                                                             */
+/* ====================================================================        */
+/*                                                                             */
+/* IMPORTANT ARM memory access considerations:                         */
+/*                                                                             */
+/* char        : byte alligned. Can be accessed at any location in memory.     */
+/*                                                                             */
+/* short int: occupies 2 consecutive bytes. It can be read/write       */
+/*       accessed only when half-word alligned. Therefore, it is       */
+/*       located at addresses ending with 0x0, 0x2, 0x4, 0x6, 0x8,     */
+/*       0xA, 0xC or 0xE.                                              */
+/*                                                                             */
+/* int : occupies 4 consecutive bytes. It can be read/write            */
+/*       accessed only when half-word alligned. Therefore, it is       */
+/*       located at addresses ending with 0x0, 0x4, 0x8 or 0xC.        */
+/*                                                                             */
+/* ====================================================================        */
+/*                                                                             */
+/* Due to the LPC2000 Flash memory characteristics, an ee_data                 */
+/* structure size (EE_REC_SIZE) is limited to the following set:       */
+/*                                                                             */
+/* LPC2101/2/3, LPC2131/2/4/6/8, LPC2141/2/4/6/8: 0x10, 0x20, 0x40,     */ 
+/*                                                0x80 or 0x100         */
+/*                                                                             */
+/* LPC2104/5/6, LPC2112/4/9, LPC2124/9, LPC2192/4: 0x10, 0x20, 0x40,    */
+/*                                                 0x80, 0x100 or 0x200 */
+/*                                                                             */
+/* ====================================================================        */
+/*                                                                             */
+/* example1:                                                           */
+/*                                                                             */
+/* struct ee_data{             //structure starts as word alligned     */
+/*     unsigned char   _id;    //1 byte  - no allignement restr.       */
+/*                                  //             3 BYTE GAP!!!!              */              
+/*     unsigned int    _rec_count; //4 bytes - must be word alligned!  */
+/*     unsigned char   _cs;    //1 byte  - no allignement restr.       */
+/*};                           // next structure will start as         */
+/*                                  // word alligned...                 */
+/* Structure in example 1 occupies 12 bytes of memory                  */
+/*                                                                             */
+/* --------------------------------------------------------------------        */
+/*                                                                             */
+/* example2:                                                           */
+/*                                                                             */
+/* struct ee_data{             //structure starts as word alligned     */
+/*     unsigned char   _id;    //1 byte  - no allignement restr.       */
+/*     unsigned char   _cs;    //1 byte  - no allignement restr.       */
+/*                              //         2 BYTE GAP!!!!              */              
+/*     unsigned int    _rec_count; //4 bytes - must be word alligned!  */
+/*};                           // next structure will start as         */
+/*                                  // word alligned...                 */
+/* Structure in example 2 occupies 8 bytes of memory                   */
+/*                                                                             */
+/************************************************************************/
+
+struct ee_data{
+       unsigned char   _id;            //  4 bytes: 1 byte (char) + 3 byte GAP!
+       unsigned int    _rec_count;     //  4 bytes (int)
+       unsigned int    _counter;       //  4 bytes (int)
+       unsigned char   _cs;            //  4 bytes: 1 byte (char) + 3 byte GAP!
+};                                     // 16 bytes total
+
+/************************************************************************/
+/*                                                                     */
+/*     Disclaimer: all observations presented in example1, example 2 and */
+/*     ee_data structure defined here are based on Keil's ARM compiler. */
+/*     If another compiler is used, memory usage would have to be      */
+/*     re-examined and verified.                                       */
+/*                                                                     */
+/************************************************************************/
+
+
+#define EE_REC_SIZE            0x10    //see restrictions from above
+
+/********************************************************************/
+/*                                                                     */
+/*     Valid combinations for                                          */
+/* EE_REC_SIZE, EE_BUFFER_SIZE, EE_BUFFER_MASK and EE_START_MASK       */
+/*                                                                     */
+/* EE_BUFFER_SIZE ! EE_START_MASK ! EE_REC_SIZE ! EE_BUFFER_MASK       */
+/* ----------------------------------------------------------------    */
+/*     256     0xFFFFFF00              0x010           0xF0            */
+/*     256     0xFFFFFF00              0x020           0xE0            */
+/*     256     0xFFFFFF00              0x040           0xC0            */
+/*     256     0xFFFFFF00              0x080           0x80            */
+/*     256     0xFFFFFF00              0x100           0x00            */
+/* ---------------------------------------------------------------- */
+/*     512     0xFFFFFE00              0x010           0x1F0           */
+/*     512     0xFFFFFE00              0x020           0x1E0           */
+/*     512     0xFFFFFE00              0x040           0x1C0           */
+/*     512     0xFFFFFE00              0x080           0x180           */
+/*     512     0xFFFFFE00              0x100           0x100           */
+/*     512     0xFFFFFE00              0x200           0x000           */
+/********************************************************************/
+/*     For LPC2101/2/3, LPC213x and LPC214x EE_BUFFER_SIZE is 256. */
+/*     For all other LPC2000 devices EE_BUFFER_SIZE is always 512. */
+/********************************************************************/
+#define EE_BUFFER_SIZE 256
+#define EE_START_MASK  0xFFFFFF00
+#define EE_BUFFER_MASK 0x000000F0
+
+/********************************************************************/
+/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+/*!!                                                             !!*/
+/*!!                                                             !!*/
+/*!!   DO NOT MODIFY THE FOLLOWING CODE!!!                       !!*/
+/*!!   ===================================                       !!*/
+/*!!                                                             !!*/
+/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+/********************************************************************/
+
+#define EE_REC_ID                              0xAA
+#define EE_SIZE                                        (EE_ADDR_H+1-EE_ADDR_L)
+#define NO_RECORDS_AVAILABLE   500
+#define NO_SPACE_IN_EEPROM             501
+#define INDEX_OUT_OF_RANGE             502
+
+#ifndef _EEPROM_
+       extern const unsigned char eeprom[];
+       extern void ee_erase(unsigned int , unsigned int []);   //function erases EEPROM
+       extern void ee_write(unsigned int , unsigned int []);   //function adds a record in EEPROM
+       extern void ee_read (unsigned int , unsigned int []);   //function reads the latest valid record in EEPROM
+       extern void ee_readn(unsigned int , unsigned int []);   //function reads n-th record in EEPROM
+       extern void ee_count(unsigned int , unsigned int []);   //function counts records in EEPROM
+#endif
diff --git a/drivers/ecos_lpc2138_sja1000/nvram_readme b/drivers/ecos_lpc2138_sja1000/nvram_readme
new file mode 100644 (file)
index 0000000..db364a4
--- /dev/null
@@ -0,0 +1,61 @@
+procedure for NVRAM
+===================
+
+data block 0
+------------
+This data block is located at the beginning of the NVRAM and contains
+a series of registers.
+eg. 1. the version number of the current dictionnary (32 bits)
+    2. pointer to the current dictionnary (32 bits)
+    3. date of last dictionnary dump (32 bits)
+    4. pointer to the last dict (32 bits)
+    5. size in page of the current dict
+
+a minimum number of registers should always be in this block (including a number of 'for future use' 32 bits registers). the remaining space will be left to the developper
+
+a 256kb data block could handled 64 registers 
+
+data block 1 to N
+-----------------
+The place where to put the content of the dictionnary
+
+
+procedure to write in the NVRAM
+-------------------------------
+for each sub-index
+add a flag indicating the state
+       = 0  : normal
+       = -1 : this is a old sub-index, no longer used
+       = +1 : this is a new sub-index
+
+the sub-indexed flaged to -1 could be remove when doing a new release of dictionnary
+eg. from BIOS V0 to V1, flag the old sub-index to -1.  but when going to V2, those must be remove from the dictionnary
+
+this flag is important when reloading the old NVRAM content. Since the writing and reading are done sequentially, the dictionnary and the NVRAM must be synchronised.
+
+
+ON BOOT
+-------
+1. read the block data 0 and check the NVRAM version number against the current dictionnary
+if the dict version = NVRAM version, then read the NVRAM using the normal procedure (state=0 and state=+1)
+if the dict version is newer then the NVRAM, read the NVRAM using the state=0 and state=-1 . this will ensure a synchone reading of the data
+
+2. if this is a new NVRAM, write the whole dictionnary to a NEW position in the NVRAM.
+       write all sub-indexes with state=0 and =+1, do not write does with state=-1
+       write the new version number in the registery and the date
+
+
+ON WRITE
+--------
+write the content of the whole dict (only those sub-indexes that must be saved) to the NVRAM
+write the version number  
+write the date
+
+
+NEW VERSION OF BIOS
+-------------------
+When a new version of BIOS is downloaded into the device, special procedure must be taken (cf. ON BOOT and ON WRITE). But to avoid problem during the update (i.e. lost of NVRAM data or worst NVRAM corruption) fewer NVRAM manipulation should be performed. Therefore, when writing the new dictionary to NVRAM, it should be put AFTER the previous one. This will provide a way to go back and fetch the previous dictionnary saved values if needed. 
+
+Obviously, the NVRAM has a limited capacity and it is possible that the new BIOS will overshoot the upper limit of memory. In that case, the algorithm should do a loop-around the addressed. Meaning, if the last block of data is reached, go back to data block 1 (data block 0 = registers). If the NVRAM is large enough, it should not cause problem (i.e. overwritting the beginning of the actual dict).
+
+Data Block 0 has the offset in memory to access the current dict. It also containt the pointer to the last version of the dict. Since the algo writing to the NVRAM does not compact memory, the size of the dict is not necessarily the size of the NVRAM memory it occupies.
index 71a428db06b9f93ba77f718ba8d29a3804d8be98..8eeef3e4912b764d2277d5622aa427a62cd6211b 100644 (file)
@@ -20,4 +20,159 @@ License along with this library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#include <cyg/kernel/kapi.h>
+#include <cyg/hal/hal_arch.h>
+
+#include "lpc2138_pinout.h"
+#include "lpc2138_defs.h"
+#include "lpc2138.h"
+
+#include "sja1000.h"
+
+
+#define CYGNUM_HAL_INTERRUPT_1 CYGNUM_HAL_INTERRUPT_EINT1
+#define CYGNUM_HAL_PRI_HIGH    0
+
+
+cyg_uint32 interrupt_1_isr(cyg_vector_t vector, cyg_addrword_t data);
+void interrupt_1_dsr(cyg_vector_t   vector,
+                            cyg_ucount32   count,
+                            cyg_addrword_t data);
+
+
+/* Interrupt for CAN device. */
+static cyg_interrupt interrupt_1;
+static cyg_handle_t  interrupt_1_handle;
+
+
+void init_sja1000(void)
+{
+    do
+    {
+        sja1000_write(MOD, 1<<RM);                  /* demande reset */
+    }
+    while ((sja1000_read(MOD) & (1<<RM)) == 0);   /* loop until reset good */
+
+/*
+    sja1000_write(bustiming0, ((0<<SJW1)|(0<<SJW0)|(0<<BRP5)|(0<<BRP4)|(0<<BRP3)|(0<<BRP2)|(0<<BRP1)|(0<<BRP0)));
+    sja1000_write(bustiming1, ((1<<SAM)|(0<<TSEG22)|(1<<TSEG21)|(0<<TSEG20)|(0<<TSEG13)|(1<<TSEG12)|(0<<TSEG11)|(0<<TSEG10)));
+*/
+
+/* OUTPUT CONTROL REGISTER */
+    sja1000_write(outputcontrol, ((1<<OCTP1)|(1<<OCTN1)|(0<<OCPOL1)|(1<<OCTP0)|(1<<OCTN0)|(0<<OCPOL0)|(1<<OCMODE1)|(0<<OCMODE0)));
+
+
+    sja1000_write(clockdivider, ((1<<CANmode)|(1<<CBP)|(1<<RXINTEN)|(0<<clockoff)|(1<<CD2)|(1<<CD1)|(1<<CD0)));
+    sja1000_write(16,  0x01);   /* 0 code all accept block high bit */
+    sja1000_write(17,  0x00);   /* 0 all accept block high bit */
+    sja1000_write(18,  0x00);   /* 0 all accept block high bit */
+    sja1000_write(19,  0x00);   /* 0 all accept block high bit */
+    sja1000_write(20,  0xFE);   /* 1 mask */
+    sja1000_write(21,  0xFF);
+    sja1000_write(22,  0xFF);
+    sja1000_write(23,  0xFF);
+    sja1000_write(IER, 0x01);
+    sja1000_write(clockdivider, ((1<<CANmode)|(1<<CBP)|(1<<RXINTEN)|(0<<clockoff)|(1<<CD2)|(1<<CD1)|(0<<CD0)));
+
+    do
+    {
+        sja1000_write(MOD, (1<<AFM)|(0<<STM)|(0<<RM));
+    }
+    while ((sja1000_read(MOD) & (1<<RM)) == 1);   /* loop until reset gone */
+}
+
+
+/***************************************************************************/
+
+
+void init_interrupts(void)
+{
+    cyg_vector_t   interrupt_1_vector   = CYGNUM_HAL_INTERRUPT_1;
+    cyg_priority_t interrupt_1_priority = CYGNUM_HAL_PRI_HIGH;
+
+    cyg_interrupt_create(
+        interrupt_1_vector,
+        interrupt_1_priority,
+        (cyg_addrword_t) 0,
+        (cyg_ISR_t *) &interrupt_1_isr,
+        (cyg_DSR_t *) &interrupt_1_dsr,
+        &interrupt_1_handle,
+        &interrupt_1);
+
+    cyg_interrupt_attach(interrupt_1_handle);
+
+    cyg_interrupt_acknowledge(interrupt_1_vector);
+
+    cyg_interrupt_unmask(interrupt_1_vector);
+}
+
+/* External Interrupt 1 Service */
+void eint1_srv(void) /*__irq*/ 
+{
+       //++intrp_count;                              // increment interrupt count
+       EXTINT      = 2;                            // Clear EINT1 interrupt flag
+       VICVectAddr = 0;                            // Acknowledge Interrupt
+}
+
+
+/* Initialize EINT1 Interrupt Pin */
+void init_eint1(void)
+{
+       EXTMODE       = 0x2;                         // Edge sensitive mode on EINT1
+       EXTPOLAR      = 0;                           // falling edge sensitive
+       P0_PINSEL0   |= 2 << 28;                     // Enable EINT1 on GPIO_0.14
+       VICVectAddr0  = (unsigned long) eint1_srv;   // set interrupt vector in VIC 0
+       VICVectCntl0  = 0x20 | 15;                   // use VIC 0 for EINT1 Interrupt
+       EXTINT        = 2;
+       VICIntEnable  = 1 << 15;                     // Enable EINT1 Interrupt
+}
+
+
+/*
+{
+       unsigned char byte=sja1000_read(0x02);
+
+       if (byte & 0x01)
+       {
+               // RXFIFO full
+       }
+       
+       if (byte & 0x02)
+       {
+               // overrun
+       }
+       
+       if (byte & 0x04)
+       {
+               // the cpu may write a msg
+       }
+       
+       if (byte & 0x08)
+       {
+               // tx complete
+       }
+       
+       if (byte & 0x10)
+       {
+               // receiving
+       }
+       
+       if (byte & 0x20)
+       {
+               // transmitting
+       }
+       
+       if (byte & 0x40)
+       {
+               // at least one of the error counter has reached or exceeeded
+               // the CPU warning limit
+       }
+       
+       if (byte & 0x80)
+       {
+               // bus off
+       }
+}
+*/
+
 
index cb296888b198e8db09b55e8d94b68695c762a87b..d014d8168cc394f4430671b696361e51171f7bc5 100644 (file)
@@ -32,6 +32,7 @@ PREFIX = SUB_PREFIX
 TARGET = SUB_TARGET
 CAN_DRIVER = SUB_CAN_DRIVER
 TIMERS_DRIVER = SUB_TIMERS_DRIVER
+LED_ENABLE = SUB_LED_ENABLE
 
 INCLUDES = -I../../include -I../../include/$(TARGET) -I../../include/$(CAN_DRIVER) -I../../include/$(TIMERS_DRIVER)
 
@@ -43,6 +44,12 @@ ifeq ($(TIMERS_DRIVER),timers_xeno)
        PROGDEFINES = -DUSE_XENO
 endif
 
+ifeq ($(LED_ENABLE),YES)
+OBJS += ../../drivers/can_virtual/led_virtual.o 
+PROG_CFLAGS += -DLED_ENABLE
+endif
+
+
 all: TestMasterSlave
 
 ../../drivers/$(TARGET)/libcanfestival_$(TARGET).a:
index 661f216906cdc58a5aa89fb83e2938d5015004aa..2ac03a780fbcf5840326b164eea8a3070169f63e 100644 (file)
@@ -37,15 +37,15 @@ CAN_HANDLE canOpen(s_BOARD *board);
 int canClose(CAN_HANDLE fd0);
 void canReceiveLoop(CAN_HANDLE fd0);
 
-void led_set_redgreen(unsigned char bits);
+#include "data.h"
+
+void led_set_redgreen(CO_Data *d, unsigned char bits);
 
 int nvram_open(void);
 void nvram_close(void);
 char nvram_write(int type, int access_attr, void *data);
 char nvram_read(int type, int access_attr, void *data);
 
-#include "data.h"
-
 struct struct_s_BOARD {
   char * busname;
   int baudrate;
index f91ae4078f6e8d9fbc380dd860370309263284b5..0dfb19157d75589c4940aaf1a188fc9abc68c94e 100644 (file)
@@ -39,5 +39,4 @@ enum
 
 void led_set_state(CO_Data *d, int state);
 
-
 #endif
index 6a1019f96dfaf780d195efcdbfbb5befe37dd36e..c367f9fe16169d678c3369defbe2672bce3f5b48 100644 (file)
@@ -30,9 +30,9 @@ ARCH_NAME = SUB_ARCH_NAME
 PREFIX = SUB_PREFIX
 BINUTILS_PREFIX = SUB_BINUTILS_PREFIX
 TARGET = SUB_TARGET
-LSS_ENABLE=SUB_LSS_ENABLE
-LED_ENABLE=SUB_LED_ENABLE
-NVRAM_ENABLE=SUB_NVRAM_ENABLE
+LSS_ENABLE = SUB_LSS_ENABLE
+LED_ENABLE = SUB_LED_ENABLE
+NVRAM_ENABLE = SUB_NVRAM_ENABLE
 CAN_DRIVER = SUB_CAN_DRIVER
 TIMERS_DRIVER = SUB_TIMERS_DRIVER
 TIMERS_ENABLE = SUB_TIMERS_ENABLE
@@ -73,6 +73,7 @@ endif
 ifeq ($(LED_ENABLE),YES)
 OBJS += $(TARGET)_led.o
 SRC_HFILES += ../include/led.h
+PROG_CFLAGS += -DLED_ENABLE
 endif 
 
 ifeq ($(NVRAM_ENABLE),YES)
index 5ca49e1b2d0d7a2a19b7e1c96ebaa23dee32bc4d..20593f8fd92e5e6c3d00d4be0b682ee483e548c6 100644 (file)
--- a/src/led.c
+++ b/src/led.c
@@ -65,6 +65,8 @@ const char *led_sequence_table[6] = // up and downs of the sequence
 
 void led_set_state(CO_Data *d, int state)
 {
+printf("led_set_state(%x)\n", state);
+
        switch(state)
        {
                case Initialisation:
@@ -100,8 +102,8 @@ void led_set_state(CO_Data *d, int state)
        {
                led_stop_timer();
 
-               led_set_green(led_state_green);
-               led_set_red(led_state_red);
+               //led_set_green(led_state_green);
+               //led_set_red(led_state_red);
        }
 
        else
@@ -168,15 +170,15 @@ void led_set_error(CO_Data *d, UNS8 error)
                }
 
                led_start_timer(d, 200);
-               led_set_red(led_state_red);
+               //led_set_red(led_state_red);
        }
 
        if (led_state_green < 2  &&  led_state_red < 2)
        {
                led_stop_timer();
 
-               led_set_green(led_state_green);
-               led_set_red(led_state_red);
+               //led_set_green(led_state_green);
+               //led_set_red(led_state_red);
        }
 }
 
@@ -197,7 +199,7 @@ void led_stop_timer(void)
 
 void led_callback(CO_Data *d, UNS32 id)
 {
-       unsigned char bits = 0;
+       UNS8 bits = 0;
 
        // RED LED
        if (led_sequence_table[led_sequence_red][led_seq_index_red] == '1')
@@ -233,7 +235,7 @@ void led_callback(CO_Data *d, UNS32 id)
        if (led_seq_index_green > strlen(led_sequence_table[led_sequence_green]))
                led_seq_index_green = 0;
 
-       led_set_redgreen(bits);
+       led_set_redgreen(d, bits);
 }