SPI interface 3-wire serial Si471X - interface

I tried to find an answer to this question by searching SDIO which is related to my question based on Silicon Labs naming of data channels. However, I was flooded with topics related to the SDIO protocol for serial comms with an SD memory card - a totally different concern.
I want to interface a PIC MCU (SPI bus) with Silicon Labs FM TX/RX 47XX chips which describe a serial control interface and the multiple ways to use it - what they call 2-wire (basically I2C) or what they call 3-wire and refer to as "SPI". The 3 lines are SLCK, SEN and SDIO (clock, enable, and data input/output half-duplex over the same wire).
My problem is that SPI is full duplex capable - TX and RX simultaneously. Even though every implementation I've seen of this is really half-duplex - send then receive - the hardware is wired with SDI/SDO or MISO/MOSI or called whatever lines in the SPI module; a separate data IN and a data OUT wire. Along with SCLK and SEN (clock and enable).
I'm not sure how to wire this up - and whether it will work. Do I wire both the SDI and SDO pins of the PIC (SPI module) to the same SDIO on the Si47XX? Since the Si47XX is half-duplex that would make sense; but I've never seen the two lines tied on an SPI interface. Not sure if the pins are always Hi-Z for example and I don't want to fry something out. Would I need to add pull ups/downs?
Oddly, I can't seem to find an actual wiring diagram of such a case. When I search 3-wire SPI I always get examples where SEN is tied since only one slave device is being used - not my situation. Any advice would be - as always - greatly appreciated.
-Rick

One can interconnect SPI and 3-wire devices using the following schematic. It does not matter which device is master and which is slave.
SPI device 3-wire device
----+
SDO |--/\/\/\-+ 3k
| | +---
SDI |---------*--------| SDIO
| |
SCK |------------------| SCK
SEN |------------------| SEN
----+ +---
If a 3-wire device is in reception state, then SDO signal comes via resistor to (Hi-Z) SDIO pin and back to SDI pin.
If the 3-wire device is in transmission state, then SDIO output overrides SDO value.
The example of such connection one can see in FTDI datasheet for FT2232H, page 37 (Figure 4.1RS232 Configuration) — 93С46 to FT2232H connection.
At lower SPI frequencies one can use higher resistor value for lower overriding current. It's depend also from traces length but in usual cases 3k is in very good marging for frequences up to 2 MHz.
p.s. It seems that the question is not about programming. Could it be moved to electronics.stackexchange.com?

Related

How to use linux gpio subsystem with PySerial for RS485 DE signal (RTS)

I'm using PySerial to communicate to some devices over RS485 multi-drop. I am bit-banging the DE signal to enable transmission before sending a packet and releasing it at the end.
The problem is that the time for release varies, especially under processor load, and the responses from the devices get clobbered (and aren't received).
I know PySerial has RS485 support, but from everything I've read about my embedded SBC (NXP iMX6 Dual), the RTS signal is not available on the GPIO connector. I just have arbitrary GPIO to use.
Is there a way to map an arbitrary GPIO signal to the RTS functionality so that the Linux tty drivers will assert/deassert my desired GPIO pin?
The following statement gives me some hope (https://www.kernel.org/doc/html/v4.17/driver-api/gpio/drivers-on-gpio.html)
"""
... there are special GPIO drivers in subsystems like ... the TTY serial subsystem to emulate MCTRL (modem control) signals CTS/RTS by using two GPIO lines.
"""
There seems to be some kind of support for in the tty driver for /dev/ttyimxN devices.
https://github.com/torvalds/linux/blob/v4.14/drivers/tty/serial/serial_mctrl_gpio.h
https://github.com/torvalds/linux/blob/v4.14/drivers/tty/serial/imx.c
unsigned int have_rtsgpio:1;
But how can I set this up with PySerial?
How can I specify the GPIO port to use (if at all)?
Thanks for any help !!
EDIT
I've found info in the kernel sources that match the kernel on my board. This describes how to specify the gpio for modem control emulation (software control, instead of hardware control).
https://github.com/ADVANTECH-Corp/linux-imx/blob/adv_4.14.98_2.0.0_ga/Documentation/devicetree/bindings/serial/serial.txt
So it seems possible by changing the device tree sources and making a new device tree blob for my system.
This should all be independent of pyserial.
I'm not sure if this can be set/overridden at runtime with an ioctl, which would be handy (instead of having to muck around with kernel sources and building device tree blobs, etc).

Is there a HAL library ISR function that automatically triggers when a byte is received into the Rx buffer of SPIx on STM32L4xx?

I am wondering if there is a user-definable, built-in ISR function in the HAL library that triggers as soon as a byte is received in the SPIx Rx buffer on STM32L4xx MCU? For instance, as a startup test, I would like to send one byte (0xBC) from a Master STM32L452 nucleo board via SPI2 to a Slave STM32L452 nucleo board. Once the Slave board receives the byte, it flashes LED2, and transmits a different byte (0xCD) back to the Master. Once the Master receives the byte, it flashes LED2 as confirmation. I have initialized both boards as Master/Slave, enabled DMA and global interrupts, 8 bits per transfer using MXcube. I can achieve what I want using the HAL_SPI_Transmit_DMA() and HAL_SPI_Receive_DMA() functions and delays written into the while(1) portion of my main routine (as below). However, I would like to achieve the same using an ISR function that automatically executes once a byte is received into the SPI Rx Buffer.
Master Code:
uint8_t spiDataReceive = 0;
uint8_t spiDataTransmit = 0xBC;
while(1) {
if(!HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13)) {
//Transmit byte 0xBC to Slave and Receive Response
HAL_SPI_Transmit_DMA(&hspi2, &spiDataTransmit, 1);
HAL_Delay(20);
HAL_SPI_Receive_DMA(&hspi2, &spiDataReceive, 1);
if(spiDataReceive == 0xCD) {
flashLED2();
spiDataReceive = 0x00;
}
}
}
Slave Code:
uint8_t spiDataReceive = 0;
uint8_t spiDataTransmit = 0xCD;
while(1) {
HAL_SPI_Receive_DMA(&hspi2, &spiDataReceive, 1);
HAL_Delay(10);
if(spiDataReceive == 0xBC) {
HAL_SPI_Transmit_DMA(&hspi2, &spiDataTransmit, 1);
flashLED2();
spiDataReceive = 0x00;
}
}
No library is needed. You need to set RNEIE bit in the SPI CR register and enable in the NVIC the interrupt. 2 lines of code. No libraries needed.
The only needed resource is the Reference Manual from the STM website.
Yes, the HAL provides user callbacks. In order to use those, you have to activate the corresponding interrupt in NVIC and have the HAL handler called by the interrupt vector table (please have a look at stm32l4xx_it.c, too).
But before you do so, you should consider the following questions:
If you feel confused or frustrated by the complexity of ST HAL libraries, read the Reference Manual and follow the advice of P__J__ (see other answer).
If you feel confused or frustrated by the complexity of the hardware interface, follow the present answer.
Both HAL_SPI_Transmit_DMA() and HAL_SPI_Transmit_IT() support a variable number of transfer bytes.
If all you are going to need is that one-byte transfer, HAL functions may be an overkill.
Their advantage is that you can run some C library functions without dealing with HW register access in C (if that is quite new to you, coming from the arduino ecosystem). And of course, to transfer more than a single byte through the same interface when you extend your application.
You should decide whether you want to get an interrupt from the DMA you have tied to the UART, or if you want to avoid the DMA and get the interrupt from the UART itself. From my point of view, you should really not trigger an ISR by the same interrupt event which is used to start a DMA transfer to fetch the data!
In the same way as you find a description of the HW registers in the
Reference Manual and
Data Sheet of the controller, you find documentation on the HAL (layering concept, usage requirements etc.) in the
User manual of STM32L4/L4+ HAL and low-layer drivers
(see sections 70 and 102, resp., and chapter 3).
Of course, this interface aims mostly for abstraction and portability whereas directly addressing the HW interface usually allows much better efficiency in terms of latency/CPU load, and ROM/RAM usage. The "Low-Level" library drivers aim for a certain compromise, but if you are new to this whole topic and unsure what to start with, you should either start from the HW register interface, or from the portable HAL library API.
If the specification documents (HW or Lib description) are too abstract for you and you prefer some hands-on information source, you may want to first have a look at STM32Cube firmware examples for STM32CubeL4.
These also include SPI data exchange use cases (SPI_FullDuplex_ComIT for example) that are available for NUCLEO-L4532RE (and others) and described in application note AN4726 (page 16).
In addition to the interrupt selection/handling, you should check two more aspects of your program:
If you get an interrupt from the hardware, there is no reason for the HAL_Delay() calls.
Keep in mind that on SPI, you can only "return" data from slave to master while the master is transferring data (which may be zero data).
Otherwise, the "transmit" call on the slave side will only put data into the TX register, and the SPI peripheral will wait infinitely for the SCK trigger from the master...

I am trying to understand how a JTAG connection is used to test the circuitry in a chip using just 5 pins?

describe how a JTAG connection is used to test the circuitry in a chip using just 5 pins
JTAG is used as a synonyme for the boundary scan protocol, see
- https://en.wikipedia.org/wiki/JTAG#Boundary_scan_testing
- https://en.wikipedia.org/wiki/Boundary_scan
It was the Joint Test Action Group (JTAG) who originally devised this protocol for testing circuitry around chips.
Besides this original purpose, the same protocol is used to program and debug CPUs, FPGAs etc.
In order to use JTAG, you need an adapter device that supports the circuitry you would like to test/debug.
[...] using just 5 pins
You are wondering how to test the entire chip through "just" 5 pins? To get a rough idea, think of a shift register similar to UART and SPI (but keep in mind that JTAG is notably more sophisticated).

one-wire over bit banging vs. one wire over usart

I want to use a sensor with one-wire protocol, the matter is which way of using this protocol is optimized and more rational? over usart or using bit banging?
if it is important I'm using am2305 and stm32fxx microcontrollers.
I'm prefer to use USART+DMA with one buffer for transmit and receive. And I think this choice depends on your skill and requierements of your project.
There many ways to implement one-wire protocol.
exti interrupts + timer base mode
timer input capture + dma
usart interrupts
usart (err interrupts only) + dma
All of them have thier advantages and disadvantages:
busy or free pins
busy or free periferals (tim, usart)
busy or free dma channels
lower or higher frequency of interrupts in programm
easy or hard for implement it
I have different projects where work first and last methods listed above.
You must know which method is preferred for you and your project.

How to use DMA for I2C read on Cortex M3

I'm using an Atmel SAM3S MCU, and their ASF stuff can do I2C (they call it TWI) communications. That's fine, except it's taking too much time from my main loop.
So, I'd like to be able to spark off a DMA transfer to read the data from the I2C device. However, all the docs say you can't turn on TX and RX simultaneously on a half-duplex device like TWI. The docs do show that it has a Peripheral DMA Controller (PDC) register section in the TWI registers, but I can't find any PDC examples, except for the USART, which is full duplex.
The only thing I can think of to try is to set TX section, and the next-RX section, and hope that it automatically enables RX after the TX is done.
Has anyone out there used DMA for an I2C read on the SAM3S? If so, could you point me to some docs or examples?
I'm not familiar with the particular part, however I would suggest that for many common usage patterns your best bet would probably be to only use DMA to handle multi-byte sequences of data. Most I2C peripherals allow data to be read out by performing a start with a "write" address byte, and, if that is acknowledged, sending out an address or other information about what data is desired. This is followed by a restart and a "read" address byte. If that is acknowledged, one may then perform all but one of the byte reads with the "ack" flag set. When that is finished, ask for the final byte to be read with the "ack" flag clear.
I'm not sure whether it would be worthwhile to use the DMA controller to clock out the bytes of the requested address, but probably not worthwhile to try to use it to clock out the first byte of the read command.