Reading PIT registers with C code

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Reading PIT registers with C code

ソリューションへジャンプ
2,630件の閲覧回数
michaelworster
Contributor IV

I'm trying to read one of the PIT (Perioditic Interrupt Timers) registers. For now, I don't really care which one I just want to run a test read from a Linux module. I've tried two methods:

    unsigned int PIT_MCR = 0;

    //Attempt one:

    //PIT_MCR = *((unsigned int *)(void *)(0x40037000));

    //Attempt two:

    PIT_MCR = __raw_readl(0x40037000);

    printk("PIT_MCR(0x4003_7000): %u\n", PIT_MCR);

Both of these attempts to access the register fail in the same way. An "Oops" message stating the memory can't be reached:

"Unable to handle kernel paging request at virtual address 40037000"

Is there anything special that has to be done in order to access/read from these registers?

ラベル(3)
0 件の賞賛
返信
1 解決策
1,877件の閲覧回数
timesyssupport
Senior Contributor II

Hi Mike,

Please see inline my responses below:

>>When I look at the memory map, that's not accessible:
>>/usr # cat /proc/iomem
>>00001000-00001000 : offset_jr0
>>
>>40034000-400341ff : fsl-usb2-udc
>><-- Should have been here
>>40038000-40038fff : mxc_pwm.1

The information in /proc/iomem comes from the kernel driver mapping the I/O memory using ioremap. The PIT register is not visible in /proc/iomem for this reason.

>>And when I try to check out what value is in this region of memory:

>>unsigned int PIT_MCR = 0;

>>PIT_MCR = *((unsigned int *)(void *)(0x40037000));

>>printk("In the HW init\nPIT_MCR(0x4003_7000): %u\n", PIT_MCR);

>>the result is an Oops: Unable to handle kernel paging request at virtual address 40037000

>>pgd = 863c0000

>>[40037000] *pgd=00000000

>>Internal error: Oops: 5 [#1]

>>Which is not too surprising because it's not in the memory map. I'd like to ask what is different and what you had to do in order to 

>>access/manipulate the memory in the PIT registers.

In order to access the registers, the driver / kernel module needs to map the physical memory to virtual memory using ioremap. Alternatively it can also be done using the MVF_IO_ADDRESS macro for Vybrid which returns the virtual memory address for a given physical address.

<Examples>

void __iomem *pit_mcr_register_base;

pit_mcr_register_base = MVF_IO_ADDRESS(0x40037000)

pit_mcr_register_val = readl(pit_mcr_register_base);

or

pit_mcr_register = (uint32_t *) ioremap(0x40037000, <size>)

pit_mcr_register_val = readl(pit_mcr_register);

Thanks,

Linux Engineer

Timesys Support

元の投稿で解決策を見る

0 件の賞賛
返信
3 返答(返信)
1,877件の閲覧回数
michaelworster
Contributor IV

I found one example which shows that the proper Clock Gating register must be enabled prior to accessing the PIT registers.

 

set_ccgr_register(PIT_CCGR_INDEX, CLK_ON_ALL_MODES); // PIT_CCGR_INDEX = 23 CLK_ON_ALL_MODES = 0x2

 

The gist of this function is that the CCM CCRG1 (0x4006B044) needs to be up dated to access the PIT module, however the issue is that this CCM CCRG1 register itself is not accessible and any attempt to access it results in the same type of Oops kernel paging fault.

I'm not sure if there's an additional step to access the CCM registers, or, more likely, there's a problem with the manner in which I'm attempting to access registers in general from a kernel module.

0 件の賞賛
返信
1,878件の閲覧回数
timesyssupport
Senior Contributor II

Hi Mike,

Please see inline my responses below:

>>When I look at the memory map, that's not accessible:
>>/usr # cat /proc/iomem
>>00001000-00001000 : offset_jr0
>>
>>40034000-400341ff : fsl-usb2-udc
>><-- Should have been here
>>40038000-40038fff : mxc_pwm.1

The information in /proc/iomem comes from the kernel driver mapping the I/O memory using ioremap. The PIT register is not visible in /proc/iomem for this reason.

>>And when I try to check out what value is in this region of memory:

>>unsigned int PIT_MCR = 0;

>>PIT_MCR = *((unsigned int *)(void *)(0x40037000));

>>printk("In the HW init\nPIT_MCR(0x4003_7000): %u\n", PIT_MCR);

>>the result is an Oops: Unable to handle kernel paging request at virtual address 40037000

>>pgd = 863c0000

>>[40037000] *pgd=00000000

>>Internal error: Oops: 5 [#1]

>>Which is not too surprising because it's not in the memory map. I'd like to ask what is different and what you had to do in order to 

>>access/manipulate the memory in the PIT registers.

In order to access the registers, the driver / kernel module needs to map the physical memory to virtual memory using ioremap. Alternatively it can also be done using the MVF_IO_ADDRESS macro for Vybrid which returns the virtual memory address for a given physical address.

<Examples>

void __iomem *pit_mcr_register_base;

pit_mcr_register_base = MVF_IO_ADDRESS(0x40037000)

pit_mcr_register_val = readl(pit_mcr_register_base);

or

pit_mcr_register = (uint32_t *) ioremap(0x40037000, <size>)

pit_mcr_register_val = readl(pit_mcr_register);

Thanks,

Linux Engineer

Timesys Support

0 件の賞賛
返信
1,877件の閲覧回数
karina_valencia
NXP Apps Support
NXP Apps Support

timesyssupport can you help on this case?

0 件の賞賛
返信