简体   繁体   中英

Serial Linux embedded Driver with GPIO

i'm trying to develop a driver to communicate with a device. My driver use sysfs to communicate with userspace, and use rs232 to send/receive information from extern device. My Boad and the other device communicate through rs232, but i don't know how to initialise this communication in driver with my rx,tx, cts/rts. I see lot of information about tty. But nothing about using directly GPIO for rs232 communication.

The structure

User -> Board

|-----rx------|
|-----tx------|
|-----cts-----|

device

If someone have an idea :)

Thanks you

I went through a similar problem very recently in my professional career. We ran out of hardware UARTs and needed to implement a UART protocol using a single wire on GPIO.

Now, if I am understanding you correctly (or did I miss the specific architecture you are asking about?), you are trying to implement this on a microprocessor of some sort that can (or is) running linux. Depending on your hardware and what kind of debug tools/programmers you have available, you pretty much have two options to get basic bare-metal (read: no OS) UART communications running that can be extended (and often simplified) with serial port configuration in the linux kernel at the OS level. I won't go into detail on configuring serial ports at the OS level, but if you can do it on bare metal, you can do it in an OS; I will focus on the two bare-bones solutions.

EDIT: I now realize that you are indeed in a full blown OS. Everything below is for the firmware that you will have to develop and associate with the calls Gautham Kantharaju described. So the software UART may not be entirely helpful.

These are:

  1. There are hardware UART ports on your microcontroller/microprocessor that already have dedicated registers for UART configuration and FIFOs.
  2. You only have access to the GPIO module and only have access to the pure GPIO functions - output logic high/low, interrupt configuration (interrupt on rising edge, falling edge; send interrupt to vector or DMA request, etc). and an input data register.

In either case, you need to look through your microprocessor's datasheets and reference manual to first learn about how its UART registers work. You will also almost definitely find application notes for implementing and enabling a UART on your chip. It is pretty standard across hardware with just minor differences between them. There are almost always code examples that accomplish these tasks for you, but depending on your needs, you will likely have to modify at least some of the configuration settings.

You should see some form of registers with:

  1. Some form of an enable register to effectively give power to the module. This can involve ungating a clock register (the module can't function without a clock) and some other steps that may be more hardware specific.
  2. Registers to set the flow control. There can be many here. Ones for enabling flow control all together, whether the CTS line is active high/low, whether to enable interrupts and where the interrupt flag is, etc.
  3. General UART config (likely this will be part of the initialization phase as some UARTs [Freescale's ARM for example] may be initialized by writing to the configuration register. These are where you will see number of stop bits, number of data bits, parity bits, etc. There is a lot that can be configured using UARTs... It is a very mature standard.
  4. Your FIFO registers and how to access them.

Again, your library/application stack will likely include examples that offer macros and functions to accomplish all of these configuration options and in many cases the default config will work. You may need to go into your serial driver (commonly serial.c) and alter the code to fit your needs, but if you know what is going on with the registers and configuration, it will be a lot easier to understand which settings to mess


Now, if it is the latter, you need to implement a software UART. There are many examples out there but it won't do you any good unless you learn the ins and out of the port control of GPIO pins as well as the nitty gritty of what the UART hardware accomplishes. It sounds a lot harder than it is. You will hopefully have two lines: one for RX and one for TX. If you don't need flow control, then that's all you need. Otherwise, you will need an RTS and CTS line. These are just simple GPIOs that control direction with an "active" logic level (can be high or low depending on the hardware - READ YOUR DATASHEET) driven on the RTS pin to indicate a request to send and an acknowledgement from the CTS line indicating that transmission can now begin.

Assuming no flow control for a moment, let's start with a simple receive. Basically, you will need to do some form of an interrupt on the start bit. In the interrupt's handler, start a hardware timer of some kind (Yet another register/module you will have to configure), and either sample the RX line at periodic intervals until the end of the data frame (start_bit + data_bits + stop_bit(s) + parity_bit) or use the timer to time how long a line was held high/low and perform some math in another function (NOT IN THE INTERRUPT HANDLER!). In most cases, you will want the former kind of timer, but if there is an interesting device with a specific handshaking involved, you may need to be more flexible with the timing and opt for the second form of sampling incoming data. Also, a buffer would be very useful and indispensable when debugging, so you may very well want to keep that in mind as you go about implementing this.

To transmit, You will need to disable interrupts (or mask them) so that your transmission will not be interrupted (especially important for a single wire implentation). Then you will have to parse through your data to determine whether each bit is a 1 or 0 (active high or low) and set a hardware timer for one "bit time" (inverse of baud rate).

If flow control is needed, you will just have to add another simple polling method before you go into active receive so that the device knows it is "allowed" to communicate.

If parity bits are enabled, those will also need to be processed either during transmission to be sent out with the data or after a receive to determine whether the data was transferred successfully.

A Google search for "software uart" will yield many examples from ATMEL for their AVR chips and others detailing how to go about implementing one. This app note is good for the basics and underlying theory and the code linked in ZIP on this page really helps explain how to code it .


Hopefully this gave you some good jumping off points.

@Makit, 1) First go through the processor's Technical Reference Manual (TRM) . Understand how to configure UART port to which external device is connected to. Need to write/develop a firmware (OS independent code) where you will be configuring some of the uart registers for ex: Line control register (LCR) , where-in will configure start, parity, stop bit(8N1) and need to configure baudrate according to formula in the TRM and assign the appropriate values to DLL and DLH registers. After this ---> 2) Start with developing character device driver with common file operations (open, close, read and write). After that, need to map identified uart port registers using " ioremap_nocache " kernel api and use return value (pointer value) to read/write external device using ioread[8|16|32]/iowrite[8|16|32] . Uart device driver will use firmware code developed to configure uart registers, read and write to external device. Please feel free to feedback :-).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM