This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nrf_drv_twi_tx & rx with Adafruit PN532

I have the Adafruit PN532 Shield v1.3 mounted to an nRF52840 DK, trying to run the ble_nfc_pairing_reference_c example from SDK 17. With no modification to the example code, I was getting the following output.

  

After some debugging I found the error was returning from the nrf_drv_twi_tx function with these default arguments passed. 

To investigate, I flashed the twi_scanner example and successfully found the PN532 at address 0x24. 

Since this doesn't match the PN532_I2C_ADDRESS being passed in the nfc reference example, I changed (0x48 >> 1) to (0x24). This resulted in the following output. 

The only difference being that the tx function seemed to send data successfully, but the nrf_drv_twi_rx function that passes those same parameters was returning a wild error while trying to read the acknowledgement. 

Since I was getting two different error scenarios, I re-extracted a fresh SDK 17 and tried again, but the exact behavior occurred. Does anyone know what is going on here?

My theory is that either there is something wrong with the Adafruit hardware, or these parameters are not configured correctly, unless I'm missing something. 

Any help here would be much appreciated. 

Thanks in advance!

Sam

Parents
  • Hello Sam,

    The only difference being that the tx function seemed to send data successfully, but the nrf_drv_twi_rx function that passes those same parameters was returning a wild error while trying to read the acknowledgement. 

    Could you make sure to pass the returned error code to an APP_ERROR_CHECK, and make sure that you have DEBUG defined in your preprocessor defines - like shown in the included image?
      
    Enabling DEBUG in your preprocessor defines makes the APP_ERROR_CHECK write a detailed error message to the log, before the device is reset.
    Please do this, and post the entire debug message, so we may look into what's the root issue here.

    Do you have access to a logic analyzer by any chance?

    Looking forward to resolving this issue together!

    Best regards,
    Karl

  • Thank you Karl, apologies for taking a bit on the replay. I did as you instructed and got the following error check message. 

    I also ran the SCL, SDA, and IRQ pins through a logic analyzer and can see that the message was indeed sent as well as acknowledged it seems...?

    This seems to confirm an earlier suspicion I had that it may be the IRQ pin that is causing this issue, but your guess will definitely be better than mine, and I'm still not sure how I'd go about solving this. Let me know if there's other info you need, your help is much appreciated. 

    Thanks, 

    Sam

  • Could you check that the address you are trying to read in the rx command is exposed in the slave device?

    I'm not totally sure how I'd go about confirming whether the address is exposed? I've found that the twi_scanner example finds the device at 0x24, which makes sense given the address parameters in adafruitPN532.h .

    #define PN532_I2C_ADDRESS   (0x48 >> 1) ///< Address of the I2C peripheral of the Adafruit PN532 Shield.
    

    Does this answer this question as well? I'm not sure. 

    Could you check that the address you were trying to access here was in fact valid?

    As far as the IRQ pin, from the trace it seems to be staying high when, I was under the impression it needed to read a 0 for the firmware to pick up the acknowledgement. Honestly though that is just an estimated theory that I gathered from these functions that get called the init function. 

    I want to be clear that this was my best guess, I don't want to spin off in a wild goose chase. 

    Thanks again for your help, 

    Sam

  • Hello Sam,

    Sam_Rall said:
    I'm not totally sure how I'd go about confirming whether the address is exposed? I've found that the twi_scanner example finds the device at 0x24, which makes sense given the address parameters in adafruitPN532.h .

    The scanner finding it on address 0x24 indicates that the device acknowledged this address, when the master requested it - i.e the slave pulled down the SDA line at the ninth clock cycle, to acknowledge the centrals request ( as per the TWI protocol ).

    Sam_Rall said:
    Does this answer this question as well? I'm not sure. 

    Do you have the datasheet for the module you are using? I think most of our answers will lie there.
    Reading the datasheet to understand how the communication with the device is implemented is a lot easier than trying to parse it from the driver directly.
    The datasheet will detail how to go about controlling, configuring and communicating with the device over TWI.

    Sam_Rall said:
    As far as the IRQ pin, from the trace it seems to be staying high when, I was under the impression it needed to read a 0 for the firmware to pick up the acknowledgement. Honestly though that is just an estimated theory that I gathered from these functions that get called the init function. 

    This too will be detailed in the modules datasheet - what the IRQ is used for, and how it is used.
    From the code you have shared, I suspect that the IRQ is used to indicate that the slave is ready to transfer data, or receive commands.

    Please see if you can find the datasheet, and these two sections in particular. You may also post the datasheet here for me to take a look at it - but I highly recommend that you familiarize with it on your own first. Navigating the datasheet is essential to all microcontroller programming.

    Looking forward to resolving this together!

    Best regards,
    Karl

  • https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf

    Here is the data sheet for the PN532, I'll take today to look through the I2C documentation and configuration.

    However, if I'm following the instructions per the Nordic SDK documentation for this NFC ref example, it should really work without much tinkering if I'm not changing anything in the code... either that or your SDK documentation should be updated to say that this example doesn't work in all cases. Indeed, it does not seem like this pn532 library was written correctly if I can't simply compile and run this example with fresh hardware out of the box. Please, if you are able, look into replicating this example and see if you experience any similar issues. 

  • Hello again Sam,

    Sorry for my late reply.

    Sam_Rall said:
    Here is the data sheet for the PN532, I'll take today to look through the I2C documentation and configuration.

     Thank you. I just needed to confirm that we were on the same page here.

    Sam_Rall said:
    However, if I'm following the instructions per the Nordic SDK documentation for this NFC ref example, it should really work without much tinkering if I'm not changing anything in the code...

    Agreed, absolutely. I will reach out to the developers of this example to get their feedback on this. There should not be any need for modifications to get this up and running as per the documentations setup and testing section. I must however also emphesize that this particular example is still tagged as experimental, but it should of course work out-of-the-box regardless of this. After all, it has gone through rigorous testing before being added to the SDK release.

    Just to summarize; you are following the setup and testing documentation for the Experimental: BLE Pairing Using NFC - Central Reference Example from the nRF5 SDK v.17.0.2, and it seems that the IRQ of the PN532 never goes low again after the first transfer, indicating that the PN532 is not ready for the following rx transfer. As I understand it, this issue becomes apparent when the device is powering on - without needing any input (such as button presses) from you, correct?
    Could you check how many times the loop in adafruit_pn532_waitready_ms is executed, and confirm that it moves on from the loop as a result of the 'timeout'?

    Could you confirm for me which SoftDevice and version you have flashed your device with, prior to flashing the example?
    Could you also confirm that you have installed the micro-ecc library successfully?
    How did you program the device, using nRF Connect Programmer, or nrfjprog from the command line?

    Sam_Rall said:
    Please, if you are able, look into replicating this example and see if you experience any similar issues. 

    If there is no immediate note on this by the developers I will indeed try to replicate this on my end, and see if I can not get to the bottom of why it is unable to contact the board.

    Looking forward to resolving this together!

    Best regards,
    Karl

  • As I understand it, this issue becomes apparent when the device is powering on - without needing any input (such as button presses) from you, correct?

    That is correct, yes.

    Could you check how many times the loop in adafruit_pn532_waitready_ms is executed, and confirm that it moves on from the loop as a result of the 'timeout'?

    Looking at the waitready_ms function closer, it seems to get called each time with a 1000 (1 second) value passed to it, and indeed it does exit the loop having timed out of this value. 

    As you can see above, I've stopped the debugger after it exits the loop, RESULT is still false, and TIMER equals TIMEOUT of 1000. Note my debug message on line 893 and the corresponding output below which confirms this. 

    Could you confirm for me which SoftDevice and version you have flashed your device with, prior to flashing the example?

    I believe I had flashed s140 to this 840 DK a while ago before flashing this nfc example (as I need long range capability for our product application). Am I correct in assuming this is ok because s140 is backward compatible? Hopefully this wasn't my mistake?

    Could you also confirm that you have installed the micro-ecc library successfully?

     Yes I have followed the instructions for installing the micro-ecc library successfully per the SDK doc page you linked above. Also, the example won't compile without it?

    How did you program the device, using nRF Connect Programmer, or nrfjprog from the command line?

    Flashing directly to the device with Segger Embedded Studio and the JLink. Not sure what backend is needed for that off the top of my head but I know this computer has both. 

    Again, can't thank you enough for the assistance here!

    Let me know if there's more info you need. 

    Sam

Reply
  • As I understand it, this issue becomes apparent when the device is powering on - without needing any input (such as button presses) from you, correct?

    That is correct, yes.

    Could you check how many times the loop in adafruit_pn532_waitready_ms is executed, and confirm that it moves on from the loop as a result of the 'timeout'?

    Looking at the waitready_ms function closer, it seems to get called each time with a 1000 (1 second) value passed to it, and indeed it does exit the loop having timed out of this value. 

    As you can see above, I've stopped the debugger after it exits the loop, RESULT is still false, and TIMER equals TIMEOUT of 1000. Note my debug message on line 893 and the corresponding output below which confirms this. 

    Could you confirm for me which SoftDevice and version you have flashed your device with, prior to flashing the example?

    I believe I had flashed s140 to this 840 DK a while ago before flashing this nfc example (as I need long range capability for our product application). Am I correct in assuming this is ok because s140 is backward compatible? Hopefully this wasn't my mistake?

    Could you also confirm that you have installed the micro-ecc library successfully?

     Yes I have followed the instructions for installing the micro-ecc library successfully per the SDK doc page you linked above. Also, the example won't compile without it?

    How did you program the device, using nRF Connect Programmer, or nrfjprog from the command line?

    Flashing directly to the device with Segger Embedded Studio and the JLink. Not sure what backend is needed for that off the top of my head but I know this computer has both. 

    Again, can't thank you enough for the assistance here!

    Let me know if there's more info you need. 

    Sam

Children
  • Hello Sam,

    Sam_Rall said:
    Looking at the waitready_ms function closer, it seems to get called each time with a 1000 (1 second) value passed to it, and indeed it does exit the loop having timed out of this value. 

    Great, thank you for confirming this. This is in line with what was shown in the logic analyzer output you showed earlier - the PN532 never pulls the IRQ low again after the first transmission series, to indicate that it is ready again. This currently looks to be the point of failure for the example, so we should look into the possible reasons for why the PN532 would behave like this.

    Sam_Rall said:
    I believe I had flashed s140 to this 840 DK a while ago before flashing this nfc example (as I need long range capability for our product application). Am I correct in assuming this is ok because s140 is backward compatible? Hopefully this wasn't my mistake?

    I see, thank you for clarifying.
    Could I ask you to try this example again, with the S132, to see if there is any difference in the behavior then? The example's documentation notes this as the only SoftDevice that it is made for and tested with.
    It should well be possible to modify the example to work with the S140, but we will first need to rule out that this could be the source of the error. While initially it might seem unrelated to the high IRQ line, I would like to rule the SoftDevice out as a possibility before we proceed with other options.

    Sam_Rall said:
     Yes I have followed the instructions for installing the micro-ecc library successfully per the SDK doc page you linked above. Also, the example won't compile without it?

    Yes, I just wanted to make sure that everything had run smoothly up until the running application, thank you for letting me know.

    Sam_Rall said:
    Again, can't thank you enough for the assistance here!

    It is no problem at all, Sam, I am happy to help!

    Looking forward to getting to the bottom of this issue!

    Best regards,
    Karl

  • Could I ask you to try this example again, with the S132, to see if there is any difference in the behavior then? The example's documentation notes this as the only SoftDevice that it is made for and tested with.

    Yeah over the weekend I did give this some more time debugging and tinkering, and it's safe to safe to say the SoftDevice is not the issue here. I flashed s132 from a clean SDK 17 as well as the example and there was no change in behavior whatsoever. I will continue to keep the s132 on the DK until this gets resolved before adapting to the s140.

    I've also been pouring over the data sheet as well, searching for a reason the IRQ pin is not being set to 0 when it should be. I'm not sure where in the firmware these sections would apply, but could it be possible the I2C configuration is not setup for interrupt requests? I've attached some clips of the datasheet I feel are relevant here but honestly it's sort of a last ditch effort.

    Has there been any word from the developers of the adafruit_pn532 library? Is there any way I can retrieve  info from the I2C registers to see what might be happening when the NACK is received? Pages 58-63 of the datasheet contain I2C transmitter status codes with scenarios and descriptions, I'll keep working on it but again, a bit at the end of my rope on this. 

    Cheers,

    Sam

  • Hello Sam,

    Sam_Rall said:
    I'll keep working on it but again, a bit at the end of my rope on this. 

    I understand - it is indeed very frustrating when things does not work as expected, with no clear cut reasoning or fix.
    I am however confident that we together will be able to resolve this issue!

    Sam_Rall said:
    I flashed s132 from a clean SDK 17 as well as the example and there was no change in behavior whatsoever. I will continue to keep the s132 on the DK until this gets resolved before adapting to the s140.

    Great, I am happy to rule out this possibility as well.
    Lastly, could you walk me through what changes you made to migrate the example from the nRF52832 ( as it is provided, for the nRF52 DK ) to the nRF52840 that you are working with? I would like to rule out these changes as a potential issue as well.
    Based on the logical analyzer screenshot you shared earlier and the test using the twi_slave example ( which got an acknowledgement on an address ) we know that it is connected correctly.

    Sam_Rall said:
    I've also been pouring over the data sheet as well, searching for a reason the IRQ pin is not being set to 0 when it should be. I'm not sure where in the firmware these sections would apply, but could it be possible the I2C configuration is not setup for interrupt requests?

    If someone had developed this driver privately, then this would also have been my go-to suspicion, but since it is a credited driver with a seemingly glaring issue, I would not think that this would be the case. From the descriptions and images you have shared, it seems that the initial command - get firmware version - is sent and acknowledged successfully. It is the waiting for the response containing the firmware version that is timing out.
    So, we know that there is communication between the devices - it is just not flowing as expected.

    Sam_Rall said:
    Is there any way I can retrieve  info from the I2C registers to see what might be happening when the NACK is received?

    Just to check, could you try to comment out line 263 through 273 of the adafruit_pn532.c? This section only attempts to retrieve the firmware version of the PN532, to confirm that it is connected and responding as intended.
    Removing this section and running the example again will confirm that the issue is not limited to this particular command ( if it fails in a similar way when it gets to the sam_config function.
    If you could provide the logger output and/or logical traces for this test, that would be very helpful for me to have a look at.

    Looking forward to resolving this issue together!

    Best regards,
    Karl

  • Lastly, could you walk me through what changes you made to migrate the example from the nRF52832 ( as it is provided, for the nRF52 DK ) to the nRF52840 that you are working with? I would like to rule out these changes as a potential issue as well.

    In the beginning, I did think it was a pinning issue because the sdk_config has the PN532_IRQ set to pin 13, which didn't make sense to me at first. But after some tinkering with different pinning configs, it didn't seem to matter and was still getting errors.

    After that I simply stuck to erasing the DK completely and flashing s132 plus the ble_nfc_paring_reference_c example with the PCA10040 support (as this is the only support it ships with) from a fresh extracted SDK 17. I'm aware the 840 DK has the PCA10056 but again I thought I was ok on the backward compatibility. I've literally made no other changes apart from enabling DEBUG options and other changes per your instructions as I post results. 

    Just to check, could you try to comment out line 263 through 273 of the adafruit_pn532.c? This section only attempts to retrieve the firmware version of the PN532, to confirm that it is connected and responding as intended.

    Unfortunately it seems the SAM config command (or any command) indeed times out as well. 

    Although I did  notice the IRQ dropping a few hundred uS after the command is sent, but only on every OTHER system reset cycle. Every other cycle the IRQ still refuses to come down at all. 

    Not sure if this was helpful, not wanting a goose chase here but it seemed odd. 

    Cheers,

    Sam

  • UPDATE: Big breakthrough here. 

    Out of curiosity I flashed the adafruit_tag_reader example from SDK 17 and the PN532 communicates effectively with the 840. I can see the waitready_ms() function operate properly because the IRQ comes down about 225uS (the delta between my red cursors below) after a command is sent and the ACK is actually picked up.

     

    So the important discovery here is that the PCA10040 support for this example is where I was going wrong because the adafruit_tag_reader example will only function properly on my 840 DK with the PCA10056 supported example. When I flashed the adafruit_tag_rader example with the 10040 support, I got identical errors as we've been discussing. So I'm afraid I must take some responsibility in not knowing that this was actually more of a hardware selection issue. I wasn't aware the difference in board support could cause issues such as this, I've run plenty of Nordic SDK examples with different boards (for testing only, not production) and have had no major issues such as this. Big whoops on my part. 

    SO

    Taking a look at pca10056.h, I can see the pinouts are completely different for PN532_IRQ and PN532_RESET. However, whenever I try and incorporate the appropriate changes into the ble_nfc_pairing_reference_c by studying the differences in the board support, I still can't get the example to run properly on the 840. Instead of NRF_ERROR_INTERNAL I get crazy error values that output as "Unknown Error".

    So I'm still a little bit in need of some help. I will spend today researching how to migrate this board support, as there's still no PCA10056 support for ble_nfc_pairing_reference_c that I can find - unless you know where I could look? Hoping this example is still possible on the 840? My application MUST use the 840 silicon, I cannot drop down to the 832. 

    Eternally wishing I would have discovered this sooner,

    Cheers,

    Sam

Related