UART based peripheral driver
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
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
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
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
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