Driver Compilation -reg

Hi
I am trying to execute the sample resource manager driver given in Resource Manager document. Currently work on Freescale sabre sd i.mx6 and I have to implement i2c driver on QNX Momentics IDE 6.5 version. Currently lacking in how to compile the sample resource manager either as static or shared. I am flashing my code on sd card and booting it from sd card, so I am able to compile my application, put the binary in prebuilt and update the build file. I recompile the *.ifs but adding new binary and generating new *.ifs and building the entire bsp. Kindly provide suggestions how to do I (i) insert this sample driver into bsp or running kernel (ii) is it possible to use the existing i2c driver available in bsp to perform read and write to i2c device registers from application, if so I need procedure to do that. Looking for suggestions.

Not quite sure what you are asking here.

It sounds like you have successfully compiled the sample resource manager into an executable (Lets call it ‘foo’).
It also sounds like you have also successfully modified the bsp build file (lets call it ‘bsp.build’) to add ‘foo’ to it so that ‘foo’ is in your boot image.

Are you asking how you automatically start your ‘foo’ process when QNX boots on your board?

As far as the second question about using the existing i2c driver from the bsp we need more info. Is this i2c driver written for QNX or Linux or some other O/S? If it’s specifically written for QNX you should definitely be able to use it. If it’s written for another O/S you can probably use it but will need to modify it for difference between QNX and the other O/S.

Tim

Updating in next post

Tim, Thanks for your reply. My first query is about how to attach driver in the QNX kernel, procedure I am not clear from the documents I read, like to know whether the sample resource manager to be compiled as static/shared and as of now I compiled it as static, it generated lib**.o and lib**.a, in these two files which one should go into QNX kernel?. Like in linux, I don’t see mknod,insmod commands active in the image file system, how to enable them?. Next, like to know how to insert the sample driver.
Second query, its an QNX i2c driver in the freescale sabresd BSP, in that driver ioctl is not implemented and it is an multi threaded driver and I don’t see main() implemented for i2c resource manager driver, how does it get initialized all the prototype functions implemented in the i2c driver are defined in proto.h, if there is no ioctl how to perform read/ write to i2c devices.

I new to QNX and got stuck in procedures, looking for support and suggestions.

  1. You don’t place your driver into part of the Kernel like you do in Linux (ie it doesn’t link into the kernel). Instead QNX drivers run as their own process.

Right now you have 2 library files (.0 and .a) than contain your resource manager code (that’s why I assume you have in there). What you’ll need to do is turn that into an executable by creating another file with a main() routine in it. That main() then calls the functions in your library. Note that I l assume you’ve read this on resource managers:
qnx.com/developers/docs/6.4. … esmgr.html

  1. Are you sure it’s a QNX I2C driver? Is it advertized as that?

Ioctl commands are mostly used for resource managers in order to present information to other processes. What I assume you have in that I2C driver is the low level driver code that talks to the I2C hardware. It’s probably got interruptAttach / InterruptAttachEvent calls in it to interact with the hardware.

Assuming that’s the case, what you need to do is put that multi-threaded driver code INTO your resource manager code (this is why it does not have a main()). The idea is the driver gets/sends the data to the I2C hardware and the resource manager part of the code (the ioctl stuff) interacts with other QNX processes.

So what should happen in your main() code is you will start the multi threaded I2C driver. You will also have another thread(s) that handle the ioctl calls so that your resource manager can present the data received from the I2C driver to other QNX processes and receive data from them to forward to the I2C driver.

// Pseudo code
void main ()
{
// Start I2C driver threads from BSP
startI2C();

// Start the Resource Manager ioctl() stuff
startResourceManager();

while(1)
{
      // Handle ioctl requests from other processes.

      // You will also have to add code to copy data received from other QNX processes via ioctl() calls to the I2C driver.
      // You will have to add code to copy data to other QNX processes that is received from the I2C driver.
 }

}

Tim

There is some sample code here from a book written many years ago that was ‘the bible’ for development of this kind of stuff. You should be able to find full sample resource managers here that are actually used for things like the QNX Ram Disk. It will at least give you an idea of how your main() should look.
qnx.com/download/feature.htm … amid=23638
The original PDF book that accompanied it is here
qnx.com/download/feature.htm … amid=23592

Tim, Thanks for the reply. From your response it gave me some clarity that even if I write a Resource Manager(RM) outside the BSP, it should be compiled as “application” to generate a bin. My earlier post might have confused, my driver code has a main(), which calls the RM code calls. Just whatever explained in your recent post I am following that link to write a single threaded RM driver, all my confusion is whether it should be configured as static/shared/application when creating a project. If you have any procedure document for starting a RM driver please share it, as I am running out of time. I have spent a lot of time in understanding the way to compile it. Please do needful for this activity alone. If you have any sample RM driver with application kindly share it.

Correct. Once you have your bin file you add that to your QNX build file so that your bin gets placed in the QNX boot image. I’ll assume you know how to do that since you have the board booting.

Attached is some sample source code for a simple USB printer driver as a resource manager. All the usb* functions are related to USB which you would replace with your I2C communication (are you reading, writing or doing both?).

Tim

P.S. What exactly do you have to do with this board? If you just need to read (or write) to some I2C hardware that can be done without needing a full resource manager. All you’ll need is the driver code (supplied with the board) compiled into a bin where your main() function does the read (or write) to the I2C hardware. The resource manager part is normally used to relay data from the driver to other processes and you may (probably) don’t have.

Tim, thanks for your immediate response. I’m working on freescale i.mx6 sabresd board. I need to develop my own api’s for read/write for i2c functionality. I just started writing outside the bsp, but stuck in linking the modules with BSP. Today I tried writing sample RM with /dev/sample and created as " application" in the QNX C project, bin is copied to prebuilt/bin and update the build file and recompiled the ifs. Now this sample RM bin is in /proc/boot. I executed it with “./XXX” on my serial console shell, it just waits for some input, but it without coming back to shell how do I check whether my new node is created or not, how do I execute the client code/application. Just stuck with procedures…

Anyone trying to develop drivers on QNX, not knowing that these are not linked to the QNX kernel, should read “QNX System Architecture” in the docs. Ideally visit a QNX training course.

The documentation for some of the QNX drivers in QNX BSPs sometimes isn’t very comprehensive. You should reach out to QNX support to get clarity on how to use from an app level.

What do you mean by ‘your new node is created’? Not sure what you are asking / expecting?

Do you have 2 executable binaries or 1? If you executed with ./XXX then you started it running. Do you have a 2nd executable you need to run?

As for why it doesn’t return to the shell, you’ll have to look in your main() code. Does it exit or does it run forever in a while(1) loop? does your code do any ‘printf’ to tell you it executing or where it is?

You should have other consoles available depending on how your .build file is set up. Use CTRL-ALt-(1-4) to switch consoles.

If you add ‘pidin’ to the list of programs in your .build file you can use the ‘pidin’ command to see if your XXX process is running.

Tim

Hi Tim, PFA sample RM with device node /dev/sample. In my earlier post, as you suggested I created RM as application, successfully bin is created then copied to prebuilt and updated the build file. On my target the sample RM resides in /proc/boot and I need to execute it as an application from my serial console and how do I check whether the device node is created successfully in /dev, since if I execute the RM it waits for some input seems then do I execute client program (user space program). Still I am missing something in the procedcure. I looked into the printer driver just please help me, how did you create project meaning(shared/application) and then how did you merge it BSP and then how did you execute printer RM(will RM executes automatically or need to insert into microkernel manually) and printer application program (how devctl is taken). Please do needful.

There are 2 ways you can start your RM.

  1. From the serial console instead of doing ‘./XXX’ do ‘./XXX &’. The & tells QNX to execute the program as a background process and return shell control to you. Then you can do other commands like run your client program.
  2. In your .build file you can automatically start your RM at boot time. This is done in the ‘startup-script’ section. I don’t know what that section looks like in your .build file. But basically you just need to add the same entry as I showed above but with a full path ‘./proc/boot/XXX &’. You must have the & in this case or the script will not continue after launching your RM.

Now that your RM is running as a background process you can see if successfully created an entry in /dev by doing a ‘ls /dev’ command. For this you will need to make sure that ‘ls’ is added to the list of binaries in your image.

Assuming your RM is running you can then run your client program from the serial console. If you need to stop your RM for some reason you can use ‘slay XXX’ (slay must also be in the list of binaries in your image).

Tim

Note that I didn’t look at your code because it seems like you just need to launch your RM as a background process.

Tim, Thanks for your suggestions, now successfully loaded the RM and apologies for delayed update. Now I am facing another issue, for register read/write (in16/out16) to be used and defined in arm/inout.h , but when used in the code, it is unable to execute those functions. What could be the reason. Please suggest.

From the doc’s

qnx.com/developers/docs/6.3. … /in16.html

see the Caveats section. Does your code do the ThreadCtl(_NTO_TCTL_IO, 0) request?

Tim

Yes, the code contains ThreadCtl(), but then in() and out() not executing. Is there any difference in adding arm/inout.h & hw/inout.h, both have been tried but not working.

How do you know in() and out() are not executing? Are you running in the debugger or using printf’s? Maybe they are executing but pointing to the wrong address.

There is not much more I can help you with now other than to say the best bet is to attach the debugger and see what’s going on.

Tim

I have following device structure
typedef struct {
unsigned reglen;
uintptr_t regbase;
unsigned physbase;
unsigned short div;
unsigned short slave;
unsigned int status;
iofunc_attr_t attr;
resmgr_connect_funcs_t connect_funcs;
resmgr_io_funcs_t io_funcs;
dispatch_t *i2c_dispatch;
dispatch_context_t *i2c_ctp;
} mx6x_i2c_dev_t;

I have initialized in init section of the code, how do I pass this struct to open,close, read and write iofuncs.