Fehler beim Zugriff auf Kerneltreiberdaten vom FIQ-Interrupt-Handler
Bei ARM-FIQ-Interrupts sind einige Register nur für die FIQ-Verwendung reserviert, und dies ist eine praktische Möglichkeit, den Status beispielsweise für die Datenübertragung zwischen FIQ-Aufrufen zu speichern.
Momentan löse ich welche ausGPIO
Stifte von der FIQ, und es funktioniert wie erwartet. Beim Einrichten des FIQ-Handlers übergebe ich die Zeiger an die Datenregister, die mit ioremap zugeordnet wurden. Der Arbeitscode sieht folgendermaßen aus:
//Driver initialization:
static char* dout0;
static char* din0;
...
static int driver_probe(struct platform_device *pdev)
{
struct pt_regs regs;
...
dout0 = ioremap(HW_PINCTRL_DOUT0, 0xffff);
din0 = ioremap(HW_PINCTRL_DIN0, 0xffff);
...
regs.ARM_r8 = (long) dout0;
regs.ARM_r9 = (long) din0;
set_fiq_regs(®s);
...
//In the FIQ handler:
LDR r12, [r8]
ORR r12, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8]
Der obige Code verhält sich wie erwartetpin 5
wird hoch gesetzt, nachdem der FIQ-Handler ausgeführt wurde.
Für eine kompliziertere Operation möchte ich eine Struktur vorbereiten, die Datenzeiger und andere verarbeitungsbezogene Daten enthält, einschließlich weiterer Zuordnungen zu verschiedenen Registern - und diese an den FIQ-Handler übergeben. Aber da läuft schon etwas schief, wenn der obige Code auf diesen migriert wird.
Ich habe den obigen Code so geändert, dass er so aussieht
//In Driver:
struct fiq_processing {
char* din0;
char* dout0;
};
static fiq_processing * pdata; //Pointer to our processing data structure
...
static int driver_probe(struct platform_device *pdev)
{
struct pt_regs regs;
pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); //Allocate memory for struct
printk("Size of the data struct %d \n", sizeof(*pdata)); //I get "8" as the size
...
pdata->din0 = ioremap(HW_PINCTRL_DIN0, 0xffff);
pdata->dout0 = ioremap(HW_PINCTRL_DOUT0, 0xffff);
...
regs.ARM_r8 = (long) pdata;
set_fiq_regs(®s);
...
//In the FIQ handler:
#define OFFSET_DIN0 0x0
#define OFFSET_DOUT0 0x4 //We know size is 8, so offset for dout is half from that
...
LDR r12, [r8, #OFFSET_DOUT0]
ORR r12, r12, #0x20 /* set pin 5 high in dout0 register */
STR r12, [r8, #OFFSET_DOUT0] /* This will do nothing ? */
Nachdem ich den Speicher für die Struktur zugewiesen und die Registerzeiger zugeordnet habe, übergebe ich die Adresse für die pdata-Struktur an den FIQ-Handler. Im FIQ-Handler habe ich Offsets fürdin0
unddout0
, was ich gedacht habe0x0
und0x4
jeweils (von der Strukturgröße von 8 abgezogen).
Aber aus irgendeinem Grund kann mein FIQ den Ausgangspin nicht mehr hoch setzen - ich kann nicht herausfinden, was ich hier falsch mache. Berechne ich den Offset dort falsch? ODER ist der AnrufSTR r12, [r8, #OFFSET_DOUT0]
falsch ? Die tatsächliche FIQ ist etwas länger (sie liest den Eingabezustand und die Eingabe daraus schafft einige Bedingungen), aber selbst das Setzen eines Basisbits scheint jetzt fehlzuschlagen.