control Chip Select manually prior to data read in linux? - linux

Hi I have a SPI touch device with 24 keys, each read will return 3 bytes, containing exact all 24 keys status. My hardware is a custom made beaglebone like device, spi0 is able to read its own write by connecting MISO to MOSI.
Everything (wiring, software) is working perfectly matching this guide: http://communistcode.co.uk/blog/blogPost.php?blogPostID=1
Now my touch device is CS active high device, but it requires to drive the chip select to low and back to high before actual read. I don't seems to have control with SPI cs value, I can only either control it within an actual read phase by specifying CS high or low. From my knowledge I have to use another GPIO to emulate the CS.
Question: any way to control cs freely? (i.e. set 0 or 1 by my code directly?)

I have solved this by pinmux the CS pin to a GPIO, and control it manually prior to actual communication.

Related

how to find out which ioports be assigned to my devices

has linux reserved io port numbers for all manufactured devices.
I have devices like intel built-in network card. or another device I have for wifi (usb) from realtek.
On linux repository on github, device drivers use specific io ports to register. And kernel assign those ports to device driver. device drivers normally request for ports using call to request_region function. so for some ethernet device it requests like following
for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10)
{
if (!request_region(id_port, 1, "3c509-control"))
continue;
outb(0x00, id_port);
outb(0xff, id_port);
if (inb(id_port) & 0x01)
break;
else
release_region(id_port, 1);
}
above starts with 0x110 to 0x200, any port can be assigned in this range by kernel to driver and appear in /proc/ioports file means driver is using that io port by the time of success return from request_region.
Question : So my question is has linux assigned io ports to all manufactured devices usable with kernel 5.7 or latest kernel version?
Question : What if I want to write device driver for any device. How can I find the io ports number range to request to. I dont not expect that I have to look into kernel code and find similer driver port range. so How can I find that io port number range. how to achieve this first step required in writing device driver (any device. be it wifi internet device or ethernet device)
Question : So my question is has linux assigned io ports to all manufactured devices usable with kernel 5.7 or latest kernel version?
No.
Question : What if I want to write device driver for any device. How can I find the io ports number range to request to.
You ask the user for it. After all it's the user who set them using jumpers on the ISA card.
Here's a picture of an old Sound Blaster card (taken from Wikipedia, I'm too lazy to rummage around in my basement now). I've highlighted a specific area in the picture:
That jumper header I highlighted: That's the port configuration jumper. As a user you literally connect two of the pins with a jumper connector and that connects a specific address line that comes from the card connectors to the circuitry on the rest of the card. This address line is part of the AT bus port I/O scheme. The user sets this jumper, writes down the number and then tells the driver, which number it was set to. That's how AT style I/O ports.
Or the driver uses one of the well known port numbers for specific hardware (like network controllers) that dates back to the era, where ISA style ports were still are thing. Also there's old ISA-P'n'P where the BIOS and the add-in cards would negotiate the port assignments at power up, before the OS even started. You can read those port numbers with the ISA-P'n'P API provided by the kernel.
We no longer use this kind of hardware in practice! Except for legacy and retro computing purposes.
Over a quarter of century ago, the old AT / ISA bus was superseeded with PCI. Today we use PCIe which, from the point of view of software still looks like PCI. One of the important things about PCI was, that it completely dropped the whole concept of ports.
With ISA what you had were 8 data lines and 16 address lines, plus two read/write enable lines, one for memory mapped I/O and one for port I/O. You can find the details here https://archive.is/3jjZj. But what happens when you're reading from say, port 0x0104, it would physically set the bit pattern of 0x0104 to the address lines on the ISA bus, pull low the read enable line, and then read the voltage level on the data lines. And all of that is implemented as an actual set of instructions of the x86: https://c9x.me/x86/html/file_module_x86_id_139.html
Now look at the PCI bus: There's no longer separate data and address lines. Instead read/write commands would be sent, and everything happens through memory mappings. PCI devices have something called a BAR: a Base Address Register. This is configured by the PCI root complex and assigns the hardware the region of actual physical bus addresses where it appears. The OS has to get those BAR information from the PCI root complex. The driver uses the PCI IDs to have the hardware discovered and the BAR information told to it. It can then do memory reads/writes to talk to the hardware. No I/O ports involved. And that is just the lowest level. USB and Ethernet happen a lot further up. USB is quite abstract, as is Ethernet.
Your other question Looking for driver developer datasheet of Intel(R) Core(TM) i5-2450M CPU # 2.50GHz suggests, that you have some serious misconceptions of what is actually going on. You were asking about USB devices, and Ethernet ports. Neither of those in any way directly interact with this part of the computer.
Your question per se is interesting. But we're also running into a massive XYZ problem here; it's worse than an XY problem; you're asking about X, although you want to solve Y. But Y isn't even the problem you're dealing with in the first place.
You're obviously smart, and curious, and I applaud that. But I have to tell you, that you've to backtrack quite a bit, to clear up some of the misconceptions you have.

Is there possible to stream infinte data over SPI using DMA on STM32F3?

I'm developing a RF modem based on a new protocol, which has a feature of streaming 96 Bytes in one frame - but they are sent on and on, before communication ends. I plan using two 96 Bytes buffers in STM32 - in next lines I will explain why.
I want to send first 96 Byte frames by the USB-CDC to STM32 - then external modem chip will generate a "9600bps" clock and STM will have to write Payload bits by bits on specified output pin(at the trailing edge of the each clock pulse).
When STM32 will notice that it had sent a half of 96 Byte frame - that it sent to PC notification to send more data - PC will refill second 96 Byte buffer by USB-CDC immediately. When STM32 will end sending first buffer - immediately starts sending second buffer content. When it will send half of second buffer - as previous will ask PC for another 96Byte frame.
And that way all the time, before PC will sent command to stop tx.
This transfer mode - a serial, with using a "trigger clock".
Is this possible using DMA, and how could I set it?
I want to use DMA to have ability to use USB while already streaming data to the radio modem chip. Is this the right approach?
I'm working in project building an opensource radiocommunication system project with both packet and stream capatibilities & digital voice. I'm designing and electronics for PC radiomodem. Project is called M17 and is maintained by Wojtek SP5WWP.
Re. general architecture. Serial communication over USB ACM does not have to use buffer of the same size and be synchronized with the downstream communication over SPI. You could use buffers as big as practically possible so PC can send data in advance. This will reduce the chance of buffer underflow if PC does not provide data fast enough. Use a circular buffer and fill it when a packet arrives from USB.
DMA is the right approach. Although people often say that DMA is only necessary for high bandwidth operations, it may be actually easier to work with DMA than handling interrupts per every byte, even when you only handle 9600 bits per second.
DMA controller in STM32F3 has a Half-Transfer Complete (HTIF in DMA_ISR) bit that you can poll or make it generate and interrupt. In conjunction with the Transfer Complete status (TCIF) and the Circular bit (CIRC in DMA_CCR) you can organize a double-buffered data pipe so that transfers can overlap with whatever else the MCU is doing. The application will reload the first half of the DMA buffer on the HTIF event. When the TCIF event happens, it reloads the second half. It has to be done quickly, before the other half is also completed. However, you need a double buffered pipeline only when you need to constantly stream data, i.e. overall amount is larger than can the size of the DMA buffer.
Stopping a circular DMA may be tricky. I suppose both the STM32 and external chip know how many bytes to send. In that case, after this amount is received, disable the DMA.
It seems you need a slave SPI in STM32 as the external chip generates SPI clock.
DMA is not difficult to set up, however, it needs multiple things to work properly. I assume register-level programming, if you use some kind of framework, you'll need to find out how it implements these features. Enable clocks for SPI, GPIO port for SPI pins, and DMA, configure the pins as AF. Find the right DMA channel for the SPI peripheral. In case of SPI DMA you usually need two channels: TX and RX, but with the slave SPI, you may get away with one. Configure SPI, pay attention to clock polarity and phase, and set it to generate a DMA request for each TX and/or RX. Set the DMA CPAR channel register pointing to the SPI DR register in channel(s) and program all other DMA channel registers appropriately. Enable the DMA channel(s). Enable SPI in slave mode. When the SPI master clocks data on the MOSI/SCK pins, the DMA controller will put them in memory. When the buffer is half-full and full-full, the channel will set the HTIF and TCIF bits and generate and interrupt, if you told it to. Use these events to implement flow control.

How to set chip select in SPI programming for multipleslaves ? (struct spi_ioc_transfer)

Maybe I am asking the wrong question actually but I am just making my first steps in the embedded world. So I am sorry if the question is somehow stupid.
I am trying to program a software for 9DOF IMU in c++ and linux environment.
As far as I understood the SPI, the SS pin has to be low active in order for a transmission to occur. I have seen multiple reading or writing bytes function examples and all using the struct spi_ioc_transfer but they were all single slave examples and there is no mention about setting or configuring the SS in the code. Also When I check the structre of spi_ioc_transfer there is the cs_change however, how does it know which cs we are dealing with from the beginning ?
The chip select (CS or SS) to use is determined by which device node you open.
To talk to a SPI chip with the Linux spidev driver, you open a device such as /dev/spidev0.1. The numbers in the device node file name refer to the bus and chip select, respectively — in this example it would be the first bus (0) and the second CS (1). If you want to talk to devices on different chip-selects, you have to open different device nodes and do ioctls on the appropriate one.

spi_write_then_read with variant register size

As I understand the term "word length" (spi_bits_per_word) in spi, defines the CS (chip select) active time.
It therefore seems that linux driver will function correctly when dealing with simple spi protocols which keeps word size constant.
But, How can we deal with spi protocols which use different spi size as part of protocol.
for example cs need to be active for sending spi word - 9 bits, and then reading spi - 8 bits or 24 bits (the length of the register read is different each time, depends on register)
How can we implement that using spi_write_then_read ?
Do we need to set bits_per_word size for the sending and then another bits_per_word for the receiving ?
Regards,
Ran
"word length" means number of bits you can send in one transaction. It doesn't defines the CS (chip select) active time. You can keep it active for whatever time you want(least is for word-length).
SPI has got some format. You cannot randomly read-write whatever number of bits you want.Most of SPI supports 4-bit, 8-bit, 16-bit and 32-bit mode. If the given mode doesn't satisfy your requirement then you need to break your requirement. For eg:- To read 24-bit data, we need to use 8-bit word-length transfer for 3 times.
Generally SPI is fullduplex means it will read at same time it will write.

SPI data transfer - why MOSI goes to zero half cycle before the data transfer?

I have an SPI signal output from a SPI device. I wonder why the data output (MOSI) goes to 0 half cycle before the actual data is written on the bus? Is it a must condition for an SPI device? If it does not go to zero, would there be any problem on the data transfer?
I use spidev32766.1 on linux (ubuntu 12.04 - kernel 3.7.1), the processor is imx233
Thank you in advance!!
The slave device doesn't care what happens on the data line except for a very short period (usually <1ns) either side of its active clock edge (this window is defined by the setup and hold time specifications for the interface).
I have no idea why your system would put out that "wiggle" though!

Resources