Dostęp do danych sterownika jądra z programu obsługi przerwań FIQ nie działa
W przerwaniach FIQ ARM mamy kilka rejestrów zarezerwowanych tylko do użytku FIQ, a są to przydatne sposoby „zapisywania stanu” na przykład przesyłania danych między połączeniami FIQ.
Obecnie wyzwalam niektóreGPIO
pinów z FIQ i działa zgodnie z oczekiwaniami. Podczas konfigurowania modułu obsługi FIQ przekazuję wskaźniki do rejestrów danych, które zostały zmapowane za pomocą ioremap. Kod roboczy wygląda tak:
//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]
Powyższy kod działa zgodnie z oczekiwaniamipin 5
jest ustawiony wysoko po wykonaniu procedury FIQ.
W przypadku bardziej skomplikowanych operacji chcę przygotować strukturę, która będzie przechowywać wskaźniki danych i inne dane związane z przetwarzaniem, w tym więcej mapowań do różnych rejestrów - i przekazać to do obsługi FIQ. Ale coś już nie tak się dzieje podczas migracji powyższego kodu do tego.
Zmodyfikowałem powyższy kod, aby wyglądał tak
//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 ? */
Po przydzieleniu pamięci dla struktury i zmapowaniu wskaźników rejestru przekazuję adres struktury pdata do modułu obsługi FIQ. W module obsługi FIQ mam offset dladin0
idout0
, o którym myślałem, że będzie0x0
i0x4
odpowiednio (odjęte od wielkości struktury 8).
Ale z jakiegoś powodu, teraz mój FIQ nie jest już w stanie ustawić wysokiego poziomu wyjścia - nie mogę zrozumieć, co robię źle tutaj. LUB to połączenieSTR r12, [r8, #OFFSET_DOUT0]
niepoprawny? Rzeczywisty FIQ jest nieco dłuższy (odczytuje stan wejściowy, a wejście z niego tworzy pewne warunki), ale nawet podstawowy zestaw bitów wydaje się teraz zawodzić.