RS485 support in pxa255 - linux

I want to use rs485 placed on my card. I'm working on arm-linux and with pxa255 processor. I have already checked "serial.h" located in arm-linux tool chain but unfortunately i couldn't find the appropriate rs485 settings struct although it is supported in some other environments like cris. So now, do i have to write a low-level driver to enable rs485 or is there any other easier way to do this?

I'd recommend reviewing this page about Linux RS-485 support.

There seems to be quite a lot of confusion about serial ports with regards to RS485 mode support on Linux drivers. I think I might be able to shed some light answering this question.
First off, you should ask yourself: why do I want to activate RS485 support on my serial port? I don't know what development board or hardware you're using but be aware that most UARTs work with single-ended TTL levels only (5V or 3.3V levels). That means you won't be able to talk to RS485 devices directly because they only handle differential signals. If you want more details you can see this link: https://www2.htw-dresden.de/~huhle/ArtScienceRS485.pdf for a good introduction.
So you can write as many lines of code and drivers as you want but that won't help your TTL UART talk to RS485. Even if you have a device that supports RS485 on its driver, the hardware itself needs to have a level translator IC (like a MAX485) for you to be able to use it. Fortunately, our beloved Linux Kernel developers know a lot about hardware and you don't have to worry about this (for most devices anyway). Then, answering your question: if you are not able to find the RS485 settings on your driver it will most likely mean your hardware does not offer support directly.
Luckily for you, the solution is quite easy: just get a cheap USB to RS485 dongle. You can find them from 5-10$ and they should work fine out of the box for most scenarios. In my experience, FTDI chips work well.
If you really have to go with one particular UART for any reason whatsoever, for instance, imagine you want to use the UART on your Raspberry Pi or any other where you only have TX and RX signals accessible. Then you have a slightly more difficult challenge ahead of you and you need to study a bit more about how RS485 devices work. The key aspect here is to understand that RS485 on a half-duplex two-wire link (see note below for more details on this). To be able to share a two-wire bus where one or multiple devices are listening and only one is talking at any time, you need an additional control signal (Drive Enable/~Read Enable) on top of your TX and RX (note that when you go on single-ended TTL you have two signals referred to GND using three wires compared to one differential bus with two wires for the RS485 side). Your RS485 transceiver (say MAX485) will need this RE/~DE signal to arrange who is talking and who is listening on the bus, namely: all devices listening on the bus will have this signal low (read enable set) while the talker will be high (drive enable).
Here we get to the essence of your question: where can you get this additional signal? Well, the answer is: it depends on your UART chip. Some chips don't offer anything to work with, then you're left with the option of manually driving in your software application a GPIO line or flow controls signals (RTS or DTR) for UARTS where you have them available. You can read more details on this topic for the particular case of the FTDI chips here: RS485: Inappropriate ioctl for device. There is also a reference to a nice hardware solution to this problem using the mythical 555 timer IC.
Note: more confusing areas: one, RS485 is half-duplex and sometimes mixed up with RS422, which is full duplex and needs four wires; and two: where I say two-wire and four wires I should better say three-wire and five wires because the differential voltage signals need a GND to serve as a return path; sadly, most practical implementations of RS485 are two-wire and they seem to work reliably for most people, but that's a huge topic itself and we can talk about it somewhere else.

Related

Using libMPSSE with FT4232H in Linux

I don't have much experience with the FT4232H.
It is quad a port device.
I want to configure some of the ports as SPI, other as UART and GPIO
I have started experimenting with the SPI .
In the official documentation it says that if ftd2xx and libMPSSE are used
one have to remove the standard kernel modules ftdi_sio and usbserial so I did it.
My question:
In Linux can I have all 4 port configured arbitrary as SPI/UART/I2C/GPIO
as each port uses possibly different driver in the PC?
As far as I know the driver is loaded based on the PID/VID.
It is unique for the FT4232H which has 4 ports, so how this can be done?
Any thought about this is welcome.
I also want to share my current (one day) experience with the libMPSSE.
Unfortunately kind of negative.
I have downloaded the source code for the latest libMPSSE-rev0.6 from the official FTDI web site.
I was surprised to see that no provisioning for compilation under Linux.
There is no Makefile for the libMPSSE. I have made a simple one which is not a big deal but then I found out it does not compile out of the box. I got "undefined type byte" at one location.
After building the library I have done a simple test application which behaved strange.
I was sending 8 bytes on the SPI but with the oscilloscope I was observing 7 8bit clock packets then 100us pause and finally the last 8 bit packet. The MOSI also was incorrect in the last packet.(I was sending all 0 but got two bits high at the end)
Luckily I found https://www.mathworks.com/matlabcentral/answers/518039-ftdi-libmpsse-0-6-spi_readwrite-weird-behaviour-loadlibrary-calllib .
Fixing that made my transfer looks OK.
It looks to me FTDI have not done even a basic check of libMPSSE
I can not understand how FTDI so popular chips can have that low quality software library.
Probably ftd2xx is OK and issues are only in the higher layer libMPSSE?
Anyone using libMPSSE? Should I expect more issues?
Any thoughts about FTDI solution stability is welcome.
Thanks
Dimitar
First of all:
In my understanding, large part of your "question" is not really a question but a "discussion starting point" which is not the scope of the "stack-..." ecosystem.
To the driver question part:
To the best of my knowledge, the driver is loaded once per device and not per port. However, the ftd2xx is able to address each port individually and set them to different modes (basically it simple gives the specific orders to the MPSSE engine which does not really care about the real meaning of the given sequences). Only thing you lose is the convinent VCP accessability.
The different libMPSSE modes have their limitations and quirks. A website search will yield more than enough as a starting point for more narrowed down follow-up questions. If you are only interested in one mode, an IC dedicated to only this mode might be an alternative to the relatively "generic" FTx232x serie.

Serial communication behavior

Im trying to learn about serial communication and I saw that command in below link
http://www.tldp.org/HOWTO/Serial-HOWTO-19.html#pinout_
Only 3 of the 9 pins have a fixed assignment: transmit, receive and signal ground. This is fixed by the hardware and you can't change it.
But the other signal lines are controlled by software and may do (and mean) almost anything at all.
So, these 6 pins, are they reliable to control state of them?
I have many devices, is there any way to make hardware handshaking in a common way?
what I have to do, If some drivers does not handle this pins accurately?
Is there any way to make them fixed assigned by program?

Using two USART ports on the STM32-Discovery

I am using an STM32-Discovery board for my first time. I want to use two of the USART ports on the board at the same time to read in serial information. Can the STM32 read in serial information from both of these USART ports at the same time? Do I need to set an interrupt instead, to switch between them?
I realize this is connected to threading on the board, but I do not understand the threading of the board.
You can read and write as many peripherals as you wish. But of course you need to do it a proper way. For example if you poll for the data from UART1 the data can be overrun on the another ones. So you need to implement other methods like using the interrupts. The topic is too broad for the simple answer.

PCIe device discovery algorithm pseudo code

I have a PCIe model written in System Verilog, although I think this question is language agnostic. The model performs PCIe configuration reads and writes and memory reads and writes perfectly in simulation. However, what I need to do is "discover" my PCIe device and configure my config space registers in simulation. Is there a boiler plate chunk of pseudo code that represents the Linux PCIe enumeration process that I can just add my own models transactions functions too so that I can get a "Bus walk", followed by BAR programming, SR-IOV enable if discovered, MSIx config? It seems like this would be a common exercise for PCIe device so maybe there is model.
It isn't terribly difficult to do. Basically you loop through the config space, checking for each each possible device on the first root bus 0. When a device is found, you allocate a memory space for it based on its requested size and program the BARs accordingly. If you find any bridges, you also configure and enable them - the basic bridge registers for this are standard. This includes assigning the upstream and downstream bus numbers, which then allows you to enumerate the new downstream bus, and so on.
I had to do this once to access a PCI I/O card on a system that had no OS or other software environment. It wasn't too bad and that was across two bridges from two vendors, as well as the I/O card registers and the CPU bus root bridge setup. This was PCI, not PCIe, but it would be very much the same. You could even do it with completely hard-coded numbers if the hardware never changed, but in my case there were a couple variants so I actually had to do some simple enumeration to find the device numbers dynamically. One gotcha is that you may have to delay a bit, or retry, to give all the devices time to come online before you try to access them.
In doing that I found this book to be invaluable: PCI System Architecture (4th Edition). I notice there is also an version for PCIe: PCI Express System Architecture (1st Edition). I would definitely get one of those if you haven't already. These books contain detailed algorithms and explanations about how to do all of this. At the time I didn't really use or refer to any code to speak of, but...
The best code resource I have found is U-Boot. It operates at a similarly low-level and is totally self contained and is still fairly small and as simple as possible. For example, the enumeration appears to start with the function pci_init() calls a board specific pci_xxx_init(). This then sets up the root bridge and then calls pci_hose_scan_bus() in drivers/pci/pci.c to do the real work. Also check out the routines in drivers/pci/pci_auto.c, as well as the rest of the folder.
For your task you probably only need a very small subset and could just hack out parts of these files into a simple driver. Basically a for() loop and some pci_read/write_config() calls with logic to recognize your device and bridge IDs.

Getting ARM/WM8350 audio and power management working in linux

I have a rooted Sony prs900, running a linux 2.6.23 #2 PREEMPT kernel, for ARMv6. (Montavista linux kernel). I'm having problems with figuring out how power management works, both for running the system and for powering up and down the audio port.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
It's worth a little money for help, say $100 paypal donation to an email account, (or more if this takes a long time...) for the first person able to explain to me how to do them in a way that works.
Eg: read battery status, and change some power modes like getting the audio amplifiers to power up/down so that the audio played to /dev/dsp (oss emulation) actually comes out as sound rather than just being consumed by the chip and ignored...
The actual sony kernel, and binary packages of cross compiler tools are located on the main page. Actual kernel sourcecode is also available.
What I have learned so far myself :
The sony is using a wolfson micro WM8350 audio driver and battery charger/power management chip for all the system's power; eg: it can power down/up the SD memory cards, send more power to the cpu, power up audio amplifiers, etc. See: WM8350 Datasheet.
Pretty much, the whole problem revolves around getting the WM8350 kernel drivers to work...
Although the company brags quite a bit about it's support under linux, they don't have any application notes or examples that are actually helpful that I can find, other than the datasheet. I suspect the kernel drivers I have are beta code, because they don't seem to be behaving well (several error messages in the kernel log about wm8350 registers not being readable happen at every boot even when running only the sony's native software...).
The kernel driver's source-code of most interest are in: linux-2.6.23_091126/drivers/mxc/pmic/{core,wm8350}
Notice, the wm8350 is a competitor to the MC14783, but the linux kernel drivers use the same {core} driver source code for both chips; The sony ONLY has the wm8350 on it -- there is no MC14783 present.
The code that I most want most desperately to understand how to make operate is found in the subdirectory {wm8350}, eg: wm8350/wm8350pm/power_supply_sysfs.c.
I want the audio to fire up too, but 'm not quite sure where the pertinent audio amplifier code is yet...
Very clearly the wm8350pm code is designed to export a /sys directory interface; right now /sys is mounted and operational on the system; but I'm not very familiar with the semantics of these newer style interfaces... they aren't quite like the old APM power interfaces for Linux laptops...
First I checked the obvious:
If I do a "cat /sys/power/state" it returns the word "mem" and nothing else.
The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
Doing a find /sys -iname "wm8350" reveals a handful of directories with the patterns:
wm8350-rtc , wm8350-pmic , wm8350-bl , wm8350-power , wm8350-led
wm8350-hifi-dai , wm8350-codec
wm8350-imx32ads.0
So, I do an ls-l on each directory, and look for actual files rather than symbolic links or subdirectories, and what I find are stock useless writable files: bind, unbind, uevent,
and a very few read only files: pmic_reg, dapm_widget, modalias, codec_reg which aren't very helpful.
It's no surprise that:
Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/modalias gives "wm8350-ebx5016-audio"
Doing: cat /sys/devices/platform/wm8350-imx32ads.0/modalias gives "wm8350-imx32ads"
and since audio is off... Doing: cat /sys/devices/platform/wm8350-ebx5016-audi/dapm_widget reveals the audio state:
Headphone Jack: Off
Line In Jack: On
Mic Bias: Off
Left DAC: Off
Right DAC: Off
... (all else off and omitted except )...
EBX5016-hifi: PM State: D3hot
The last two files, I expect should do wm8350 chip register dumps... and one did.
Doing: cat /sys/devices/wm8350-pmic/pmic-reg causes a long pause, then nothing is printed.
but:
Doing: cat /sys/devices/wm8350/platform/wm8350-ebx5016-audi/wm8350-codec/codec_reg does prints a list of registers up to e8 which is just a few bytes larger than the datasheet says the chip should be (0x00 to 0xe6).
I tried using a python program to play wav files, (works on my desktop computer), and I noticed that /dev/dsp does open, the mixers DO set volume levels, and nothing comes out. So -- the audio driver is not able to enable the sound amplifiers on it's own automatically.
There are no alsa sound files in /dev, nor are any alsa tools found on the embedded machine... so I assume Sony is strictly using OSS /dev/dsp and /dev/mixer.
There is only one other access point I can find to the ws8350:
There IS a device driver /dev/wm8350.
That driver created by the source code in subdirectory wm8350/wm8350_reg.c ; in theory it should be able to read and write to all registers using ioctls() calls from a user space. However, something appears grossly wrong with it, for I wrote a test program to read the wm8350 registers... and most of the registers return error messages rather than allowing to be read, including the most pulic ID registers (0x00, 0x01) etc.
So, I'm quite stuck. Pointers, thoughts, hints, are quite desired.
I would like to change your question a little bit.
How does Linux ASOC (alsa system on chip) power management work?
I will answer this and then give some hints on using this specific chip.
.. If I do a cat /sys/power/state it returns the word "mem" and nothing else. The file has permissions -rw-r--r--, so potentially it could be written -- but I don't know with what. The string "mem" does not exist anywhere in the source code for the wm8350pm drivers, so I don't even know if /sys/power/state is part of the source code.
You need to get an understanding of the Linux driver model. Hardware in Linux is structured like a tree. The rational is that things must be powered up/down in specific sequences. For instance, you should not power down the PCI bus controller before powering down the PCI peripherals. Linux builds a tree of hardware and each driver (code) and device (data/actual hardware) has specific call backs/function pointers which handle some specific tasks.
probe - Are you there? Determines actual hardware/device is present.
remove - Shuts down device. Module removal, power off, etc.
suspend - going to sleep.
resume - waking up.
Three and four may look interesting to you. Now, to read about what /sys/power/state is about. The text mem, means that suspend to memory is supported by your system. In this mode, Linux does these steps,
Find first lowest level active bus.
suspend devices on that bus.
suspend bus and de-activate.
If a bus is active go to step 1.
Set CPU to low power state (suspend to RAM).
This is not quite the full story. A few devices may support a wake-up. They will have extra call-backs to enable waking the system from sleep modes. Read the documentation to find out about this.
That is general power management and driver/device structure. Now, how is the ASOC (alsa system on chip) structured?
There are typically three drivers/devices that get stitched together.
Codec - The wm8350 in your case. This includes audio amplifier drive circuitry and can include sound mixing and source controls. Supports digital to analog and analog to digital, typically through an i2s interface. The i2s is not the only interface. Usually a register bank is controlled through a secondary interface; i2c in the wm8350 case.
DAI - Refer to chapter 1.2.18.1 of the iMx31 reference manual; the hardware is called the SSI by Freescale. The next chapter on the AUDMUX is also useful to understand audio support on the iMx31/32.
Machine file - this is the board specific routing. It hooks the DAI to the codec and is the parent of both. It provides board clocking information and other specific configuration. For instance, it may use the AUDMUX to route the physical pins to the SSI block.
An i2c (or SPI) interface from the codec driver to send control commands to the coded chip. Some chips might uses a wacky i2s interface or something else for control (but not in your case).
Now if you understood this, you will see that some features of the wm8350 seem to break the Linux model. The DAI interface can be stopped (digital audio), but the i2c interface must remain alive to program the registers related to the power functionality in the codec/PMIC (power management IC).
The latest WM8350 calls the IC a multi-function device and support was introduced in 2.6.35. The initial support may not have included the WM8350 features. Unfortunately, without some details on the layout of the Sony prs900 board, it would be difficult to know how to use the WM8350 PMIC functionality. The code will involve the iMx31 CPU, the WM8350, the i2c connection, and possibly some power supply circuitry.
For certain, you can just try echo mem > /sys/power/state and see what happens. If it works, you are lucky. The power/current consumption in sleep might not be optimal, but it will probably be hard to fix with the 2.6.23 kernel. You will want to look through the /sys directories for wake-up sources and possibly register these before issuing the suspend to memory command.
I can neither figure out how to read the battery/powerline status information, nor get the audio chip to play sound, etc ... although I have been studying the kernel modules for a while...
From the above discussions, the battery and powerline status will probably be found through another device. However, the pmic_reg file may actually give the status if things are connected properly on the board.
The audio chip will use ALSA. You need to use either alsamixer or the command line amixer to set up audio routes through the codec, so the DAI channel (PCM from iMx32) is routed and sent to the speaker. To minimize power consumption, things are usually turned off by default. The /dev/dsp files are just OSS compatibility. This configuration will support ALSA natively. You are better off to use ALSA if possible.
Donate to the OSF and get a tax receipt, if this was helpful enough.

Resources