DMA from Linux kernel-space to PCIe card - linux-kernel

I am trying to write a linux driver for a PCIe device - the Adlink PCIe 7300A High-Speed digital-IO card.
The driver works fine for normal memory transfer, but attempting to use the card's bus-mastering capabilities to initiate DMA transfer of a buffer from CPU memory to the device's output FIFO buffer simply does not work.
I have been trying to solve this problem on the order of weeks, not on the order of days.
Any insight at all would really really be appreciated.
Driver code -- https://github.com/sbrookes/timing_driver_sdarn/blob/master/kernel_land/timing.c
Device Datasheet -- http://www.acceed.com/manuals/adlink/P7300A%20Manual.PDF
PLX 9080 PCI Interface chip Datasheet -- http://www.der-ingo.de/bin/milanhelp/PLX9080.pdf
I can not explain how much I would appreciate any bit of insight.
Thank you,
Scott

I seem to have solved the problem. It seems like there was an incorrect condition in the interrupt handler that was aborting the DMA transfer at the wrong time, never letting the transfer even begin.
A serious "duh" moment, but it took serious struggle to find it.
As per the comments, sorry if I polluted SO with my desperation. Still learning how to be a good citizen.
Not sure if the code linked above will remain static as my project changes or whether that link will reflect the most current version. Basically just be careful not to abort your transfer at the wrong time.

Related

What does the kernel do once put into memory?

I'm a first year grad student trying to write an Operating System from scratch as a side project. I've read the Linux Programming Interface, Modern Operating Systems 4th edition, a bunch of articles on OSdev wiki's, and anything I can find on Google, but I'm having a tough time finding what I should be doing next after writing a simple bootloader, and a kernel that can take user input and display it back onto the screen.
I have a feeling that I need to create some drivers that interact with the file system and memory, but I'm not entirely sure. I'm trying to work my way up with just physical memory and one process running "kernel" for right now. I'll worry about virtual memory (pagging) and multi-processes later. If anyone can give me some kind of direction or better understanding of what happens when the kernel is finally put into memory, that would be great.
Thanks.
I would like to point a resource that will be of great help for you to understand this stuff in real details. One of the great and evolving resource that is being maintained on git.
https://github.com/0xAX/linux-insides/tree/master/Booting

Hitting a Breakpoint causes flashmemory to lose writing capability

I have a phenomenon that I fail to understand.
Im using an Atmel UC3C (AVR32) (together with Atmel Studio 7.0) to capture data from UART and writing it to Flash (I'm aware of the limited write cycles).
I set a breakpoint after the write instruction to check if everything went smoothly. It did, but only one time, when I clicked on "continue" and send UART data again, the data will appear in RAM but won't be written to flash.
I don't get any errors or exceptions (I'm catching uart errors and flash-erase errors). I can reproduce that at will. As soon as a breakpoint is hit (anywhere in the application), flash loses the capability to to write data.
The best part is, when I remove the breakpoint, it works flawlessly (I set a breakpoint after multiple writes and looked at all the written flashpages to see if the changes were applied).
I checked for race-conditions but havn't found any. Uart data is buffered in a circular buffer, if the buffer would overflow, then the UART is blocked and the buffer is flushed (there is no sensitive data transmitted).
My question is: Why is a breakpoint interfering with the program flow, to a point, that it breaks the flash-write capability?
edit: A reset is giving the write capability back to the flash.
These kind of phenomenon could be caused by several things:
On pretty much any MCU, the flash driver code that is writing to the flash cannot be located in the same flash bank as is currently being programmed. When you have this problem, you can usually either provoke it or make it seem to go away by introducing breakpoints, or by single-stepping. Most commonly such code might work when single-stepping, but break when free running.
The solution is to preferably place the flash driver in a different bank than the one getting programmed. A more questionable alternative is to load the flash driver into RAM and execute it from there. (The RAM method is actually recommended by several MCU vendors, even though executing code from RAM is widely known as dangerous practice for multiple reasons.)
Your breakpoint could be interrupting the flash programming. Most flash drivers do not tolerate to get interrupted in the middle of execution. You must not allow any form of interrupt to be executed during flash programming. This includes all other interrupts in your program too. Set the global interrupt mask during programming (and make sure there are no non-maskable interrupts).
Similarly, if your flash driver is based on interrupts, make sure that the debugger isn't blocking interrupts when you set a breakpoint.
Your flash clock pre-scaler could be incorrectly set, resulting in odd behavior when you alter the real-time behavior, by for example by introducing a breakpoint.
In addition, UART and other serial peripherals may have status registers that are cleared by reading them, followed by a read of a data register. Debuggers that read all registers, for example for the purpose of displaying a memory map, may destroy such status flags. This could also be the case.

Enabling dynamic debug makes my camera driver behave better

I am prototyping the driver for an 8 bit parallel image sensor on an ARM device with a built-in ISP. I will spare the details, as I seek for general guide on how to approach this particular problem I am having.
Simply put, when I load the ISP driver (not my prototype camera driver) with dyndbg=+pt flag, the camera driver usually grabs images (about ~8 out of 10 attempts). If I remove the flag, and load the ISP driver without any options, my camera driver rarely finishes its job (about 1 out of ~100 attempts). The system gets stuck saying the device has timed out.
I suspect loading the driver with debug flag is somehow altering the timing, resulting more stable interaction between the ISP and the image sensor. I mostly spend my hours debugging electrical aspects of embedded boards, and rarely delve into a deep software stack such as ISP or Video4Linux. Hence my conjecture may be completely off.
Therefore some pointers will be much appreciated. The kernel is 3.18.
You haven't provided a lot of details for us to work with here, but if enabling debug is making your device work, my suspicion would be that the debug output is introducing a delay which is required for your device to work properly. I'd read through your device datasheets carefully to see if there are any timing requirements you might not be respecting.

How do I access a specific register of my Intel chipset?

I want to read the "TSTR"-register (Thermal Sensor Thermometer Read Register) of my Intel Chipset.
I have found that the __readmsr function is what I need.
I have also setup a kernel driver since the function is only available in kernel mode.
But I have no clue how to access the register...
In the datasheet of the chipset it is stated on page 857 that the offset adress of the register is TBARB+03h.
How can I use this adress? Are there tutorials out there that could help me?
Thanks!
As far as I have figured out, trying to do the exact same thing, __readmsr is indeed the right command for accessing registers:
http://msdn.microsoft.com/en-us/library/y55zyfdx%28v=VS.100%29.aspx
however I am working on an i5, and Intel's documentation
http://www.intel.com/content/www/us/en/intelligent-systems/piketon/core-i7-800-i5-700-desktop-datasheet-vol-2.html
suggests that things like MC_RANK_VIRTUAL_TEMP entries are registers, so it ought to work, so you are on the right track probably.. the particular register is on page 272. So technically this is indeed the answer, __readmsr(1568) in my case.
However I am struggling to convince visual studio 2010 to build this in kernel mode, which it seems reluctant to do, I keep getting the Priviledged Instruction error.. When I get this out of the way and the whole program working I'll write a tutorial on the general process, but until then I only dare give a theoretical answer. If your compiler tends to listen to what you say, just add the /kernel compiler option, since you are only reading and not editing the registers it should be safe.
Edit:
There is also this article, the answer more or less suggests what I'm trying to do, though not much more than I have so far, but take a look anyway:
How to access CPU's heat sensors?
"This instruction must be executed at privilege level 0 or in real-address mode; otherwise, a general protection exception #GP(0) will be generated."
http://faydoc.tripod.com/cpu/rdmsr.htm

Image downloads with a digital picture frame

I'm interested in hacking one of those digital picture frames (like you see for sale at Walmart) so it fetches and displays an image off the web every 5 minutes or so. (I'm going to have it load a current image.) Any ideas on how to get started?
I don't think any of them have a form of internet connectivity. I think that would be your first goal. I would start by looking at microcontrollers. The Arduino being a popular one, or the Atmel AVR chips it is based on. The Arduino has at least one add-on called an ethernet shield which you could use to gain network connectivity. You'd have to author some code that is capable of connecting to the site and downloading what you want, depending on the chip storage capacity and your coding ability, it might be very simplistic or quite sophisticated.
Next, you have to have some way of getting the device to use the downloaded images. I don't know if the picture frames use a USB connection to load images onto internal memory, or rely on some sort of flash memory card. If it simply reads an SD card, I don't know how you would be able to hack that, unless you inserted your device between the card reader in the picture frame and your own on-board memory. If it's a USB device, you could make your device emulate a USB flash memory drive.
I'm sure there are many ways to hack these things, you might find some more suggestions on instructables.com, which has numerous microcontroller projects.
Just a note, the Arduino and Atmel AVR chips are a lot of fun to work with, but the learning curve can be a challenge. You can write code for them in C or assembler, or one of the many proprietary languages for microcontrollers. Also Atmel isn't the only choice, there are also PicAxe and BasicX and others.
Robotshop.com has a good selection of controllers, but check around on the web, as there are literally hundreds of choices and vendors.

Resources