Forum Discussion
Issues using IOWR for SPI communications
I am having difficulty using the IOWR and IORD functions in NIOS II.
We have a ENUM like below:
#define BASE 0x80
typedef enum SPI_REGISTERS_tag
{
READ_REG_5_E = 0x00,
WRITE_REG_0_E = 0x01,
SPI_STATUS_WORD = 0x02,
SPI_CONTROL_WORD = 0x03
} SPI_REGISTERS;
For SPI communication to send data we need to write 0x80 at I/O address 0x8C
When we use the below statement it works fine:
*(U32*)0x8C = 0x80;
But with below code the objective is not met:
IOWR(BASE, SPI_CONTROL_WORD, 0x80);
Which translates to below code:
__builtin_stwio (((void *)(((alt_u8*)(0x80)) + (((SPI_CONTROL_WORD)) * (32/8)))), (0x80));
When I read back the value written using above statement for address 8C I get value 0x10?
We tried to use IOWR32_DRIECT() but still the same issue. We verified the assembly instruction and they differend in stw / stwio instruction note that we are using data cache:
*(U32*)0x8C = 0x80;
00C02304 movi r3,0x8C ; r3,140
00802004 movi r2,0x80 ; r2,128
18800015 stw r2,0x0(r3) ; r2,0(r3)
IOWR(BASE, SPI_CONTROL_WORD, 0x80);
18800035 stwio r2,0x0(r3) ; r2,0(r3)
I also tried making the CACHE size to 0 but no success.
What wrong am I doing and fix required to achieve the objective?
Hi,
As we do not receive any response from you on the previous question/reply/answer that we have provided. Please login to ‘https://supporttickets.intel.com’, view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions.
p/s: If any answer from the community or Intel Support are helpful, please feel free to give best answer or rate 4/5 survey.
Thank you.
Regards,
Kelly Jialin, GOH
12 Replies
- PrakashPrasad
New Contributor
I have updated - it seems that the CACHE is not getting updated. But another unfortunate findings was that the functions to update cache (alt_dcache_flush_all()) are excluded from our library - so I cannot use them. I tried the below code and it worked:
/*
* Assume new instruction in r4 and
* instruction address already in r5.
*/
stw r4, 0(r5)
flushd 0(r5)
flushi r5
flushpHence in below C code I implemented below assembly instruction code to achieve it:
.... C code ....
__asm__ ("movi r3,0x80");
__asm__ ("movi r2,0x8c");
__asm__ ("stw r3,0x0(r2)");
__asm__ volatile("flushd 0x0(r2)");.... C code ....
The above code worked though should I be using below code:
__asm__ ("movi r3,0x80");
__asm__ ("movi r2,0x8c");
__asm__ ("stw r3,0x0(r2)");
__asm__ ("flushd 0x0(r2)");
__asm__ ("flushi r2");
__asm__("flushp");My question now is can we directly use r2 and r3 registers as above. Which of the above two code sections I can use? Should we not get the value of them and restore back after the flushd assembly instruction - if so please let me know how in a C program I can achieve this?
Also should we always make use r2 and r3 register? Can we use any register as used above?
What would be the best code to implement in C code otherwise?