Part Number: AM4376
Other Parts Discussed in Thread: ASH, AM4372
I'm porting a kernel module developed with AM437X SDK 2.00 Linux 4.1.6 that, among other things, simply blinks a LED attached to gpio5 pin 0 every second using a kernel timer. It has worked fine for 5 years and uses what I think is the standard kernel I/O memory access scheme: ioremap to get the gpio5 clear and set data registers virtual addresses and iowrite32 to write 1 in those registers to change the state of the gpio pin. When I print the registers' addresses, I get 0xFA322190 and 0xFA322194 which look reasonable for hardware addresses 0x48322190 and 0x48322194.
When I built this module with SDK 7.03 Linux 5.4, I only changed the timer initialization from the old style init_timer to the new style timer_setup. All the remaining code is identical and with printk's in the timer function, I can see that the timer is working fine with both SDK 2.00 and SDK 7.03 and being called every second as expected. I also see the same virtual addresses for the gpio5 registers with both SDKs. Further, I can successfully blink the LED in a "for" loop in the module initialization function with either SDK.
BUT…when the timer fires with SDK 7.03 the LED does not change states and I get the error:
44000000.ocp:L3 Custom Error: MASTER M2 (64-bit) TARGET L4_PER_0 (Idle): Data Access in Supervisor mode during Functional access
The timer function is:
static void HeartbeatFunc(struct timer_list *arg)
{
static int LedState=0;
if(LedState)
{
printk(KERN_INFO "HeartbeatLed off GPIO5SetDataOutVA=0x%x",GPIO5SetDataOutVA);
iowrite32(1,GPIO5SetDataOutVA);
}else{
printk(KERN_INFO "HeartbeatLed off GPIO5ClrDataOutVA=0x%x",GPIO5ClrDataOutVA);
iowrite32(1,GPIO5ClrDataOutVA);
}
LedState ^= 1;
If(arg != NULL) mod_timer(&MyTimerList, jiffies + HZ);
}
The module initialization function is (greatly abbreviated)
#define GPIO5_BASE 0x48322000
#define GPIO_CLRDATAOUT_OFFSET 0x190
#define GPIO_SETDATAOUT_OFFSET 0x194
static int __init MyDriver_init(void)
{
int Result;
GPIO5BaseVA = ioremap(GPIO5_BASE, 1024);
if(GPIO5BaseVA == NULL)
{
printj(__FILE__,__LINE__,"Can't map gpio5 io memory in driver %s\n",Driver_Name);
}else{
printk(KERN_INFO "Mapped gpio5 base to 0x%x\n",GPIO5BaseVA);
// calculate the addresses of the gpio5 data control registers for later use
GPIO5ClrDataOutVA= (void __iomem *)((unsigned int)GPIO5BaseVA+(GPIO_CLRDATAOUT_OFFSET));
GPIO5SetDataOutVA= (void __iomem *)((unsigned int)GPIO5BaseVA+(GPIO_SETDATAOUT_OFFSET));
printk(KERN_INFO "Mapped gpio5 GPIO5ClrDataOutVA to 0x%x",GPIO5ClrDataOutVA);
printk(KERN_INFO "Mapped gpio5 GPIO5SetDataOutVA to 0x%x",GPIO5SetDataOutVA);
// toggle the led to show it's working
printk(KERN_INFO "Test Heartbeat Start\n");
for(i=0;i<10;++i)
{
HeartbeatFunc(NULL);
msleep(500);
}
printk(KERN_INFO "Test Heartbeat Done\n");
timer_setup(&MyTimerList,HeartbeatFunc,0);
mod_timer(&MyTimerList, jiffies + HZ);
}
return Result;
}
Any thoughts on why this error occurs and how to fix it?