Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12589 Discussions

Nios II - Data cache problem

Altera_Forum
Honored Contributor II
3,261 Views

Hi all, 

 

I'm using a Cyclone III DSP Kit (DK-DSP-3C120N) and uClinux. Some days ago I realized a working design which includes a Nios II processor characterized by only an instruction cache. Within the system there's an IP that communicates with the CPU using a PIO peripheral. I wrote a Linux driver for this IP. All seems to work, but if I add also a data cache, Nios II and the IP stop to communicate, it seems that data do not leave the PIO. Can anyone tell me why?  

 

Thanks in advance 

 

Marco
0 Kudos
21 Replies
Altera_Forum
Honored Contributor II
1,622 Views

You'll need to do something to either flush the data from the cache, or to do uncached accesses. 

uClinux ought to have functions to map the memeory uncached. 

 

You also need to ensure that you NEVER access any physical address in the same cache line via cachable accesses. The cache line read/write will have unwanted effects. 

For a hardware device this is unlikely, but can be a problem is you want a block of memory (eg for dma).
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Yep, do the cache flushing.

0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Hi again, 

 

after some weeks I got back on the issue and as you suggested I used fflush(fd) to force data flush, but nothing changed. I have to use data cache so I'd like to resolve this issue. Is it enough to add fflush(fd) after every write or do I need to do something else? 

 

Thanks in advance 

 

 

Marco
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Wrong function. I don't remember how it is called, but I am sure this isn't the right one. 

 

Edit: 

here it is: alt_dcache_flush_all();
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Thanks Socrates, but can I use it with uClinux? I remember that I read something similar in the past but it was for HAL. Am I wrong?

0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

 

--- Quote Start ---  

Wrong function. I don't remember how it is called, but I am sure this isn't the right one. 

 

Edit: 

here it is: alt_dcache_flush_all(); 

--- Quote End ---  

 

That's for HAL, that function is not available in Linux. 

 

fflush if for a *file* not for memory. 

 

Are you doing this in the kernel (like a device driver) or in user space?
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Oh I've forgot You're using ucLinux... I'd offer You to write a message to mailing list of Nios. Check alterawiki.com for that.

0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Thanks for your answer ykozlov. I'm doing it in user space. You're right, I noticed that fflush is for file. Is sync() correct? I tried it but software crashes... 

 

@Socrates 

Thanks for the advice, I'll try.
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

sync() would be a unix system call to write all the disk buffer cache to disk. 

If you are running in user mode, how are you mapping the required physical addresses into (process) virtual ones? That is usually only allowed in a device driver. That mapping operation should have an option to enable/disable the cache - put you may not have the desired control over it (even in the kernel). 

To flush the data cache you need to execute the flushd or flushda instruction, you might need initda (initd is supervisor/kernel only). Not sure what is in which .h file for these...
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Hi dsl, 

 

I wrote a char driver to manage communications with my peripheral. I've followed your previous advice, but with no success, I can't find flushda instruction. I found in linux/include/asm-nios2/cacheflush.h some functions and I tried to use flush_cache_all() within my driver at the end of the write function but it blocks when my user program calls write() for the first time.
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Your driver is probably using ioremap_nocache() to map in the device registers - in which case the address you are given will be uncached and you won't need to do explicit cache flushing. 

Which might mean your original problem is elsewhere.
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

The problem is due to data cache in Nios II processor because without it my software works :) 

 

I don't use ioremap_nocache. May I change something in my driver if I move from a processor with no data cache to a processor with data cache?
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Are You sure that cache flush is reachable from user space?

0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

The data cache flush needs to be done with the same virtual address as the memory access itself - which means you'll need to do it from within the driver. 

 

The gcc 'asm' statement for the 'flushda' instruction is quite simple, you might find one if you search through all the header files. 

 

If your driver isn't using ioremap_nocache() to get a kernel virtual address for the phyiscal address, what is it using? 

I am presuming you are using the MMU - I can't remember if that requires the data cache. 

If you aren't using the MMU (so virtual and physical addresses match), setting the high address bit or using the defines that generate the 'io' forms of the memeory instructions would work.
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

 

--- Quote Start ---  

it seems that data do not leave the PIO. 

--- Quote End ---  

 

IIRC, the way to go is to define the MMU mapü in a way that the virtual address of the PIO is not cacheable.  

 

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

 

--- Quote Start ---  

The problem is due to data cache in Nios II processor because without it my software works :) 

 

I don't use ioremap_nocache. May I change something in my driver if I move from a processor with no data cache to a processor with data cache? 

--- Quote End ---  

 

 

You have to use ioremap_nocache to get a virtual address from your physical address. Then do all your access using that address. This will work with or without an MMU.
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

 

--- Quote Start ---  

The data cache flush needs to be done with the same virtual address as the memory access itself - which means you'll need to do it from within the driver. 

 

The gcc 'asm' statement for the 'flushda' instruction is quite simple, you might find one if you search through all the header files. 

 

If your driver isn't using ioremap_nocache() to get a kernel virtual address for the phyiscal address, what is it using? 

I am presuming you are using the MMU - I can't remember if that requires the data cache. 

If you aren't using the MMU (so virtual and physical addresses match), setting the high address bit or using the defines that generate the 'io' forms of the memeory instructions would work. 

--- Quote End ---  

 

 

I'm not using MMU, so I don't use ioremap. I tried to use cache_push_all(), but it didn't works. Can you explain me how can i set 31st bit or where can I find the defines you're talking about?
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

Setting the top bit is as simple as: 

ptr = (void *)((unsigned int)ptr) | 0x80000000); 

Although it is probably worth encapsulating it in a# define. 

 

I don't know where you are getting the address from. It might be from a numeric constant in a header file - in which case you can or in the top bit then. An alternative is to get the linker script to define the value of a symbol (instead of using the contents of a variable) - in which case it can just define the high value (useful for small systems when the IO addresses can be arranged to be accessible from %gp).
0 Kudos
Altera_Forum
Honored Contributor II
1,622 Views

in the no-MMU case, ioremap_nocache()should do exactkly this and thus provide for decently portable code.  

 

-Michael
0 Kudos
Altera_Forum
Honored Contributor II
1,346 Views

I tried to use ioremap_nocache()  

 

 

static int __init fpga_in_init(void) { # ifdef DEBUG_FUNCTION_NAME printk("\n%s\n",__FUNCTION__); # endif int i; dev_t devno; ioremap_nocache((unsigned long)PIO_FPGA_IN_BASE,PIO_FPGA_IN_SIZE); if (!(request_mem_region((unsigned long)PIO_FPGA_IN_BASE, PIO_FPGA_IN_SIZE, "pio_fpga_in"))) return -1; memset(&_fpga_in_dev,0,sizeof(_fpga_in_dev)); ....  

 

 

but it doesn't work...:(
0 Kudos
Reply