Open KasperJSdeVries opened 2 years ago
Thanks for your submission. Questions:
- Is the board natively supporting I2C?
- Is the same board working for example with any other technology? Including on a Raspberry Pi with .NET IoT for example (https://github.com/dotnet/iot/)
- And of course: are you sure about the way you plug the board on the STM chip?
I'm sure it natively supports I2C as it is a custom board with a working led driver over I2C. It works with the Lp3943. Because it is a custom board im sure it is connected correctly (it's been through multiple review processes).
Because it is a custom board im sure it is connected correctly
Do you have a link on the datasheet of your custom board? I can try to help understanding the pin out. It's quite sensitive, I've been there in the past!
Do you have a link on the datasheet of your custom board? I can try to help understanding the pin out. It's quite sensitive, I've been there in the past!
I cannot do that. However I am quite sure it is correct as it is basically a copy-paste of the development board.
I cannot do that. However I am quite sure it is correct as it is basically a copy-paste of the development board.
Then it's quite hard to help you more than what I already wrote :-( Sorry about that. The PN532 works for me on nano (at least last time I checked few months ago)
Then it's quite hard to help you more than what I already wrote :-( Sorry about that. The PN532 works for me on nano (at least last time I checked few months ago)
Did it work over I2C then or did you use another bus type?
Did it work over I2C then or did you use another bus type?
Works like a charm with all interfaces. I tested it few times in the past. It's one of the only NFC reader that I have with all accessible interfaces.
I tried writing a small program in both C and with nF that reads the version info to give better insight into my issue.
The Program I used:
// Includes
#include <stdbool.h>
#include <stdio.h>
#include <memory.h>
#include "PN532.h"
// Definitions and typedefs
#define PN532_I2C_ADDRESS ((uint16_t)0x48)
// File scope variables
static I2C_HandleTypeDef *_I2C_Bus_Handle;
static GPIO_TypeDef *_Reset_GPIO_Handle;
static uint16_t _IRQ_Pin;
static uint16_t _Reset_Pin;
static uint8_t _Read_Firmware_Version_Command[] = { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a,
0x00 };
static uint8_t _Ack_Frame[] = { 0x01, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
// Global functions
void PN532_init(I2C_HandleTypeDef *I2C_Bus_Handle, uint16_t IRQ_Pin,
GPIO_TypeDef *Reset_GPIO_Handle, uint16_t Reset_Pin)
{
_I2C_Bus_Handle = I2C_Bus_Handle;
_Reset_GPIO_Handle = Reset_GPIO_Handle;
_IRQ_Pin = IRQ_Pin;
_Reset_Pin = Reset_Pin;
HAL_StatusTypeDef ret;
HAL_GPIO_WritePin(_Reset_GPIO_Handle, Reset_Pin, GPIO_PIN_SET);
ret = HAL_I2C_Master_Transmit(_I2C_Bus_Handle,
PN532_I2C_ADDRESS,
_Read_Firmware_Version_Command,
sizeof(_Read_Firmware_Version_Command),
HAL_MAX_DELAY);
if(ret != HAL_OK)
{
goto error;
}
bool done = false;
uint8_t ack_response[sizeof(_Ack_Frame)];
while(!done)
{
HAL_I2C_Master_Receive(_I2C_Bus_Handle,
PN532_I2C_ADDRESS,
ack_response, sizeof(ack_response),
HAL_MAX_DELAY);
if(ack_response[0] == 0x01)
{
done = true;
}
}
if(memcmp(_Ack_Frame, ack_response, sizeof(_Ack_Frame)) != 0)
{
goto error;
}
done = false;
uint8_t response[32];
while(!done)
{
HAL_I2C_Master_Receive(_I2C_Bus_Handle,
PN532_I2C_ADDRESS,
response,
sizeof(response),
HAL_MAX_DELAY);
if(response[0] == 0x01)
{
done = true;
}
}
return;
error: while(1)
{
HAL_Delay(100);
}
}
It uses the standard STM32 provided functions etc. with a project generated in cubeMX. It is called from the main loop with the required pin and i2c bus info.
Logic output of command frame: Logic output of ack frame: Logic output of response frame:
I used the following program:
using System;
using System.Device.Gpio;
using System.Device.I2c;
using System.Diagnostics;
using System.Threading;
namespace NFCTestApp
{
public class Program
{
public static void Main()
{
GpioController gpioController = new GpioController();
I2cDevice nfciI2CDevice = new I2cDevice(new I2cConnectionSettings(3, 0x24));
var ResetPin = gpioController.OpenPin(GetPinNumber('C', 12), PinMode.Output);
ResetPin.Write(PinValue.High);
var readFirmwareVersionCommand = new byte[] { 0x00, 0x00, 0xff, 0x02, 0xfe, 0xd4, 0x02, 0x2a, 0x00 };
var ackFrame = new byte[] { 0x01, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00 };
nfciI2CDevice.Write(readFirmwareVersionCommand);
var done = false;
var ackResponse = new byte[ackFrame.Length];
while (!done)
{
nfciI2CDevice.Read(ackResponse);
if (ackResponse[0] == 0x01)
done = true;
}
if (ackResponse != ackFrame)
{
throw new Exception();
}
done = false;
var response = new byte[32];
while (!done)
{
nfciI2CDevice.Read(response);
if (response[0] == 0x01)
done = true;
}
Debug.WriteLine($"{response}");
Thread.Sleep(Timeout.Infinite);
}
internal static int GetPinNumber(char port, byte pin)
{
if (port is < 'A' or > 'J' || pin > 15)
throw new ArgumentException("port has to be between 'A' and 'J', pin has to be in range [0,15]");
return port - 'A' << 4 | pin & 0x0F;
}
}
}
This resulted in the following logic analyzer outputs:
The Command frame: The Ack frame: The missing Response frame: at which point both lines are held low forever and the core locks up.
I hope this extra information helps in seeing where my issue lies.
On a quick look at your code above this line if (ackResponse != ackFrame)
will always fail because you're "comparing" if one array (object) is equal to another array (object). Being two different objects will always fail the comparison.
In C code your performing a memory comparison. Quite different.
It either doesnt reach the exception or it does work because the exception never gets hit.
@KasperJSdeVries, this is NOT going to work:
if (ackResponse != ackFrame)
{
throw new Exception();
}
Use something like: https://github.com/nanoframework/nanoFramework.TestFramework/blob/607a85316cbf92cdf4f5afe159196b1eae8b0355/source/TestFramework/TestExtensions.cs#L22
You can of course simplify to only compare byte but you'll have to browse individually each element of the array
@josesimoes @Ellerbach That comparison is not where the issue lies the I2C bus gets pulled low and the mcu locks up before we ever get to that comparison.
@josesimoes @Ellerbach That comparison is not where the issue lies the I2C bus gets pulled low and the mcu locks up before we ever get to that comparison.
Checkout out https://github.com/nanoframework/Home/issues/1113#issuecomment-1227306017 and how to properly wake up the sensor. Note from this implementation: the _i2cDevice.Read will not raised an exception in nanoFramework because we are providing the result of the transaction (see right after here)
Note: you can get with nanoFramework the status of the I2C operation:
var res = nfciI2CDevice.Read(response);
You'll get information on how the transaction went. That may help you.
@Ellerbach I removed the comparison and it worked then, however there is an issue with the I2C device when an exception is thrown. This is an issue seemingly unrelated to the Pn532. The Issue being the core locking up when an exception is thrown while an I2C bus is in use.
and also: why does my bit of code work but the Iot.Device driver doesn't.
I removed the comparison and it worked then,
Good news :-)
however there is an issue with the I2C device when an exception is thrown
it is most likely related to how you are managing the life of this I2cDevice, in your code use a using for example or go in a try/catch loop and dispose it properly. I would vote for something like this.
why does my bit of code work but the Iot.Device driver doesn't.
You have all the sources! So you can debug and check. It maybe related to a tiny something in there!
What I found when investigating the Pn532 driver code was that the read at: https://github.com/nanoframework/nanoFramework.IoT.Device/blob/0d1d97db4da3e306349724d369fd477fa4701055/devices/Pn532/Pn532.cs#L2067-L2070 keeps the clock low as shown: Why this happens I do not know, however when issueing another read in code the clock gets reset; but the clock gets kept low again at the end of the second read command.
Library/API/IoT binding
Pn532
Visual Studio version
No response
.NET nanoFramework extension version
No response
Target name(s)
STM
Firmware version
No response
Device capabilities
No response
Description
When using the Pn532 IoT library over I2C you get an exception: "Can't find a PN532". Looking at the I2C signal with a signal analyzer shows weird I2C behaviour. I have no idea what could be causing this.
How to reproduce
No response
Expected behaviour
No response
Screenshots
No response
Sample project or code
No response
Aditional information
No response