9 bit protocol on UART in embedded Linux - linux-kernel

I am trying to force a 9-bit protocol on a UART in embedded Linux. Currently I am testing this out on the am335x_evm board. I am planning on doing this using stick parity. Ideally I was hoping I would not need to actually modify any of the code for the omap-serial.c driver.
The reason for the 9-bit protocol is to support some legacy hardware that uses it. The parity bit needs to be 1 for the address portion of the message, 0 for the data portion, then 1 again for the termination byte.
I was planning on having a process running in user space that would interface with the UART through standard system calls (open, write, read, ioctl, tcsetattr, etc). I would configure the UART to enable parity and set the stick parity. I would then set the parity to even and call write() to send out my address data. I would then set the parity to 0 and send out the data. My concern is if I change the parity from 1 to 0, when does that take affect? If the UART is not done sending all the address data, will the change in parity apply to any unsent data?

Ended up writing my own 9-bit uart driver. Was the easiest and most efficient solution.

Proper way is to set cs9 on your serial port (and possibly no parity), provided that hardware and driver support this.
I'll search for a link for you...

Related

What is the role of clock for a UART

I'm busy writing a driver for a UART. The, struct uart_port has a field uartclk see this link. According to a slide set I found from free-electrons, this is among the most important fields to initialize. Yet, the Xilinx AXI UART Lite, which I'm writing a driver for, doesn't initialize this member see this link to see.
I'm wondering about the importance of this field. What is this in relation to a UART? Why is it important? What role does it play in the serial core?
Thanks
P.S. I know there's a driver existing. However, this driver assumes the UART Lite is to be used in an embedded environment. In the application I'm writing to, this is not the case.
The UART like any other IP in the system has to have functional and interface clocks. In some IPs it might be same clock, in some it might be more interface or functional clocks. The uartclk field reflects the actual frequency on the input to baudrate generator (don't be confused by the frequency of functional clock which most of the time is constant). When user calls termios to set a desired baudrate the UART driver for actual hardware recalculates uartclk, if needed, and bottom layer, if used, configures the registers. That's how 8250 works. In other cases it might be left unused, if, for example, serial hw driver does everything on its own.

HW device via COM port, access individual pins

I'm currently working on a project which involves dealing with a HW device tailor-made for this purpose.
The device will serve the purpose of sending certain data via serial port (COM1, for instance). The data it is supposed to send doesn't matter that much.
I already have some knowledge regarding Windows serial port communication. CreateFile, WriteFile, and so on... BUT...
There is one "engine" on the device, which will send me the data when I ask it to, and in order to do so, I need to send there a signal (10101010) the rate of which will indicate the clock rate of that device "engine".
Here comes the explanation of how this device work. It gets a signal to send data through one pin. I'm supposed to send there 0 for start, 1 for end. Then, after this, it will watch some other pin for signal, sample it, and based on the frequency of ones and zeroes I send to it, it will start sending data via the thrid pin.
My questions are:
How to access individual pins of COM port?
How to manage the frequency and any delays I will need by myself?
I think that maybe I will have to do on this in kernel more by use of device drivers which will have to be developed.
There is an easier way. The COM port will send out the signal of alternating 1s and 0s if you just send a 0xAA byte.

bypassing tty layer and copy to user

I would like to copy data to user space from kernel module which receives data from serial port and transfers it to DMA, which in turn forwards the data to tty layer and finally to user space.
the current flow is
serial driver FIFO--> DMA-->TTY layer -->User space (the data to tty layer is emptied from DMA upon expiration of timer)
What I want to achieve is
serial driver FIFO-->DMA-->user space. (I am OK with using timer to send the data to user space, if there is a better way let me know)
Also the kernel module handling the serialFIFO->DMA is not a character device.
I would like to bypass tty layer completely. what is the best way to achieve so?
Any pointers/code snippet would be appreciated.
In >=3.10.5 the "serial FIFO" that you refer to is called a uart_port. These are defined in drivers/tty/serial.
I assume that what you want to do is to copy the driver for your UART to a new file, then instead of using uart_insert_char to insert characters from the UART RX FIFO, you want to insert the characters into a buffer that you can access from user space.
The way to do this is to create a second driver, a misc class device driver that has file operations, including mmap, and that allocates kernel memory that the driver's mmap file operation function associates with the userspace mapped memory. There is a good example of code for this written by Maxime Ripard. This example was written for a FIQ handled device, but you can use just the probe routine's dma_zalloc_coherent call and the mmap routine, with it's call to remap_pfn_range, to do the trick, that is, to associate a user space mmap on the misc device file with the alloc'ed memory.
You need to connect the memory that you allocated in your misc driver to the buffer that you write to in your UART driver using either a global void pointer, or else by using an exported symbol, if your misc driver is a module. Initialize the pointer to a known invalid value in the UART driver and test it to make sure the misc driver has assigned it before you try to insert characters to the address to which it points.
Note that you can't add an mmap function to the UART driver directly because the UART driver class does not support an mmap file operation. It only supports the operations defined in the include/linux/serial_core.h struct uart_ops.
Admittedly this is a cumbersome solution - two device drivers, but the alternative is to write a new device class, a UART device that has an mmap operation, and that would be a lot of work compared with the above solution although it would be elegant. No one has done this to date because as Jonathan Corbet say's "...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices", though this is exactly what you are asking for.
I implemented this solution for a polling mode UART driver based on the mxs-auart.c code and Maxime's example. It was non-trivial effort but mostly because I am using a FIQ handler for the polling timer. You should allow two to three weeks to get the whole thing up and running.
The DMA aspect of your question depends on whether the UART supports DMA transfer mode. If so, then you should be able to set it using the serial flags. The i.MX28's PrimeCell auarts support DMA transfer but for my application there was no advantage over simply reading bytes directly from the UART RX FIFO.

Is it possible to query serial port tx pin status (signal low / high) in windows?

Is it possible to query serial port tx (send) pin status if it is active or not ?
For example when issuin break command (SetCommBreak) tx pin is set to active (low). I'd like to know when it is active or not. Thanks.
No. (at least not likely)
If you are using the "16550" family of UARTs, then I am confident that you can not query the serial port tx pin status. Of course, if you are using some new version or other UART family, maybe.
You can assume that the TX pin is in the SPACE state ('0', +Volts) whilst performing SetCommBreak(), but I suspect that is not enough for you.
If you are look to debug your code to know if a break occurred, you can short pins 2 & 3 on a 9-pin D-sub, thus loop backing the transmit to the receive. A paper clip will do. Your receive code would detect the incoming BREAK. Shorting to the incorrect pin does not cause a lasting problem with a conforming serial port, but be careful. Try this first with simple data, before testing BREAK condition.
If you have a "16550"-like UART.
You can put the UART into loop-back mode and see if you receiving you own outgoing BREAK signal. Its somewhat complicated in current PCs. Other UART type may support loop-back.

CAN Bus Protocol Implementation

I want to learn and implement CAN BUS protocol. I have implemented UART,SPI,I2C and One Wire Bus protocol using MSP430 Launchpad in software. Now I want to learn about CAN Bus protocol. I have mBed LPC 1768 Cortex M3 Development board. mBed has Can Bus Library but I want to write my own library so that I can learn it in detail, i.e. the way I did for other communication protocols.
I am not able to find suitable resources to start with and the material appears to be scattered on net. Can any one guide how do i write and implement CAN Bus protocol with the development boards available with me.
Thanks
Developing CAN library is relatively easy as compared to I2C or SPI. This is because CAN Controller of your Cortex will take care of most of complex things.
To transmit the data, You have to write ID and Data in designated registers and set bit to transmit data.
This Application note from NXP can be very useful for you.
I would recommend you to implement following functions:
InitCAN - This should set specified Baud Rate of CAN.
SetFilters - Most CAN Controllers come with Acceptance Filters, So it's good to have that
SendData - Make sure you accept Parameters like ID_Type and RTRs etc.
RecieveData - This can be blocking or Interrupt based.
Before beginning, do read CAN Basics to understand. Application notes AN713 and AN754 from Microchip is a good source. Also Vector's site and Wikipedia Article.
Plus, You can always post your doubts here or on Electronics.StackExchange.com :)
Okay so this post is quite old but people may look at it again so:
First of all Can bus is not user friendly protocol like USART or IC2 at all so you have to be very precise about your can bit timing there are tools for that but I suggest you to calculate them by hand. For a microcontroller I would suggest STM32 and be away from PIC series in my opinion. If it's only CAN-BUS without higher level protocols such as SAE J1939, steps are pretty simple and straight forward:
1)Initialize Can
2)Put CAN to configuration mode and remember that you can set baudrate, mask and filters only in configuration mode!
3) Set the baud rate registers.
4) Set the mask and filters. If you need to receive all messages just simply set mask to 0x00. Then filter will be do not care.
5) Set the CAN to the normal or loopback mode. (loopback mode is used for debugging purposes mostly.)
Some remarkable points people try to implement can at the beginning may miss:
*** You need at least 2 working CAN nodes for successfull transmission. (of course with matching baud rate). So if you want to send some data via CAN with 1 node it will not be succesfull. Because your transmitter node will not receive ACK.
*** Most likely you will need a CAN tranciever. Do not forget to put a 100 ohm or similar value resistor between Tx and Rx pins of your tranciever.
I used the software canking to talk to a mcp25050 when I learned how to implement can protocol using an hcs12 dragonboard. It helped a lot because canking will initialize everything for you when u go on the bus and all you have to do is learn how to write and recieve. If you want to learn how to initialize the steps are:
Enables can bus by setting bit on CAN Control Register 1
Enable can initialization Control Register 0
wait until can bus is in initialization mode by checking control register 1 bit
Enables can bus by setting bit on CAN Control Register 1 again and set clock source - Ethier bus clock or eclock
set prescaler baudrate and Tq with Bus timing register
set sample time and prop_seg1, prop_seg2, and phase_seg
set acceptance id on Identifier acceptance register 0-3 or 0-7 - to set your can to recieve everything set those to 00 because when doing a compare the can bus does a ones complement compare with the id coming in
set Identifier mask register 0-3 or 0-7, if you want to not care about any of the bits set them all to FF
set identifier acceptance control register to 32 bit extended or 11 bit - i use 32
set Control Register 0 back to normal mode
wait until bus is normal mode by checking Control Register 1
after this you can start changing registers or reading data to do this you must select the empty can buffer, write your id to write or request data, and then input the address, mask, and value in the 3 transmitter registers if writing and then specify the dlc (3 if writing and 8-1 if reading). to transmit the id and data you then have to set the can transmit flag to equal the can Transmit buffer selection.
** depending on what id you use bit shifting can be tedious so if you are having a problem I would suggest debugging and looking at what your Transmit buffer selection registers are holding. I had this error because i did not shift correctly when i was sending messages to the mcp25050
If your MCU supports CAN Bus, you should start from the related datasheet.

Resources