On 5/9/2024 11:02 PM, Mark Stevens wrote:
Hmmm... the UART device will closed when the kernel thread is killed, right?
When the device is closed, it is also flushed I believe. If those two things
are true, then data loss would be expected, right?
Yes, the UART is closed just before we perform a thread_delete(0).
That would be when the all data is flushed from FIFOs and input buffers
and lost.
Data loss is accounted for in the protocol. We send a known packet to the ESP
and it then responds to the request. This happens several times (we try 40
times). The logic analyser is showing the traffic between the chips and I have
manually checked the packets and the data looks good.
I don't know the details of these UART drivers, but typically when the
driver is closed all data is lost and the receivers are disabled so that
nothing more can be received.
Note that for a UART console, stdin is inherited so that the UART is not closed
when the kernel thread exits.
The UART is opened at the start of the thread not prior to the thread being
started.
We are doing the following:
int start_uart_thread()
{
// Configure the thread properties
handle = kthread_create(… monitor_thread …);
}
void monitor_thread(…)
{
int uart = open(….);
// Setup signalling.
while (!shutting_down) { read and process data }
close(uart);
kthread_delete(0);
}
Hmmm... I see that you are using file descriptors within the OS. That is
not normally done because it is unsafe; it depends on the context in
which the code using the file descriptor operates. If you code operates
on a file descriptor within the OS it could clobber the file descriptors
of a different task/kthread. These standard I/O function should be used
only by user space code and never within the OS.
That is one thing that should be fixed: Use file_open(), file_read()
and file_close() instead. This will correctly avoid use of file
descriptors.
In this case is does the inheritance go both ways? As in if I open the UART
in the kthread does the parent thread keep it open?
You are using a kernel thread above. Kernel threads and user pthreads
work differently:
* The kthreads work just like tasks and the parent kernel thread knows
nothing about the drivers opened by the child kernel thread. The
opened driver will persist until it is explicitly closed (as above)
or until the kthread exists. It will not be kept open for use by
the parent.
* With user pthreads, all file descriptors are shared. If a pthread
exits, any file descriptors opened by the pthread persist until they
are explicitly closed or until the task main thread exits.
The driver may not be closed when the main thread exits either.
Reference counting is used. When the driver is closed the reference
count is decremented. The UART will not actually be disabled until the
reference count finally decrements to zero.
So if you want the open file to persist for the parent of the kthread
you would need to (1) open the driver on the parent (reference count ==
1). (2) Start the child kthread, and (3) open the driver on the child
kthread (reference count == 2). When the child kthread exits (reference
count == 1)
This happens normally through file descriptor inheritance in user tasks,
but file descriptors are not used within the kernel.