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:

/* ### %DeviceType "%DeviceName" init code ... */
%else %- Language (& Compiler)
%error^ This bean is not implemented in selected language & compiler !
%endif %- Language (& Compiler)
%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

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

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
%- Do not make changes to these lines (if you make some changes, you damage this driver)
%- which begins with:

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

Happy Filing 🙂

What do you think?

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

You are commenting using your 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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.