8 Replies Latest reply on May 28, 2020 9:13 AM by OmAb_4672891

    Project Library

    OmAb_4672891

      Hello,


      I am writing firmware for a collection of MCU's that network via CAN. As a result, there is a lot of redundant code used between the projects. (i.e, I use a CANUtility.c file to handle all CAN operations. All projects use CANUtility.c the same way, so if I have to make a change, i have to go to all projects and change its CANUtility.c).  To combat this, I thought I'd might make a project library that all projects can include. However I seem unsure on how to do this. It does not recognize certain data types (like uint16, uint8) as i have to include project.h which is not there. In addition, I am unable to reference hardware, such as Pin_1_Read(). Is there a way I can have a file included in each project so that I have to make a change once? I've looked at the tutorials but was unable to do this.

      Thank you

        • 1. Re: Project Library
          OmAb_4672891

          To be more specific, I want to set a DEVICEID variable in main. Depending on this DEVICEID variable I would like to comment out sections of code as Cypress does in generating API source code. For example,

           

          #if DEVICEID ==1

               /* use this piece of code */

               codeA;
          #elif DEVICEID == 2
               /* use this piece of code */

               codeA but defined differently;
          #endif

           

          However, when coming to call codeA in main, it just says undefined refernece.... I would export DEVICEID using extern and using a main.h file.

          • 2. Re: Project Library
            LePo_1062026

            OmAb,

             

            Maybe this link to a Cypress KBA will help:  Creating a Library Project as an Object Code – KBA90606

             

            Len

            1 of 1 people found this helpful
            • 3. Re: Project Library
              MoTa_728816

              Hi,

               

              I tried the following experimental with CY8CKIT--044.

               

              (1) In the workspace I created a folder named common_lib

                   and in the common_lib, I created test.h and test.c

               

              test.h

              ==================

              #ifndef _TEST_H_

              #define _TEST_H_

               

              void codeA(void) ;

               

              #endif /* _TEST_H_ */

              ==================

               

              test.c

              ==================

              #include "project.h"

              #include "main.h"

              #include "test.h"

               

              #ifdef DEVICEID_1

              void codeA(void)

              {

                  UART_UartPutString("CodeA for the Device 1!\n\r") ;

              }

              #endif

               

              #ifdef DEVICEID_2

              void codeA(void)

              {

                  UART_UartPutString("CodeA for the Device 2!\n\r") ;

              #endif

              ==================

               

              (2) Then I created a projectA in the workspace

               

              schematic

              002-schematic.JPG

               

              pins

              003-pins.JPG

               

              main.h

              ========================

              #ifndef _MAIN_H_

              #define _MAIN_H_

              #include "project.h"

               

              #define DEVICEID_1

               

              #endif /* _MAIN_H_ */

              ========================

               

              main.c

              NOTE: Please focus only #includes and main(), other parts are print utilities.

              ========================

              #include "project.h"

              #include "main.h"

              #include "test.h"

               

              #include "stdio.h"

               

              #define STR_LEN 64

              char    str[STR_LEN+1] ;

              void    print(char *str)

              {

              UART_UartPutString(str) ; /* PSoC 4 */

              // UART_PutString(str) ;     /* PSoC 5 */

              }

               

              void cls(void)

              {

                  print("\033c") ; /* reset */

                  CyDelay(20) ;

                  print("\033[2J") ; /* clear screen */

                  CyDelay(20) ;

              }

               

              void splash(char *prog_name)

              {

                  cls() ;

                  if (prog_name && *prog_name) {

                      print(prog_name) ;

                  }

                  print(" (") ;

                  print(__DATE__) ;

                  print(" ") ;

                  print(__TIME__) ;

                  print(")\n") ;

              }

               

              int main(void)

              {

                  CyGlobalIntEnable; /* Enable global interrupts. */

               

                  UART_Start() ;

               

                  splash("ProjectA") ;

               

                  for(;;)

                  {

                      codeA() ;

                      CyDelay(1000) ;

                  }

              }

              ========================

               

              In the project A build setting added "../common_lib" as an include path.

              005-project_a_build.JPG

               

              (3) Then I created a projectB in the workspace

              main.h

              ===============

              #ifndef _MAIN_H_

              #define _MAIN_H_

              #include "project.h"

               

              #define DEVICEID_2

               

              #endif /* _MAIN_H_ */

              ===============

               

              main.c

              ===============

              #include "project.h"

              #include "main.h"

              #include "test.h"

              #include "stdio.h"

               

              #define STR_LEN 64

              char    str[STR_LEN+1] ;

              void    print(char *str)

              {

              UART_UartPutString(str) ; /* PSoC 4 */

              // UART_PutString(str) ;     /* PSoC 5 */

              }

               

              void cls(void)

              {

                  print("\033c") ; /* reset */

                  CyDelay(20) ;

                  print("\033[2J") ; /* clear screen */

                  CyDelay(20) ;

              }

               

              void splash(char *prog_name)

              {

                  cls() ;

                  if (prog_name && *prog_name) {

                      print(prog_name) ;

                  }

                  print(" (") ;

                  print(__DATE__) ;

                  print(" ") ;

                  print(__TIME__) ;

                  print(")\n") ;

              }

               

              int main(void)

              {

                  CyGlobalIntEnable; /* Enable global interrupts. */

               

                  UART_Start() ;

               

                  splash("ProjectB") ;

               

                  for(;;)

                  {

                      codeA() ;

                      CyDelay(1000) ;

                  }

              }

               

              /* [] END OF FILE */

              ===============

               

              In the project B build setting added "../common_lib" as an include path.

              006-project_b_build_settings.JPG

               

              (4) Then when I set the projectA as active project, the Tera Term log was

              001-teraterm_logA.JPG

               

              (5) Then when I set the projectB as active project, the Tera Term log was

              004-TeraTerm-logB.JPG

               

              I wonder if this is doing something you wanted to do?

               

              moto

              1 of 1 people found this helpful
              • 4. Re: Project Library
                NoriakiT_91

                I will introduce a different kind of solution making a custom component.

                 

                Create a symbol element of a component with no terminals and specify the "API suffix" in the Properties

                 

                GS004747.png

                And add a new "uint8" parameter "DEVICEID" in the Parameter Definition.

                GS004748.png

                If the symbol has a label like ID=`=$DEVICEID`

                GS004749.png

                you can see the device ID on your schematic.

                GS004750.png

                The component has no schematics but APIs only.  For example, there is a header file Utility.h

                #ifndef `$INSTANCE_NAME`_H
                #define `$INSTANCE_NAME`_H
                
                #include <cytypes.h>
                
                extern uint8 `$INSTANCE_NAME`_Add8(uint8 a, uint8 b);
                extern char *`$INSTANCE_NAME`_GetDeviceName(void);
                
                #endif /* `$INSTANCE_NAME`_H */
                

                 

                and a C source file Utility.c

                #include "`$INSTANCE_NAME`.h"
                
                uint8 `$INSTANCE_NAME`_Add8(uint8 a, uint8 b) {
                    return a + b;
                }
                
                extern char *`$INSTANCE_NAME`_GetDeviceName(void) {
                    #if ((`$DEVICEID`) == 1)
                        return "ONE";
                    #elif ((`$DEVICEID`) == 2)
                        return "TWO";
                    #else
                        return "N/A";
                    #endif
                }    
                

                 

                Now, you can drop and drop your custom component on your schematic and the API functions can be used as follows.

                    (void)UT_Add8(10,20);
                    (void)UT_GetDeviceName();
                

                Please note that the returned values are not used in my example.

                 

                Please refer the "Component Author Guide" document installed with the PSoC Creator for more details.

                 

                Regards,

                Noriaki

                1 of 1 people found this helpful
                • 5. Re: Project Library
                  OmAb_4672891

                  Thank you everyone for your replies! I have studied all the approaches and they all got me closer to my goal. However I am left with 2 questions.

                   

                  1) My issue was I coudln't find a way to call on generated API code within the libraries. for example using MACROs from CAN such as:
                       msg[1]=CAN_1_RX_DATA_BYTE2(*receiveMailBoxNumber);

                   

                  yields an error. I was wondering if there was a way to include generated API code within the project libraries?

                   

                  2) Is there a way to define a MACRO at run time? I have 4 types of PCB's. I would like to do conditional compiling depending on the type of board. The only way I can do that is through a MACRo. So I was wondering if there was a way I can set that macro at runtime, or have it identifiy some hardware on the board BEFORE it runs?

                   

                   

                  Thakn you again for all your help!!

                  • 6. Re: Project Library
                    MoTa_728816

                    Hi,

                     

                    > Thank you everyone for your replies! I have studied all the approaches and they all got me closer to my goal.

                    I'm glad hearing that.

                     

                    > 1) ..

                    > ...

                    > yields an error. ..

                    What is the exact error message you are getting?

                    If you can provide us a minimum sample project with which we can reproduce the problem,

                    it will help us to help you.

                     

                    > 2) Is there a way to define a MACRO at run time?

                    IMHO, MACRO is fixed at compile time, so you can not define a new MACRO at run time.

                    But if you have defined required MACROs at compile time

                    and let the run time decide which MACRO to be called may be possible.

                    Still you need to provide some clue for the CPU to realize which board it is running on.

                     

                    moto

                    1 of 1 people found this helpful
                    • 7. Re: Project Library
                      NoriakiT_91

                      As a solution to my recommendation creating a custom component, I created a component to have a name of the component which is controlled by the custom component.

                       

                      For example, my use case uses one I2C master component "I2CM" which is shared with two software component instances "I2C_LCD" and "I2C_LED"  The component PCA9632 is my custom component.

                      schematic3.png

                      The I2C_LED instance has a parameter "I2cMasterInstanceName" containing the name of an I2C master component.

                      ledDriverConfiguration.png

                      This parameter can be referred by the source code.  For example, the header file is included from the custom component's API header as follows.

                      #if !defined(CY_I2C_PCA9632_`$INSTANCE_NAME`_H)
                      #define CY_I2C_PCA9632_`$INSTANCE_NAME`_H
                      
                      #include "cytypes.h"
                      #include "cyfitter.h"
                      
                      
                      #include "`$I2cMasterInstanceName`.h"
                      
                      

                      Now, the MACROs in the I2C master component can be accessed from this software component.

                       

                      // MACROs for handling I2C Master API names on SCB and UDB
                      #if (`$INSTANCE_NAME`_IS_SCB_MASTER_USED)
                          #define `$INSTANCE_NAME`_MODE_COMPLETE_XFER         (`$I2cMasterInstanceName`_I2C_MODE_COMPLETE_XFER)
                          #define `$INSTANCE_NAME`_WRITE_COMPLETE             (`$I2cMasterInstanceName`_I2C_MSTAT_WR_CMPLT)
                      
                      
                          #define `$INSTANCE_NAME`_MasterWriteBuf(slaveAddress, wrData, cnt, mode)  \
                              `$I2cMasterInstanceName`_I2CMasterWriteBuf(slaveAddress, wrData, cnt, mode)
                      
                      
                          #define `$INSTANCE_NAME`_MasterReadStatus()     `$I2cMasterInstanceName`_I2CMasterStatus()
                      #else
                          #define `$INSTANCE_NAME`_MODE_COMPLETE_XFER         (`$I2cMasterInstanceName`_MODE_COMPLETE_XFER)
                          #define `$INSTANCE_NAME`_WRITE_COMPLETE             (`$I2cMasterInstanceName`_MSTAT_WR_CMPLT)
                      
                      
                          #define `$INSTANCE_NAME`_MasterWriteBuf(slaveAddress, wrData, cnt, mode)  \
                              `$I2cMasterInstanceName`_MasterWriteBuf(slaveAddress, wrData, cnt, mode)
                      
                      
                          #define `$INSTANCE_NAME`_MasterReadStatus()     `$I2cMasterInstanceName`_MasterStatus()
                      #endif /* `$INSTANCE_NAME`_IS_SCB_MASTER_USED */
                      
                      

                      In my component all I2C master component functions are redefined in the header file.

                       

                      Please refer my repository for more details.

                       

                      Regarding the MACRO referred at runtime, it is impossible because the MACROs are processed by a software named pre-processor and then passed to the compiler.

                       

                      Regards,

                      Noriaki

                      1 of 1 people found this helpful
                      • 8. Re: Project Library
                        OmAb_4672891

                        Thank you very much for all your help!