-1

I have googled how SPI in C could be implemented and found a tutorial, where there is the following line:

#define SpiPs_RecvByte(BaseAddress) (u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET)

I am a beginner and have no idea what this line does. Could someone explain in detail?

1 Answers1

2

The #define is a preprocessor directive, which allows a programmer to write something that looks like a function call but isn’t - in this case it keeps the code readable and concise. In this case BaseAddress must be the address of the memory-mapped SPI controller. When the directive is invoked, it reads the RXD register of the SPI controller; this assumes that an SPI transaction has already been carried out and a received octet (byte) is available to read.

In practice a programmer would write something of the form rxc = SpiPs_RecvByte(SPI_ADDR); That’s a start, do you need clarification of any of those points?

Frog
  • 6,686
  • 1
  • 8
  • 12
  • Dear Frof´g, thank you for taking your time to reply. Could you please explain the second part ˋ(u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET)ˋ? XSPIPS_RXD_OFFSET, I have found in Zynq reference manual, it is a register name to receive a data. What is ˋXSpiPs_In32ˋ? Is it a function? – Noel Miller Jul 29 '21 at 09:22
  • It’s not obvious what it is, could be a function or could be another #define. Either way, what it appears to do is to add the address of the memory-mapped SPI controller to the offset of the data Rex register within the controller, and read from that register. The value is converted to a u8 (8-bit unsigned). For example, if the SPI controller were mapped at 0x1000 and the existing register were at offset 0x3 within the controller then this would read from 0x1003 and return the least significant 8 bits. – Frog Jul 29 '21 at 10:37
  • Could you please explain in the details the second part ˋ(u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET)ˋ? – Noel Miller Jul 29 '21 at 12:08
  • @Noel Miller, digging through some header files I found this: #define XSpiPs_In32 Xil_In32 So it seems that Xil_In32 is a function or #define that reads a 32-bit value from an address in memory. The parameter is the address to read, in this case (BaseAddress) + XSPIPS_RXD_OFFSET. Evidently the SPI transfer is 8-bit and so the 32-bit value is cast to an 8-bit value simply by discarding all but the 8 least significant bits. – Frog Jul 29 '21 at 22:19
  • In the old days, embedded systems programmers would never venture far from the bare metal, but currently it's fairly typical to see a hardware abstraction layer, so the programmer doesn't need to worry about the implementation of a peripheral (in this case a SPI interface) but can write code that's portable across different systems. Hopefully the compiler optimises this all out and doesn't actually carry out layers of function calls, so there's no loss of performance or bloat of the code size. – Frog Jul 29 '21 at 22:23
  • Is it possible to rewrite the expression ( in the question) in other way? – Noel Miller Jul 30 '21 at 05:45
  • You’ll want to start with a pointer, like u32* pRegister = BaseAddress + XSPIPS_RXD_OFFSET; then dereference the pointer, in other words read what’s at the address in RAM using something like result = (u8) *pRegister; I’d try to format that better but I’m away from my desk and on my phone today. – Frog Jul 31 '21 at 01:35