UART based peripheral driver

2024-09-30 Thread Matteo Golin
Hello,

InSpace uses a radio module for our telemetry systems called the RN2483, which 
is a LoRa radio chip that has a UART
interface.

I would like to have a device driver on NuttX for this module, so I am having 
some of the students try experimenting
with creating one to get an idea of how to write a driver on NuttX.

Unlike sensor drivers where the device's `register` function takes an instance 
of the communication interface device
(i.e. `i2c_master_s` device for I2C sensors, see for example the 
`sht4x_register()` function), it does not appear like
there is a way to get the underlying device struct for a UART interface. It 
seems that the UART interfaces are
registered as part of the `serialinit` step by calls to `uart_register` and can 
only be interacted with from external
code by first calling `open()` on their pathname.

The best idea I can come up with is to have the RN2483 driver perform such an 
`open()` call, so that the registration
function for the device takes the UART output's pathname as an input parameter 
in place of the device struct
(`uart_dev_t`). But this requires that there be a pathname for the UART 
interface as well as the RN2483. I would like to
avoid this so that the RN2483 device takes control of that UART bus and 
arbitrates all communications with the
peripheral.

I did find a function called `stm32_get_uart()` which returns the UART device; 
this is more what I am looking for. It
doesn't seem like most other platforms implement a similar function though, and 
I'm not sure if it is good design to
require that an architecture first implement something similar before being 
able to use this driver. I don't want to
introduce this pattern to NuttX without first checking for other suggestions.

Am I missing an easier way to do this?

Thank you,
Matteo


signature.asc
Description: PGP signature


Re: UART based peripheral driver

2024-09-30 Thread Gregory Nutt

On 9/30/2024 10:51 AM, Matteo Golin wrote:

The best idea I can come up with is to have the RN2483 driver perform such an 
`open()` call, so that the registration
function for the device takes the UART output's pathname as an input parameter 
in place of the device struct
(`uart_dev_t`). But this requires that there be a pathname for the UART 
interface as well as the RN2483. I would like to
avoid this so that the RN2483 device takes control of that UART bus and 
arbitrates all communications with the
peripheral.


There is a special set of interfaces that must be used inside of the OS 
to access device drivers:


 * file_open() and file_close() are the moral equivalent of open() and
   close(), but these return a struct file.  You should use the struct
   file instance to access the driver, not the raw driver interface.

Then there is another set file internal OS interface like:

 * file_read(), file_write(), file_seek(), etc that can be used from
   within the OS to access the file or driver.  These take the the
   struct file instance as a parameter


Re: UART based peripheral driver

2024-09-30 Thread Gregory Nutt

On 9/30/2024 12:25 PM, michal.lyszc...@bofc.pl wrote:

On 2024-09-30 12:51:06, Matteo Golin wrote:

Hello,
I did find a function called `stm32_get_uart()` which returns the UART
device; this is more what I am looking for. It doesn't seem like most
other platforms implement a similar function though, and I'm not sure if
it is good design to require that an architecture first implement
something similar before being able to use this driver. I don't want to
introduce this pattern to NuttX without first checking for other
suggestions.

Whatever Greg said, plus from me: your lora chip is mcu agnostic, so do
not use anything from the arch/ to implement the driver. There should be
absolutely zero arch related code in that driver.

This will allow driver to be used with any MCU that has serial interface.

Also design your rn2483_init() funtion driver to accept struct to initialized
serial driver. It's not your drivers responsibility to initialize serial
device, it should be provided to you by code in boards/ directory. So
in pseudocode it would look like this

   stm32_init_rn2483() {
 struct serial *serial;
 /* get serial device specific to the board, one board will use USART1
  * other might user USART2. Decision which uart to use depends on board
  * hardware wiring and may be different even for the very same mcu */
 serial = stm32_get_serial_for_lora();
 /* initialize rn2483 lora driver and give it handle to the serial device,
  * rn2483 driver can immediately use it from on to initialize the rn2483
  * chip driver */
 rn2483_init(serial);
   }

Yep... There is also a an existing (SPI-based) LoRa driver at 
drivers/wireless/lpwan.  You LoRa driver should go in that same directory.





Re: UART based peripheral driver

2024-09-30 Thread Gregory Nutt

On 9/30/2024 11:50 AM, Gregory Nutt wrote:

On 9/30/2024 10:51 AM, Matteo Golin wrote:

The best idea I can come up with is to have the RN2483 driver perform such an 
`open()` call, so that the registration
function for the device takes the UART output's pathname as an input parameter 
in place of the device struct
(`uart_dev_t`). But this requires that there be a pathname for the UART 
interface as well as the RN2483. I would like to
avoid this so that the RN2483 device takes control of that UART bus and 
arbitrates all communications with the
peripheral.


There is a special set of interfaces that must be used inside of the 
OS to access device drivers:


  * file_open() and file_close() are the moral equivalent of open()
and close(), but these return a struct file.  You should use the
struct file instance to access the driver, not the raw driver
interface.

Then there is another set file internal OS interface like:

  * file_read(), file_write(), file_seek(), etc that can be used from
within the OS to access the file or driver.  These take the the
struct file instance as a parameter

Do 'grep -r file_open *'  to see dozens of examples of this. There are 
some specific examples under drivers/ of drivers that build 
functionality on top a UART serial driver as you are trying to do.


Re: UART based peripheral driver

2024-09-30 Thread michal . lyszczek
On 2024-09-30 12:51:06, Matteo Golin wrote:
> Hello,
> I did find a function called `stm32_get_uart()` which returns the UART
> device; this is more what I am looking for. It doesn't seem like most
> other platforms implement a similar function though, and I'm not sure if
> it is good design to require that an architecture first implement
> something similar before being able to use this driver. I don't want to
> introduce this pattern to NuttX without first checking for other
> suggestions.
Whatever Greg said, plus from me: your lora chip is mcu agnostic, so do
not use anything from the arch/ to implement the driver. There should be
absolutely zero arch related code in that driver.

This will allow driver to be used with any MCU that has serial interface.

Also design your rn2483_init() funtion driver to accept struct to initialized
serial driver. It's not your drivers responsibility to initialize serial
device, it should be provided to you by code in boards/ directory. So
in pseudocode it would look like this

  stm32_init_rn2483() {
struct serial *serial;
/* get serial device specific to the board, one board will use USART1
 * other might user USART2. Decision which uart to use depends on board
 * hardware wiring and may be different even for the very same mcu */
serial = stm32_get_serial_for_lora();
/* initialize rn2483 lora driver and give it handle to the serial device,
 * rn2483 driver can immediately use it from on to initialize the rn2483
 * chip driver */
rn2483_init(serial);
  }

-- 
.-.---.--.-.
| Michal Lyszczek | Embedded C, Linux |   Company Address|  .-. opensource |
| +48 727 564 419 | Software Engineer | Akacjowa 10a; 55-330 |  oo|  supporter |
| https://bofc.pl `.--: Brzezinka Sredzka PL | /`'\  & |
| GPG FF1EBFE7E3A974B1 | Bits of Code | NIP:   813 349 58 78 |(\_;/) programer |
`--^--^--^-'


signature.asc
Description: PGP signature