[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