CDE Hacking: Components with Multiple Files

Typically a Processor Expert component creates two files: a header file and a source file. That’s fine for normal drivers. But this does not work well for more complicated things like an RTOS or communication stacks: these are built from a whole set of source files. So how can I generate multiple files with a Processor Expert Component?

File(s) in the Driver

An easy way is to use %FILE inside the component .drv file. Actually this is the way how I did it for the MicroC/OS-II Processor Component:

%-BW_EVENT_IMPLEMENT_END
%INITIALIZATION
/* ### %DeviceType "%DeviceName" init code ... */
%CODE_BEGIN
%CODE_END
%-
%ENABLE
%CODE_BEGIN
%CODE_END
%-
%else %- Language (& Compiler)
%error^ This bean is not implemented in selected language & compiler !
%endif %- Language (& Compiler)
%DEBUG
%ALL_SYMBOLS
%-
%if defined(OSconfiguration) & OSconfiguration='yes'
%FILE %'DirRel_Code'os_cfg.h

... *** file content follows here

%-************************************
%FILE %'DirRel_Code'ucos_ii.h
%-************************************
... *** file content follows here, and so on....

While generating code for that driver, Processor Expert will see the %FILE command and will create a new file with the following content, and so on.

Note that I’m using %’DirRel_Code’: this will place the file inside the ‘Generated Code’ folder, and the name of that folder is built from that variable. It would be possible to place the file inside a subfolder within ‘Generated Code’, but then you need to make sure the compiler can find that file (setting search path, etc).

That approach is simple, but has a big disadvantage: everything is in one file. And this is especially problematic, if my component is a wrapper to an open source software stack (like FreeRTOS): if the stack changes, I need to compare my version. this is very hard with this approach.

Including External File(s)

My prefered way is to have the files in a separate directory structure: I do this for FatFS, FreeRTOS, PercepioTrace or the FSL_USB_Stack. I’m free where to place the files/folders. A logical place for it is inside the Drivers folder:

Drivers Folder with Component Files Folder

Drivers Folder with Component Files Folder

I have file which includes all the needed files for a component. I have placed them inside the Drivers folder, and I’m using a .prg file extension:

Program Include Files

Program Include Files

The example below shows an extract of the freeRTOS_Files.prg:

%-
%- FreeRTOS source files
%-

%FILE %'DirRel_Code'croutine.h
%include freeRTOS\croutine.h

%FILE %'DirRel_Code'croutine.c
%include freeRTOS\croutine.c

%FILE %'DirRel_Code'FreeRTOS.h
%include freeRTOS\FreeRTOS.h

%FILE %'DirRel_Code'FreeRTOSConfig.h
%include freeRTOS\FreeRTOSConfig.h

%FILE %'DirRel_Code'heap.c
%if MemoryScheme = "Scheme1"
%include freeRTOS\heap_1.c
%elif MemoryScheme = "Scheme2"
%include freeRTOS\heap_2.c
%elif MemoryScheme = "Scheme3"
%include freeRTOS\heap_3.c
%endif
...

Note: the .prg files are included from a driver file. So you can use normal driver code, for example you can test on properties and so on as shown in the example for FreeRTOS: depending on the MemoryScheme, a different file is used and generated.

Note2: Keep in mind that the included files are treated like normal driver files. For example if I have the modulo operator (%) in my source files, I need to replace them with %% in order Processor Expert translates it to a single %. Otherwise Processor Expert thinks it is a symbol and will return an error.

It is as well possible to include from sub folders. Below is an extract from FSL_USB_Stack_Files.prg:

%if CPUDevice="MCF52259"
%- \Device\source\driver\cfv2 -------------------------------------------
%FILE? %'DirRel_Code'usb_bdt_cfv2.h
%include FSL_USB_Stack\Device\source\driver\cfv2\usb_bdt_cfv2.h
%FILE? %'DirRel_Code'usb_dci_cfv2.h
%include FSL_USB_Stack\Device\source\driver\cfv2\usb_dci_cfv2.h
%FILE? %'DirRel_Code'usb_dci_cfv2.c
%include FSL_USB_Stack\Device\source\driver\cfv2\usb_dci_cfv2.c
%FILE? %'DirRel_Code'usb_dciapi_cfv2.h
%include FSL_USB_Stack\Device\source\driver\cfv2\usb_dciapi_cfv2.h
%- the next one is shared between V2 and V1
%FILE? %'DirRel_Code'usb_dciapi.h
%include FSL_USB_Stack\Device\source\driver\cfv1\usb_dciapi.h
%elif (CPUDevice="MCF51JM128") | (CPUDevice="MCF51MM256")
%- \Device\source\driver\cfv1 -------------------------------------------
%FILE? %'DirRel_Code'usb_bdt.h
%include FSL_USB_Stack\Device\source\driver\cfv1\usb_bdt.h
%FILE? %'DirRel_Code'usb_dci.h
%include FSL_USB_Stack\Device\source\driver\cfv1\usb_dci.h
%FILE? %'DirRel_Code'usb_dci.c
%include FSL_USB_Stack\Device\source\driver\cfv1\usb_dci.c
%FILE? %'DirRel_Code'usb_dciapi.h
%include FSL_USB_Stack\Device\source\driver\cfv1\usb_dciapi.h
%elif (CPUDevice="MC9S08JM60") | (CPUDevice="MC9S08JM16") | (CPUDevice="MC9S08MM128")
%- \Device\source\driver\s08 -------------------------------------------
%FILE? %'DirRel_Code'usb_bdt.h
%include FSL_USB_Stack\Device\source\driver\s08\usb_bdt.h
%FILE? %'DirRel_Code'usb_dci.h
%include FSL_USB_Stack\Device\source\driver\s08\usb_dci.h
%FILE? %'DirRel_Code'usb_dci.c
%include FSL_USB_Stack\Device\source\driver\s08\usb_dci.c
%FILE? %'DirRel_Code'usb_dciapi.h
%include FSL_USB_Stack\Device\source\driver\s08\usb_dciapi.h
%elif (CPUDevice="Kinetis K40") | (CPUDevice="Kinetis K53") | (CPUDevice="Kinetis K60")
%- \Device\source\driver\kinetis -------------------------------------------
%FILE? %'DirRel_Code'usb_bdt_kinetis.h
%include FSL_USB_Stack\Device\source\driver\kinetis\usb_bdt_kinetis.h
%FILE? %'DirRel_Code'usb_dci_kinetis.c
%include FSL_USB_Stack\Device\source\driver\kinetis\usb_dci_kinetis.c
%FILE? %'DirRel_Code'usb_dci_kinetis.h
%include FSL_USB_Stack\Device\source\driver\kinetis\usb_dci_kinetis.h
%FILE? %'DirRel_Code'usb_dciapi.h
%include FSL_USB_Stack\Device\source\driver\kinetis\usb_dciapi.h
%endif

Here depending on the component properties, a set of different files get included and generated.

Note the %FILE? (the question mark) syntax: This version of the %FILE syntax needs to be used if the %FILE is inside a conditional block. Otherwise a file will be created anyway (which is not what I want).

Now one thing remains: where to include that .prg file? Well, it could be somewhere in the .drv file, but I recommend to do it simply at the beginning of file (exmple for PercepioTrace.drv):

%-
%include PercepioTrace_Files.prg
%-

%-Driver generated by the Component Wizard
%-
%- WARNING !
%-
%- Do not make changes to these lines (if you make some changes, you damage this driver)
%- which begins with:
%-
%-  %-STARTUSERTYPES
%-  %-ENDUSRTYPES
....

With this, I can structure my files in a logical way, and can easily diff it against other versions.

Happy Filing 🙂

Advertisements

What do you think?

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s