I would like use external interrupt for a touch screen chip. I could successfully configure the TFT chip right now. But fail to trigger my interrupt. I think I have correct configuration about my MCU.
void STMPE610_check_tp() iv IVT_ADDR_INT2INTERRUPT{
Check_TP();
STMPE610_WriteReg(0x0B, 0xFF);//clear the interrupt status
IFS1.INT2IF = 0;
}
TRISA.b7=1;
Unlock_IOLOCK();
PPS_Mapping_NoLock(23,_INPUT, _INT2);
Lock_IOLOCK();
INTCON2.INT2EP =1;
IEC1.INT2IE = 1;
IFS1.INT2IF = 0;
IPC7 = IPC7 ^ 0x0050;
The global Interrupt enable is missing:
INTCON2.GIE = 1;
Related
So I am trying to hide global memory latency. Take the following code:
for(int i = 0; i < N; i++){
x = global_memory[i];
... do some computation on x ...
global_memory[i] = x;
}
I wanted to know whether load and store from global memory is blocking, i.e, it doesn't run next line until load or store is finished. For example take the following code:
x_next = global_memory[0];
for(int i = 0; i < N; i++){
x = x_next;
x_next = global_memory[i+1];
... do some computation on x ...
global_memory[i] = x;
}
In this code, x_next is not used until next iteration, so does loading x_next overlap with the computation? In other words, which of the following figures will happen?
I wanted to know whether load and store from global memory is blocking, i.e, it doesn't run next line until load or store is finished.
It is not blocking. A load operation does not stall a thread.
Note that the compiler will often seek to unroll loops (and reorder activity) to enable what you are proposing to do "manually".
But in any event your 2nd realization should allow the load of gm[1] to be issued and proceed while the computation being done on gm[0] is proceeding.
Global memory stores are also "fire and forget" -- nonblocking.
I am trying to investigate a memory leak problem and I found out that destructors in my library are not even called and I have the following code:
PPCamNET::Native::PpQueue::PpQueue(int capacity) : m_capacity(capacity), m_array(nullptr), m_head(0), m_tail(0)
{
// Quick fix for case when capacity is 1 (single snap)
// and Push function crashes on 1st frame
if (m_capacity == 1)
m_capacity = 2;
m_array = new FrameData[m_capacity];
m_pushes = 0;
m_pops = 0;
}
The above constructor's destructor should be called after PpQueue is destroyed, but it is not stopping at the break point.
PPCamNET::Native::PpQueue::~PpQueue()
{
delete[] m_array; //<==== here I set a break point
}
PPQueue instance is created by AcqCache constructor.
PPCamNET::Internal::AcqCache::AcqCache(AcqBuffer^ acqBuffer)
{
//m_stopWatchPush = Stopwatch::StartNew();
//m_stopWatchPop = Stopwatch::StartNew();
m_acqBuffer = acqBuffer;
m_cacheLock = gcnew Object();
m_processFrameRunning = true;
try
{
m_frameDataCache = new PpQueue(acqBuffer->BufferSize / 2 + 1);
AcqCache destructor removes m_frameDataCache, which is PpQueue.
PPCamNET::Internal::AcqCache::~AcqCache()
{
m_processFrameRunning = false;
delete m_frameDataCache; // <== here another break point but not called
delete[] m_frameInfoBuffer;
}
Finally the constructor of Acqusition creates an instance of m_acqCache with gcnew.
PPCamNET::Internal::Acquisition::Acquisition(AcqBuffer^ acqBuffer,
CameraSettings^ camSettings)
{
m_eofEvent = gcnew AutoResetEvent(false);
m_acqCache = gcnew AcqCache(acqBuffer);
I am puzzled why these destructors aren't called. Is this because GC didn't kick in to clear up m_acqCache causing other desructors not being called ?
Thanks,
GC will not call a destructor. The C++/CLI compiler translates destructors into IDisposable::Dispose() implementation, and has a different syntax (ClassName::!ClassName) which gets translated to Finalize.
C# wrongly confuses this issue by using the name "destructor" for the CLR Finalize function. Finalizers are not deterministic. The Dispose() function is not called automatically by GC. Not difficult once you know what's going on, but the terminology sure leads to confusion.
Two possible mechanisms come to mind:
IPC like the existing QMP and QAPI
QEMU loads a shared library plugin that contains the model
Required capabilities (of course all possible through the C API, but not necessarily IPC APIs):
inject interrupts
register callbacks for register access
modify main memory
Why I want this:
use QEMU as a submodule and leave its source untouched
additional advantages only present for IPC methods:
write the models in any language I want
use a non-GPL license for my device
I'm aware of in-tree devices as explained at: How to add a new device in QEMU source code? which are the traditional way of doing things.
What I've found so far:
interrupts: could only find NMI generation with the nmi monitor command
IO ports: IO possible with i and o monitor commands, so I'm fine there
main memory:
the ideal solution would be to map memory to host directly, but that seems hard:
http://kvm.vger.kernel.narkive.com/rto1dDqn/sharing-variables-memory-between-host-and-guest
https://www.linux-kvm.org/images/e/e8/0.11.Nahanni-CamMacdonell.pdf
http://www.fp7-save.eu/papers/SCALCOM2016.pdf
memory read is possible through the x and xp monitor commands
could not find how to write to memory with monitor commands. But I think the GDB API supports, so it should not be too hard to implement.
The closest working piece of code I could find was: https://github.com/texane/vpcie , which serializes PCI on both sides, and sends it through QEMU's TCP API. But this is more inefficient and intrusive, as it requires extra setup on both guest and host.
This create out of tree PCI device , it just display device in lspci..
It will ease faster PCI driver implementation as it will act as module,
can we extend this to to have similar functionality as edu-pci of QEMU.?
https://github.com/alokprasad/pci-hacking/blob/master/ksrc/virtual_pcinet/virtual_pci.c
/*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/sysfs.h>
#include <linux/fs.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/version.h>
#include<linux/kernel.h>
#define PCI_VENDOR_ID_XTREME 0x15b3
#define PCI_DEVICE_ID_XTREME_VNIC 0x1450
static struct pci_bus *vbus;
static struct pci_sysdata *sysdata;
static DEFINE_PCI_DEVICE_TABLE( vpci_dev_table) = {
{PCI_DEVICE(PCI_VENDOR_ID_XTREME, PCI_DEVICE_ID_XTREME_VNIC)},
{0}
};
MODULE_DEVICE_TABLE(pci, vpci_dev_table);
int vpci_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
switch (where) {
case PCI_VENDOR_ID:
*val = PCI_VENDOR_ID_XTREME | PCI_DEVICE_ID_XTREME_VNIC << 16;
/* our id */
break;
case PCI_COMMAND:
*val = 0;
break;
case PCI_HEADER_TYPE:
*val = PCI_HEADER_TYPE_NORMAL;
break;
case PCI_STATUS:
*val = 0;
break;
case PCI_CLASS_REVISION:
*val = (4 << 24) | (0 << 16) | 1;
/* network class, ethernet controller, revision 1 */ /*2 or 4*/
break;
case PCI_INTERRUPT_PIN:
*val = 0;
break;
case PCI_SUBSYSTEM_VENDOR_ID:
*val = 0;
break;
case PCI_SUBSYSTEM_ID:
*val = 0;
break;
default:
*val = 0;
/* sensible default */
}
return 0;
}
int vpci_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val)
{
switch (where) {
case PCI_BASE_ADDRESS_0:
case PCI_BASE_ADDRESS_1:
case PCI_BASE_ADDRESS_2:
case PCI_BASE_ADDRESS_3:
case PCI_BASE_ADDRESS_4:
case PCI_BASE_ADDRESS_5:
break;
}
return 0;
}
struct pci_ops vpci_ops = {
.read = vpci_read,
.write = vpci_write
};
void vpci_remove_vnic()
{
struct pci_dev *pcidev = NULL;
if (vbus == NULL)
return;
pci_remove_bus_device(pcidev);
pci_dev_put(pcidev);
}
EXPORT_SYMBOL( vpci_remove_vnic);
void vpci_vdev_remove(struct pci_dev *dev)
{
}
static struct pci_driver vpci_vdev_driver = {
.name = "Xtreme-Virtual-NIC1",
.id_table = vpci_dev_table,
.remove = vpci_vdev_remove
};
int vpci_bus_init(void)
{
struct pci_dev *pcidev = NULL;
sysdata = kzalloc(sizeof(void *), GFP_KERNEL);
vbus = pci_scan_bus_parented(NULL, 2, & vpci_ops, sysdata);
//vbus = pci_create_root_bus(NULL,i,& vpci_ops, sysdata,NULL);
//if (vbus != NULL)
//break;
memset(sysdata, 0, sizeof(void *));
if (vbus == NULL) {
kfree(sysdata);
return -EINVAL;
}
if (pci_register_driver(& vpci_vdev_driver) < 0) {
pci_remove_bus(vbus);
vbus = NULL;
return -EINVAL;
}
pcidev = pci_scan_single_device(vbus, 0);
if (pcidev == NULL)
return 0;
else
pci_dev_get(pcidev);
pci_bus_add_devices(vbus);
return 0;
}
void vpci_bus_remove(void)
{
if (vbus) {
pci_unregister_driver(&vpci_vdev_driver);
device_unregister(vbus->bridge);
pci_remove_bus(vbus);
kfree(sysdata);
vbus = NULL;
}
}
static int __init pci_init(void)
{
printk( "module loaded");
vpci_bus_init();
return 0;
}
static void __exit pci_exit(void)
{
printk(KERN_ALERT "unregister PCI Device\n");
pci_unregister_driver(&vpci_vdev_driver);
}
module_init(pci_init);
module_exit(pci_exit);
MODULE_LICENSE("GPL");
There is at least one fork of QEMU I'm aware of that offers shared library plugins for QEMU... but it's a fork of QEMU 4.0.
https://github.com/cromulencellc/qemu-shoggoth
It is possible to build out of tree plugins with this fork, though it's not documented.
On Nov 11 2019 Peter Maydell, a major QEMU contributor, commented on another Stack Overflow question that:
Device plugins are specifically off the menu, because upstream does not want to provide a nice easy mechanism for people to use to have out-of-tree non-GPL/closed-source devices.
So it seems that QEMU devs oppose this idea at that point in time. It is worth learning about the QEMU plugin system though which might come handy for related applications in any case: How to count the number of guest instructions QEMU executed from the beginning to the end of a run?
This is a shame. Imagine if the Linux kernel didn't have a kernel module interface! I suggest QEMU expose this interface, but just don't make it stable, so that it won't impose a developer burden, and which gives the upside that those who merge won't have as painful rebases.
I tried the following code with cuda 7.0.
If I set n_repeat to 1 and remove the last cudaDeviceReset, the code runs fine.
If I set n_repeat to 1 and keep the cudaDeviceReset, I can run the code segment towards the end but I got a memory leak detected by my memory leak detector after running the program.
If I set n_repeat to 2 and keep the cudaDeviceReset, I got an error in the second time I reach cublasCreate. The error code is CUBLAS_STATUS_NOT_INITIALIZED.
Can some one let me know what is the problem here and is cudaDeviceReset for the purpose of cleaning up between different runs of using the GPU, like what I'm trying to do here?
int device_id_ = 0;
cublasHandle_t blas_;
curandGenerator_t rand_gen_;
long alloc_size = 1000;
char* raw_;
int n_repeat = 2;
for (int i = 0; i < n_repeat; ++i) {
CHECK_CUDA(cudaSetDevice(device_id_));
CHECK_CUDA(cublasCreate(&blas_));
CHECK_CUDA(curandCreateGenerator(&rand_gen_, CURAND_RNG_PSEUDO_DEFAULT));
CHECK_CUDA(cudaMalloc((void **)&raw_, alloc_size));
CHECK_CUDA(curandDestroyGenerator(rand_gen_));
CHECK_CUDA(cublasDestroy(blas_));
CHECK_CUDA(cudaFree(raw_));
CHECK_CUDA(cudaDeviceReset());
}
I had the same problem, even with the example from Robert Crovella, cuda 7 ubuntu 14.04, K40c
Adding cudaDeviceSynchronize() after cudaSetDevice and before cublasCreate() made it work for me
Occasionally I will get an unexpected interrupt, and my code will hang inside Dummy_Handler() in exceptions.c of the Atmel Studio Framework (ASF). I am using the ATSAM3X8E microcontroller of the Arduino Due.
void Dummy_Handler(void)
{
while(1) {
}
}
Any ideas how to determine which interrupt it was?
Of course I could replace this single handler with unique dummy handlers, one for each exception. (There are about fifty of them.) For example change each line in the same exceptions.c file:
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
to this
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_HardFault_Handler")));
Etc... Or try to reason how my code could have generated which interrupt. But who has that kind of time?
This MCU has an Interrupt Program Status Register that gives some clue as to source. ASF has wrapped it in a function __get_IPSR() in core_cmFunc.h:
uint32_t phantomISR = 9999;
void Dummy_Handler(void)
{
while(1) {
phantomISR = __get_IPSR();
}
}
Then this global variable can be monitored at runtime. (In my case I paused the assembly code for this loop-of-death and saw the value 3 in the R3 register.) The Atmel MCU doc explains its value:
ISR_NUMBER
This is the number of the current exception:
0 = Thread mode
1 = Reserved
2 = NMI
3 = Hard fault
4 = Memory management fault
5 = Bus fault
6 = Usage fault
7-10 = Reserved
11 = SVCall
12 = Reserved for Debug
13 = Reserved
14 = PendSV
15 = SysTick
16 = IRQ0
45 = IRQ29
Both times this happened to me it was the Hard Fault, a kind of blue-screen-of-death for the Ardunio Due. So I also installed a Hard Fault handler of my own.
ISR(HardFault_Handler)
{
while (1) {
}
}
Also, detectable in debug mode by pausing. Of course the sequel is, what causes a Hard Fault? I'm guessing memory wipe or infinite recursion.