I have written a program to read data from Microchip I2C EEPROM 24XX64. Initially I was able to get an acknowledge from the slave for command byte which indicates a READ operation. Perhaps, instead of data bits I was able to witness stL( write drive low signal) in model simulator. I would like to know the reason for this and what must be done to over come this signal.
To read from an I2C slave, you usually have to write the register address first. The process to read is:
START
Device Address + WRITE
Register Address (# of bytes depends on slave)
REPEATED START
Device Address + READ
Slave ACKs
Master Read bytes and NACKs when it's had enough
STOP
Did you do a write to set up a register address for the read?
Related
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.
In can4linux, a Linux CAN device character driver currently a proprietary FIFO
implementation is used. The driver supports more then on CAN channel
(MAX_CHANNELS) and each channel can be opened by more than one process
(CAN_MAX_OPEN). If a CAN message is received the message is copied in all the
receive FIFOs for that channel.
Currently it looks like:
msg_fifo_t rx_buf[MAX_CHANNELS][CAN_MAX_OPEN];
The fifo size and pointers are defined in the msg_fifo_t. rx_buf is therefore a
big two dimensional array of these msg_fifo_t structures.
How can I solve this with using kfifo?
If a user process wants to read from a special
CAN controller and it is the nth process opening for read, I want to get exactly enter code herethe right fifo (or fifo pointer).
ptr = rx_buf[can[x][n];
Any links for examples or hints are welcome.
When I upload code to my Arduino while the TX and RX pins are connected to my HC-05 module, a bunch of random characters are sent to the TX buffer, and when I connect to a device, those characters are sent and mess up communication. Is there a way that I can clear this buffer after uploading the code? I've just been disconnecting the wires whenever I upload, but I'd like to find an easier way. Thanks!
Well, if you use a serial port to both send data and the program of course you will see it on the other side of the BT... Possible solutions:
disconnect the BT module every time you want to program the Arduino
shut down the other BT device (or just disconnect it) when you have to program the Arduino
shut down the HC-05 (or keep it in reset state) until the arduino says that it is communicating (so use a GPIO to control the reset pin or a transistor to power the BT on at the beginning of the program)
use a 3-state driver between the HC-05 and the Arduino serial ports (one driver for TX and one for RX) and activate its outputs at the beginning of the arduino program.
I don't like djUniversal's solution because you cannot control what the PC transmits; if, for instance, you decide to use the byte 0xAA to signal the start of the transmission then if the PC sends 0xAA the other device thinks that the Arduino is transmitting. Choosing longer bytes sequences helps, because the sequence becomes less probable, but.....
Moreover you have to send it at EVERY command, not just at the beginning, because you have to reset the arduino to program it (and so the other device is not aware of WHEN to stop considering the data).
The only other way around it is to send a header of maybe a couple of bytes each time to send a message. The other program can wait for these characters before it starts to take commands. Until those characters are read from the buffer you would just do a Serial.read() loop to get rid of the garbage.
Also, if garbage characters are going to screw up your program really badly you might want to think about creating some kind of crude checksum also to confirm the correct transmission.
Need help coding? Let me know.
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!
I am trying to send text data from one PC to other using Serial cable. One of the PC is running linux and I am sending data from it using write(2) system call. The log size is approx 65K bytes but the write(2) system call returns some 4K bytes (i.e. this much amount of data is getting transferred). I tried breaking the data in chunks of 4K but write(2) returns -1.
My question is that "Is there any buffer limit for writing data on serial port? or can I send data of any size?. Also do I need to continously read data from other PC as I write 4K chunk of data"
Do I need to do any special configuration in termios structure for sending (huge) data?
The transmit buffer is one page (took a look at Linux 2.6.18 sources) - which is 4K in most (if not all) cases.
The other end must read (don't know the size of the receive buffer), but more importantly you should not write faster than the serial port can transmit, if you are using 115200 bps 8-N-1 you can write the 4K chunk approximately 3 times a second. (115200 / 9 / 4096 = 3.125)
Yes, there is a buffer limit - but when you reach that limit, the write() should block.
When write() returns -1, what is errno set to?
Make sure that the receiver is reading.
You should update the current position it your buffer from the write(), and continue the next write from there. (Applies to all writes(), regardless if the fd is a serial port, tcp socket or a file.)
If you get an error back for subsequent writes. Judging by the manpage, its safe to retry the writes for the following errnos: EAGAIN, EINTR, and probably ENOSPC. Use perror() to see what you get. (..and post it, I am curious.)
EFBIG would seem to indicate that you are trying to write using a buffer (or rather count) that is too large, but that is probably much larger than 64k.
If the internal buffer is filled up, because you are writing to fast, try to (nano)sleep a little between the writes. There are several clever ways of doing this (like tcp does), but if the rate is known, just write at a fixed rate.
If you think the receiver is actually reading, but not much happens, have a look at the serial ports flow-control options and if the cable is wired for DTS/RTS.