0

I'm trying to write code for a SPI slave device that reads data from the MISO line.

Here is the register map for the SPI device.

enter image description here

Basically my code looks at the status register and checks two conditions.

  1. Is the RRDY bit set? (which indicates that there is data in the RX register)

  2. Is the ROE bit not set? (which indicates that recieve over-run error has not occured)

If these conditions are met then I put the recieved char into the array buf.

I am sending the device the characters 'A', 'B' and 'C'.

When I recieved 'C' I break the loop and then print out the contents of `buf'.

My question is, buf only contains 'C', '0', '0'.

Is there something wrong with my logic?

char ibuf[32];
int chr;
int ptr;

while(1) { //keep checking

  //if RRDY set and ROE is not 1
   if (((*spi_status_reg >> 7) & 1) && (!(*spi_status_reg >> 3) & 1)) {

    //macro to read char from the rx register 
    chr = IORD_ALTERA_AVALON_SPI_RXDATA(SPI_1_SLAVE_BASE); 
    ibuf[ptr] = chr; // store it
    ptr ++;

    //if 'C' then exit
    if(chr == 'C') {
      printf("Got C\r\n");
      break;
    }
  }
}

printf("Exit\r\n");

for (int i= 0; i<3; i++) {
  printf("Buffer %x\r\n", ibuf[i]);
}
dut tom
  • 3
  • 4
  • You fill `buf` but then print `ibuf` – Toby Apr 14 '17 at 12:52
  • Also, is ptr set to `0` before the while? – Toby Apr 14 '17 at 12:52
  • @Toby Yes - `ptr` is 0, buf was a posting mistake, fixed now and updated the if statement to be more readable. Thanks – dut tom Apr 14 '17 at 12:58
  • You should step through the code with a debugger and check the values in the variables are as expected, use of a debugger is a basic skill requirement for programming. – Toby Apr 14 '17 at 13:35
  • Also you might want to make explicit the brackets on the second condition: `(!((*spi_status_reg >> 3) & 1))` – Toby Apr 14 '17 at 13:38
  • @Toby I'm a little confused does `(!((*spi_status_reg >> 3) & 1))` check that the `ROE` bit is not set? – dut tom Apr 14 '17 at 14:55
  • Exactly. This is not the same as what you currently have as the `!` operator should apply to the Boolean result of the `&` operation instead of applying only to the integer result of the `>>` operation (BTW, this shows the difference between `!` and `~`, see http://stackoverflow.com/questions/21056180/c-not-operator-applied-to-int) – Toby Apr 14 '17 at 15:01

1 Answers1

0

You have applied the Boolean not operator (!) incorrectly in the second condition in your if.

Instead of doing !BooleanValue you are doing !IntegerValue which will be True any time that (*spi_status_reg >> 3) is any non-zero value.

Try !((*spi_status_reg >> 3) & 1) instead.

(Or possibly ~(*spi_status_reg >> 3) & 1, but this is less readable)

See C not operator applied to int? and http://en.cppreference.com/w/c/language/operator_precedence. The latter shows that ! has a greater precedence than &, this is why the explicit brackets are required.

FYI: Shifting the 1 is better than shifting the register value because then the compiler can optimize the value, (probably saving it as a constant; e.g. for (*spi_status_reg & (1 << 7)) the compiler will probably replace (1 << 7) with the constant 128 at compile time)

Community
  • 1
  • 1
Toby
  • 9,696
  • 16
  • 68
  • 132