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:
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:
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 🙂