What can cause spikes in the DACs output? Can it be implementation related? - callback

i have 8 external DACs MCP4728 which i'm communicating with using i2c.
The data is coming directly from a USB cable (16-17ms) and i need to update/write those values as soon as i can.
Right now i'm writing to the i2c inside the USB callback function.
Normally i see code (not DAC related) where a flag is set and then in the main loop, since the flag to update is true, something is perfomed (in this case the DACs should be set).
Can the implementation be the source of those spikes (which tipically are present only with high frequency values) ?
Can bit-skew be the problem with 17ms of updating time ?

Related

STM32MP157F dmaengine: dmaengine_prep_dma_memcpy works, dmaengine_prep_dma_cyclic does not

​
We have implemented our custom driver that uses DMA to copy a large amount of data from the FMC interface (an FPGA mapped to it) to the RAM using the STM32 mdma engine with 32 dma channels. The FPGA contains a small FIFO we want to copy the data from.
​
For very fast data acquisition the setup time for new DMA transactions becomes critical!
The first implementation used a workqueue to create the next DMA transaction. It could not be done directly from the "dma_completed" atomic context though some necessary IO that has to wait. This lead to pauses between DMA transaction up to 5ms and buffer overflows in the FPGAs FIFO.
As I am copying from a memory mapped region to RAM, I am using dmaengine_prep_dma_memcpy.
I implemented a number of improvements that reduced the pause betweens DMAs:
I am fusing dma mapped pages so that less dma transaction entries have to be created so less dma engine programming is necessary.
I am preparing the next dma pages upfront. So the next DMA transaction can be directly started from the "dma_completed" routine.
I am using a second dma channel and toggle between them when dma_completed is called. This allows to setup a second DMA with the first one still running. Though linux dma api allows this with one channel, the MDMA engine does not and ignores the added transactions.
Usually the pause is now lower than 1ms. But there a spikes were the FIFO nearly overflowing.
Finally I tried to use dmaengine_prep_dma_cyclic. This would be perfect. A continuously running DMA with no need for a setup time between interrupts.
​But this does not work. Or better: I do not get it to work...
The transaction created with dmaengine_prep_dma_cyclic does not want to start!
I am getting a new dma_cookie and any status request to the channel returns "DMA_IN_PROGRESS". It never completes and the completetion callback is also never called.
Though dmaengine_prep_dma_memcpy works fine...
I think this is because of the difference between software vs hardware triggered DMA transactions.
Looking into stm32-mdma.c is see that dmaengine_prep_dma_memcpy has its own setup routine whereas dmaengine_prep_dma_cyclic use stm32_mdma_set_xfer_param() that always configures a HW request.
My very big big questions:
Is there a way to use dmaengine_prep_dma_cyclic for a MEMORY to MEMORY DMA transaction (software triggered)? This would be the perfect solution to my performance problem...
​Are we missing some signals to connect the FPGA to the SOC? My FPGA programming collegue suspects some missing TSEL (trigger selection) setting. He suspects dmaengine_prep_dma_cyclic will work then.
If a minimum driver module source code example would help in getting better answers, I can provide one in short time. Please note that this is highly hardware specific. Other SOCs than STM32MP157F may have different behaviour.
Thanks for every feedback!
Bye Gunther
References:
https://wiki.st.com/stm32mpu/wiki/Dmaengine_overview
https://github.com/STMicroelectronics/linux/blob/v5.15-stm32mp/drivers/dma/stm32-mdma.c

how to set timer for physical process in Castalia?

As the usual practice in Castalia is that the application module requests for sensor reading using requestsensorreading() function which is handled by sensor manager. Sensor manager forwards the request to physical process and the physical process replies back with its value.
What i want to do is, i want the physical process to broadcast its value at set intervals of time. Sensor device will have a sensitivity > 0 and few nodes will receive the value. How can i accomplish this? is it possible to use timerFiredCallback function and BROADCAST_NETWORK_ADDRESS inside physical process?
You seem to be confused about the basic models of Castalia. The physical process is not a sensor node to send network broadcast messages. It is a module to model
the physical process that sensors in our sensor nodes are sampling. Moreover, a Physical process does not have one value. Values are changing depending on space and time, and depending on the specific model you have defined (the manual has plenty of info on how to define physical processes).You could define a physical process that only returns one value for every point in space and every point in time, but I am not sure why you would like to use such a process in simulation.
A physical process does not "broadcast its value". Sensor nodes sample the physical process and based on space, time, and the specific model of the process they get a value back. Different sensors nodes might get different values back. To achieve what you want, you simply make all sensor nodes periodically sample the physical process. There are some examples of Applications that do that.
So to recap: You define how your physical process needs to behave and then you make sensor nodes sample it (from the Application module using the method requestSensorReading() as you already know).

IC2 SLAVE NOT RESPONDING XC8

Hey guys i've been working on this like 72 hours straight and i can't find the error, i'm working on a PIC16F1719 i'm trying to set 3 peripherials an ADC a I2C Protocol and a USART for comunicating to a BT however the ADC was easy, but i'm having a rough time with the I2C despite the fact i've check the code several times, for some reason when i get the ACK's everything seems OK, but when i go for a lecture on the sensor (MPU6050) nothing shows up but the value i putted last time on the buffer, any ideas why this is happening? It's like the buffer doesn't clear itself and i think i can´t clear it through software, thanks.
i2c slave has the ability to lock the bus if the master does not communicate correctly with it (several possible scenarios...)
This is electirically possible since the 2 wires are wired-and, that means if any slave pulls the clock (for example) down, and keeps it that way, the bus is locked.
Always check first the values on both wires (using scope or dvm), if '0' it means bus locked.
Next test the status register of your i2c controller, it may show arbitration error or something of that sort.
If any of the errors, read the i2c slave part datasheet carefully to check what types of protocol read/write it expects and fix your code.

Omron PLC Ethernet card

I have an Ethernet card in a Omron PLC. Is there any way to do an automatic check to see if the Ethernet card is working? If not, is there a manual way? For example, if the card was to go out on the PLC it would give an error. But if the card just loses signal with the server then it would NOT give error. Any help on how to do this?
There are several types of errors you can check for. The way you do this depends on the type of error. Things you can check :
ETN unit Error Status (found at PLC CIO address CIO 1500 + (25 x unit number) +18)
What it reports : IP configuration, routing, DNS, mail, network services, etc, errors.
See : Manual Section 8-2
The ETN unit also keeps an internal error log (manual section 8-3) that you can read out to your HMI software (if you use it) using FINS commands. This documents all manner of errors internal to the ETN unit.
There are also other memory reservations in the PLC for CPU bus devices (like the ETN unit) which provide basic status flags you can include in ladder logic to raise alarms, etc. (See section 4-3 : Auxiliary Area Data).
These flags indicate whether the unit is initializing, for example, has initialized successfully, is ready to execute network commands, whether the last executed command completed OK or returned an error code (which can be read from the Error Log as above), etc. These can indicate whether the PLC is unable to properly communicate with the ETN device.
You can implement single byte location which will be autoincremented each second by the server. Then every few seconds you check in your PLC logic if old reading is the same as new reading, and if it is then you trigger an alarm that physical server (which is an communication client) is not communicating to PLC ethernet card.

AHCI Driver for own OS

I have been programming a little AHCI driver for two weeks. I have read this article and Intel's Serial ATA Advanced Host Controller Interface (AHCI) 1.3. There is an example, which shows how to read sectors via DMA mode (osdev.org). I have done this operation (ATA_CMD_READ_DMA 0xC8) successfully, but when i tried to write sectors (ATA_CMD_WRITE_DMA 0xCA) to the device, the HBA set the error
Offset 30h: PxSERR – Port x Serial ATA Error - Handshake Error
(this is decoding from Intel AHCI specification). I don't understand why it happened. Please, help me.
In addition, I have tried to issue the command IDENTIFY 0xEC, but not successfully...
You asked this question nearly two months ago so I'm not sure if you've already figured this out. Please note that I'm writing from memory in terms of what must be done first, etc. I may not have remembered all, or accurately, what must be done. You should reference the AHCI spec for everything. The methods for doing this are as varied as there are programmers that have done this. For this reason, I'm not including code examples.
For starters, ensure that you've set the HBA state machine accordingly. You'll be able to find references for the state machines supported by the HBA in that same SATA spec 1.3. In lieu of this, you should check a few registers.
Please note that all page numbers are given with respect to viewing in Adobe Acrobat and are 8 pages more than numbered in the actual document
From page 24 and 25 of the spec., check GHC.IE and GHC.AE. These two will turn on interrupts and ensure that the HBA is working in AHCI mode. Another, very important register to check, is CAP.SSS (Page 23). If this bit is high, then the HBA Supports Staggered Spin-up. This means that the HBA will not perform any protocol negotiation for any port. Before you do the following, store the value of PxSIG (Page 35 and 36).
To actually spin up the port, you'll need to visit pages 33, 34 and 35 of the spec. These pages cover the PxCMD register. For each port supported by the HBA (check CAP.NP to know how many are there), you'll have to switch high bit PxCMD.SUD. After switching that bit high, you'll want to poll on PxSSTS (Page 36) to check the state of the PHY. You can check CAP.ISS in order to know what speed you can expect to see "come alive" on PxSSTS.
After spinning up the port, check PxSIG (Page 35 & 36). The value should be different than when you started. I don't recall now what you can expect them to become, but they will be different. When communication is actually established, the device sends to the host an initial FIS. Without this first FIS, the HBA will be unable to communicate with the device. (It's with this first FIS that the HBA sets the correct bits in PxSIG.)
Finally, after all of this, you'll need to set PxCMD.FRE (page 34). This bit in the port command register enables FIS delivery to the device. If this bit is low, the HBA will ignore anything you send to it.
As I said in the beginning, I'm not sure if this will answer all of your question but I hope that it does get you on the right track. I'm going from memory on the events that must be done in order to effectively communicate to a SATA device. I may not have remembered in full detail.
I hope this helps you.