Post Go back to editing

ADUCM350 ported to GCC

Hi to all,

I ported SDK and several test programs to GCC and during this task the compiler found some issues in the source code.

So, I'm reporting some of these corrections, not related to the type of the compiler, that in my opinion they could be considered as bugs:

1) ===============

I have not found metrics.h in the source tree. By looking the source code, I have reconstructed it in the best way I could but, unless I just missed it somewhere, it would be better to include it in the next release..

2) ===============

There is an error in declaration of LCD_DevData[] into lcd.c.

The struct ADI_LCD_DEV_DATA_TYPE has a bBlockingMode but it is missing in the later declaration:

@@ -72,7 +72,6 @@
         ADI_LCD_STATE_UNINITIALIZED,    /* Init state */
         pADI_LCD,                       /* Pointer to the LCD MMR registers */
         LCD_IRQn,                       /* LCD Interrupt Number */
+        0,
         NULL,                           /* Pointer to callback function */
         NULL,                           /* Callback parameter */
     }

3) ===============

Into i2c.c:

@@ -1204,7 +1204,7 @@
     hDevice->TxRemaining      = 0;
     hDevice->pRxBuffer        = NULL;
     hDevice->RxRemaining      = 0;
+    hDevice->dataAddress      = 0;
-    hDevice->dataAddress      = NULL;
     hDevice->dataAddressWidth = ADI_I2C_NO_DATA_ADDRESSING_PHASE;

 #if (ADI_I2C_CFG_ENABLE_DMA_SUPPORT == 1)

the dataAddress field is initialized with NULL without reason and the compiler complained about the fact that a pointer is assigned to an integer of different size without a cast.

4) ===============

In captouch_lib.c:

@@ -28,7 +28,7 @@
 #include <stddef.h>                /* for NULL */
 #include <string.h>                /* for memcpy */
 #include <stdlib.h>
-#include "test_common.h"  // test
 #include "captouch.h"
 #include "captouch_lib.h"
 #include "gpio.h"      /* GPIO configuration */

the inclusion of test_common.h is useless so I removed it.

5) ===============

It is better to avoid C99, like C++ in-scope declarations.

With GCC I could bypass it by adding -std=C99 in the options, but in my opinion it would be better to leave clean ANSI C code.

Hopefully, this happens only in few sources.

6) ===============

GCC complained that NULL cannot be assigned to an enum type, obviously.

This happens in system.c:

@@ -170,7 +170,7 @@

 #ifdef ADI_SYSTEM_CLOCK_TRANSITION

+static ADI_SYS_CLOCK_STATE_TYPE     currentState = ADI_SYS_CLOCK_STATE_INVALID;
-static ADI_SYS_CLOCK_STATE_TYPE     currentState = NULL;

 /*----------------------------------------------------------------------------
   State parameters initialization
@@ -1751,35 +1751,35 @@
 static const StateTableEntryType StateTransitionTable[] = {

 /*  from-state                              input-event                             to-state                                action                  */
+    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState,      },
+    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB,                aEnterUSBState,              },
+    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+
+    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,          },
+    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,    aEnterUSBState,              },
+    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+
+    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,    ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,          },
+    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_USB_LPM,            aEnterUSBLPMState,           },
+
+    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_USB,                ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState,      },
+    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState,      },
+
+    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState,      },
+    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
+    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB,                aEnterUSBState,              },
+    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,          },
+    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_INVALID,            ADI_SYS_CLOCK_STATE_INVALID, },
-    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState, },
-    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB,                aEnterUSBState,         },
-    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_OFF,          NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_MINIMAL,           ADI_SYS_CLOCK_TRIGGER_USB_LPM,          NULL,                                   NULL,                   },
-
-    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,     },
-    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,    aEnterUSBState,         },
-    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_OFF,          NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_MEASUREMENT,       ADI_SYS_CLOCK_TRIGGER_USB_LPM,          NULL,                                   NULL,                   },
-
-    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,    NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_ON,           NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,     },
-    {ADI_SYS_CLOCK_STATE_USB,               ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_USB_LPM,            aEnterUSBLPMState,      },
-
-    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  ADI_SYS_CLOCK_STATE_USB,                NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_ON,           NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState, },
-    {ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,   ADI_SYS_CLOCK_TRIGGER_USB_LPM,          ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState, },
-
-    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_ON,   ADI_SYS_CLOCK_STATE_MEASUREMENT,        aEnterMeasurementState, },
-    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_MEASUREMENT_OFF,  NULL,                                   NULL,                   },
-    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_ON,           ADI_SYS_CLOCK_STATE_USB,                aEnterUSBState,         },
-    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_OFF,          ADI_SYS_CLOCK_STATE_MINIMAL,            aEnterMinimalState,     },
-    {ADI_SYS_CLOCK_STATE_USB_LPM,           ADI_SYS_CLOCK_TRIGGER_USB_LPM,          NULL,                                   NULL,                   },

 };

Into system.h, I added ADI_SYS_CLOCK_STATE_INVALID to the enum.

@@ -253,8 +253,7 @@
  *                                          configurations are requested asynchronously.
  */
 typedef enum {
+    ADI_SYS_CLOCK_STATE_INVALID = 0,
+    ADI_SYS_CLOCK_STATE_MINIMAL,
-    ADI_SYS_CLOCK_STATE_MINIMAL = 1,        /* use one-based enum to avoid confusion with NULL, which is used to flag invalid state transitions */
     ADI_SYS_CLOCK_STATE_MEASUREMENT,
     ADI_SYS_CLOCK_STATE_USB,
     ADI_SYS_CLOCK_STATE_USB_MEASUREMENT,

7) ===============

Into system.c, __vector_table is declared as a void object.

Probably, __relocated_vector_table needs to be fixed too, but I have not tested it.

@@ -26,7 +26,7 @@
 #ifdef RELOCATE_IVT
 extern void __relocated_vector_table;
 #else
+extern void *__vector_table[];
-extern void __vector_table;
 #endif

 /*----------------------------------------------------------------------------

8) ===============

Into uart.c, some fields of UART_DevData[] are NULL instead of zero and the compiler complained the pointer to integer assignment.

@@ -176,15 +176,15 @@
            NULL,                                        /*!< rx buffer start address    */
            0,                                           /*!< rx buffer write index      */
            0,                                           /*!< rx buffer read index       */
+           0,                                           /*!< rx buffer size             */
-           NULL,                                        /*!< rx buffer size             */
            0,                                           /*!< available bytes            */
        },
        {
            NULL,                                        /*!< tx buffer start address    */
            0,                                           /*!< tx buffer read index       */
            0,                                           /*!< tx buffer write index      */
+           0,                                           /*!< tx buffer size             */
+           0,                                           /*!< number of free elements    */
-           NULL,                                        /*!< tx buffer size             */
-           NULL,                                        /*!< number of free elements    */
        },
 #endif /* (1 == ADI_UART_CFG_INTERRUPT_MODE_SUPPORT) */
 #if defined(ADI_DEBUG)

Other fixes are required for making the SDK working.

I hope this could be useful.

Sincerely,

Carlo Bramini.

  • Hi Carlo,

    Thanks for the detailed information. We will review this and, where warranted, will add your suggestions to a future SDK revision.

    Rgds,

    Eoghan.

  • Hi Carlo,

    Do you want to share your results with us?

    Thank you

    Petar

  • Hi , , and To Whomever Else It May Concern ...

    have you made progress porting ADuCM350 firmware development tools to GNU CC?
    ... and how far away is a Free Software tool chain (compiler/debugger/libraries for the peripherals) for the ADuCM350? 
    The price tag for IAR Embedded Workbench is a bit prohibitive for a lot of people who have become interested in this chip in the last few days. 

    Thanks
    Christoph

  • Hi Christophe ,

    I'd also like to use GCC with this chip. I'm willing to spend some time to make this work but it would be more fun if it could be a collaborative effort....Did you get any feedback or make any progress since your port ? Does anybody know if some of the similar chips (e.g. ADuCM360 or so) have the same/similar core and do support gcc ?

    Thanks,

      Moritz

  • Hi All ADuCM350 developers,

    I am keen to get a GCC/GNU option for development with this chip, Happy to collaborate.

    Regards

    Paul

  • Hi Paul and everyone else interested in GCC/GNU compilers,

    I got the following toolchain now working under Linux:

    - gcc-arm-none-eabi-7-2017-q4-major -> the actual compiler

    - Eclipse Oxygen .2  --> IDE development tool

    - GNU MCU Eclipse --> plug-in to make life (sometimes) easier

    The way to go is to make a project with the template for a generic Cortex M3 CPUs as described on the GNU MCU Eclipse pages. Next I used the code provided by AD (with some modifications, some of them involving educated guessing, so still some verifications to do) and copied it at the right location in the directory hierarchy. Then I modified things until no errors were left and manually updated the linker mapping file.

    I can compile stuff now and run it with the Gnu Debugger and the Segger JLink software and the JLink that comes with the EVM for the ADuCM350. So far I didn't test the drivers for the peripherals.

    Current problem:

    - sometimes I can't re-connect to my custom board and I have to use the built-in serial bootloader to make it debuggable again (maybe some problems with the clock because I didn't put an external HF quartz on my board; REV B will have one for sure); or maybe the debug pins need some kind of init code to work ?

    You can send me a message at moritz_gnu (AT) LabLab.eu to discuss collaboration.

     Best Regards,

      Moritz

  • Hi Moritz,

    I think it would be great to collaborate. Ideally I would like to produce a CMSIS pack for Eclipse so that the ADuCM350 can be specified as a target.  Here is the link for CMSIS pack creation tutorials and tools.

    Software Packs Overview - Keil

    Paul

  • Hi Paul, Moritz,

    I'm embarking on a new project with the ADuCM350, and am new to Eclipse too. I'm a hardware designer with only some software experience so I'm not sure what I can contribute, but I am willing to pitch in. Have you made any progress on the CMSIS pack development since the last message?

  • Hi Altra-jw,

    I made some progress with Eclipse and the ADuCM350 creating a PACK but there is a lack of information on how to set Packs up. You would think adding a local pack would be easy but it is not, so I have hosted my pack online, but it is still a work in progress. Let me know if you would like to give it a go.

    Currently I am looking at Mbed - really easy to use on supported boards. However the ADuCM350 is not supported but I feel that this is a quicker path than eclipse.

    Paul

  • > the similar chips (e.g. ADuCM360 or so) have the same/similar core and do support gcc ?

    Hi Christophe ,

    As a side note to this forum question, CrossCore Embedded Studio (CCES) analog.com/cces (available on Windows and Linux) which is ADI's Eclipse based development environment supports ADuCM360/1/2/3 development using the latest GCC ARM Embedded toolchain and CMSIS pack files.

    EVAL-ADICUP360 Tool Chain [Analog Devices Wiki]  contains all the instructions you should need to get up and running, including a free and permanent license when using your ADuCM36x and other Cortex-M parts!

    CrossCore Embedded Studio Quickstart User Guide [Analog Devices Wiki]  also contains some great instructions on using the ADuCM36x support available in CrossCore Embedded Studio.

    Thanks,

    Andrew

    P.S. our  EV-COG-AD3029 Evaluation Board | Analog Devices and EV-COG-AD4050 Evaluation Board | Analog Devices  can be used with Arm Mbed · GitHub.