[okl4-developer] OKL4 v2.1: Initiate client-to-server data exchange

David Mirabito davidm at ok-labs.com
Tue Sep 9 10:49:17 EST 2008


Hi Frank,
So the way a server works is that someone (usually the 'devicecore',  
as it knows about memory mappings and irq assignments) starts up an  
initializes a vserver. It should make as many calls as necessary to  
device_add_resource() to provide memory mappings (resource is the phys  
addr), interrupts (resource is the IRQ number) or busses (resources  
are the thread_id of of the server implementing the bus, and a handle  
to a device obtained from from the bus server). See platform/s3c2410/ 
iguana/devicecore/src/device_core.c to see how we do this. After  
providing the resources, the device core obtains and keeps a reference  
to the device object. The device is now ready to be accessed by a user.

Depending on how the sever is structured, there may be more or less  
actual RPC calls to the server. For example the serial server only has  
ones to share a memsection created by a client, and inform it of where  
in this memsection the control block is. All further communication is  
done by filling out lists in originating from the block and sending an  
asynchronous notification.
The LCD driver on the other hand, also adds specific calls for  
operations such as getting and setting the screen mode. An ethernet  
driver might have pure RPCs for reading the MAC address and setting  
promiscious mode, but use a series of queues and asynch notification  
for managing tx and rx queues.

The way L4_Notify appears to a recipient is as an IPC from  
L4_nilthread, and the 'A' bit set in the tag which is delivered in  
MR0, and the received payload in MR1. The serverloop initializes the  
acceptor to include notification, indicating that it is also prepared  
to receive notification when it does the open wait (L4_ReplyWait).
When this receives such a notification, the serverloop then checks to  
see the the sender was the nilthread (== 0). If so it is assumed that  
we were notified and the async_handler is called. PIstachio returns  
the bits delivered in a notification in mr[1], which is passed as an  
argument. This is also where we may decide to call the interrupt  
handler, or other RPC functions, depending on the message received.
It's worth pointing out that the generated loop could also have check  
for the 'A' bit in the tag as an alternate means to determine if we  
should call async_handler, in a similar manner to how it checks for  
error conditions.

 From here it is purely up at an agreement between client and server  
on how to proceed (possibly hidden in a library). Serial works by  
keeping track of the various queues, and only notifying (IIRC) when  
one goes from empty to non-empty. This way a client can keep appending  
packets of data to the list without performing system calls, if the  
server is currently processing earlier elements in the list, we trust  
it will eventually get to these new ones in time. If the server  
exhausts the list, it will sleep and we need to wake it with a notify  
when adding the first new packet to the outgoing queue.

A similar scheme is in operation when incoming data from the serial  
port is delivered. A complete draining of the FIFO may place several  
bytes into a packet (depending on driver/server design) which we place  
on the RX head and notify the client. Due to priorities, we may be  
interrupted before the client gets to run with a FIFO full of new  
data. This will go into a second packed appended to the queue, and as  
such there is no need to do another notify. Eventually the client will  
get scheduled, notice the notification and process all the bytes in  
all the packets of his incoming queue.
Also, the vserver needs to have a few empty packets on hand to use for  
incoming data, these are allocated at startup. If the server exhausts  
these, it should disable further interrupts (or perhaps just drop  
further incoming data?) and wait for the client to notify back that it  
has placed new empty packets in the queue for use.
Unfortunately doing this queue manipulation in a safe manner and  
protecting the server from rogue pointers in the list (hence  
memsection-id + offset method, which the server can verify before  
dereferencing) adds to the complexity of the implementation

Of course all this asynch shared memory & notification is just one  
possible implementation. One could just as easily have defined the  
interface to be vserial_put_byte(char byte) or similar, and used this  
RPC call to perform IO. For high-bandwidth applications this may not  
be ideal for performance, but might make an easy starting point when  
getting hardware to actually do something, and then move to an asynch  
model once this works.
Another alternative might be to provide a pointer and length to/of a  
buffer in the registered memsection (near the control block) in a RPC  
call. By the time the call completes, the client knows all data has  
been dealt with and is free to reuse the buffer.
There are just suggestions, a vserver is free to expose whatever  
interface it likes to clients, there are no hard&fast rules - other  
than the init and teardown calls in he device and factory interfaces  
(in the idl4 file) you may use whatever you like in the virtual_spi  
interface.

Unfortunately I do not know enough about SPI and its uses to offer  
more use-specifc advice other than to point out these possibilities.

I hope you found something useful from this mail, let me know if I  
might clear something up further,
  - David Mirabito, OKL



On 09/09/2008, at 3:55 AM, Frank Kaiser wrote:

> Hello
>
> I still have a hard time to get my SPI driver/server working. Due to  
> the lack of documentation I take the VSERIAL driver as an example,  
> and for the client side I use the drivers_example.c code. I try to  
> figure out what is required for the client to control the server,  
> especially to initiate the data transfer.
> The defined IDL4 interface only provides initialisation,  
> configuration and shutdown functions. In the implementation there  
> are 2 times calls of the function L4_Notify(server, 0x1), where  
> server is the thread ID of VSERIAL. One call is at the end of  
> function init_serial(), the other in function main(), which handles  
> the income notification SERIAL. It looks as if the notification call  
> shall initiate sending of serial data, however, I cannot find  
> anything in the server code which handles a notification from the  
> client, i. e. there is no call of function L4_WaitNotify().
> In the generated file server_loop.c there is an IPC reception  
> mechanism which handles two things:
> ·       Processing of IDL4-defined functions
> ·       Handling of an interrupt notification which is directed to  
> the asynchronous handler
> So, where is the client notification going to? To me it is even  
> unclear, how L4_Notify() maps its parameter to IPC (not described in  
> the OKL4 user manual) to see how it looks in the server loop.
>
> Regards
> Frank
> _______________________________________________
> Developer mailing list
> Developer at okl4.org
> https://lists.okl4.org/mailman/listinfo/developer




More information about the Developer mailing list