Module RFID PN532 (I2C)

Schéma d’Ensemble

ensemble_pn532.svg


Documents

PN532 Datasheet

PN532 User Manual


Projet Démonstration

WORKSPACE_F411_RFID_PN532.zip

Driver RFID PN532

pn532.h

/*
 * pn532.h
 *
 *  Created on: Oct 3, 2017
 *      Author: kerhoas
 */

#ifndef INC_PN532_H_
#define INC_PN532_H_

#include "main.h"

#define PN532_PREAMBLE                      (0x00)
#define PN532_STARTCODE1                    (0x00)
#define PN532_STARTCODE2                    (0xFF)
#define PN532_POSTAMBLE                     (0x00)

#define PN532_HOSTTOPN532                   (0xD4)
#define PN532_PN532TOHOST                   (0xD5)

// PN532 Commands
#define PN532_COMMAND_DIAGNOSE              (0x00)
#define PN532_COMMAND_GETFIRMWAREVERSION    (0x02)
#define PN532_COMMAND_GETGENERALSTATUS      (0x04)
#define PN532_COMMAND_READREGISTER          (0x06)
#define PN532_COMMAND_WRITEREGISTER         (0x08)
#define PN532_COMMAND_READGPIO              (0x0C)
#define PN532_COMMAND_WRITEGPIO             (0x0E)
#define PN532_COMMAND_SETSERIALBAUDRATE     (0x10)
#define PN532_COMMAND_SETPARAMETERS         (0x12)
#define PN532_COMMAND_SAMCONFIGURATION      (0x14)
#define PN532_COMMAND_POWERDOWN             (0x16)
#define PN532_COMMAND_RFCONFIGURATION       (0x32)
#define PN532_COMMAND_RFREGULATIONTEST      (0x58)
#define PN532_COMMAND_INJUMPFORDEP          (0x56)
#define PN532_COMMAND_INJUMPFORPSL          (0x46)
#define PN532_COMMAND_INLISTPASSIVETARGET   (0x4A)
#define PN532_COMMAND_INATR                 (0x50)
#define PN532_COMMAND_INPSL                 (0x4E)
#define PN532_COMMAND_INDATAEXCHANGE        (0x40)
#define PN532_COMMAND_INCOMMUNICATETHRU     (0x42)
#define PN532_COMMAND_INDESELECT            (0x44)
#define PN532_COMMAND_INRELEASE             (0x52)
#define PN532_COMMAND_INSELECT              (0x54)
#define PN532_COMMAND_INAUTOPOLL            (0x60)
#define PN532_COMMAND_TGINITASTARGET        (0x8C)
#define PN532_COMMAND_TGSETGENERALBYTES     (0x92)
#define PN532_COMMAND_TGGETDATA             (0x86)
#define PN532_COMMAND_TGSETDATA             (0x8E)
#define PN532_COMMAND_TGSETMETADATA         (0x94)
#define PN532_COMMAND_TGGETINITIATORCOMMAND (0x88)
#define PN532_COMMAND_TGRESPONSETOINITIATOR (0x90)
#define PN532_COMMAND_TGGETTARGETSTATUS     (0x8A)

#define PN532_RESPONSE_INDATAEXCHANGE       (0x41)
#define PN532_RESPONSE_INLISTPASSIVETARGET  (0x4B)

#define PN532_WAKEUP                        (0x55)

#define PN532_SPI_STATREAD                  (0x02)
#define PN532_SPI_DATAWRITE                 (0x01)
#define PN532_SPI_DATAREAD                  (0x03)
#define PN532_SPI_READY                     (0x01)

#define PN532_I2C_ADDRESS                   (0x48)
#define PN532_I2C_READBIT                   (0x01)
#define PN532_I2C_BUSY                      (0x00)
#define PN532_I2C_READY                     (0x01)
#define PN532_I2C_READYTIMEOUT              (20)

#define PN532_MIFARE_ISO14443A              (0x00)

// Mifare Commands
#define MIFARE_CMD_AUTH_A                   (0x60)
#define MIFARE_CMD_AUTH_B                   (0x61)
#define MIFARE_CMD_READ                     (0x30)
#define MIFARE_CMD_WRITE                    (0xA0)
#define MIFARE_CMD_TRANSFER                 (0xB0)
#define MIFARE_CMD_DECREMENT                (0xC0)
#define MIFARE_CMD_INCREMENT                (0xC1)
#define MIFARE_CMD_STORE                    (0xC2)
#define MIFARE_ULTRALIGHT_CMD_WRITE         (0xA2)

// Prefixes for NDEF Records (to identify record type)
#define NDEF_URIPREFIX_NONE                 (0x00)
#define NDEF_URIPREFIX_HTTP_WWWDOT          (0x01)
#define NDEF_URIPREFIX_HTTPS_WWWDOT         (0x02)
#define NDEF_URIPREFIX_HTTP                 (0x03)
#define NDEF_URIPREFIX_HTTPS                (0x04)
#define NDEF_URIPREFIX_TEL                  (0x05)
#define NDEF_URIPREFIX_MAILTO               (0x06)
#define NDEF_URIPREFIX_FTP_ANONAT           (0x07)
#define NDEF_URIPREFIX_FTP_FTPDOT           (0x08)
#define NDEF_URIPREFIX_FTPS                 (0x09)
#define NDEF_URIPREFIX_SFTP                 (0x0A)
#define NDEF_URIPREFIX_SMB                  (0x0B)
#define NDEF_URIPREFIX_NFS                  (0x0C)
#define NDEF_URIPREFIX_FTP                  (0x0D)
#define NDEF_URIPREFIX_DAV                  (0x0E)
#define NDEF_URIPREFIX_NEWS                 (0x0F)
#define NDEF_URIPREFIX_TELNET               (0x10)
#define NDEF_URIPREFIX_IMAP                 (0x11)
#define NDEF_URIPREFIX_RTSP                 (0x12)
#define NDEF_URIPREFIX_URN                  (0x13)
#define NDEF_URIPREFIX_POP                  (0x14)
#define NDEF_URIPREFIX_SIP                  (0x15)
#define NDEF_URIPREFIX_SIPS                 (0x16)
#define NDEF_URIPREFIX_TFTP                 (0x17)
#define NDEF_URIPREFIX_BTSPP                (0x18)
#define NDEF_URIPREFIX_BTL2CAP              (0x19)
#define NDEF_URIPREFIX_BTGOEP               (0x1A)
#define NDEF_URIPREFIX_TCPOBEX              (0x1B)
#define NDEF_URIPREFIX_IRDAOBEX             (0x1C)
#define NDEF_URIPREFIX_FILE                 (0x1D)
#define NDEF_URIPREFIX_URN_EPC_ID           (0x1E)
#define NDEF_URIPREFIX_URN_EPC_TAG          (0x1F)
#define NDEF_URIPREFIX_URN_EPC_PAT          (0x20)
#define NDEF_URIPREFIX_URN_EPC_RAW          (0x21)
#define NDEF_URIPREFIX_URN_EPC              (0x22)
#define NDEF_URIPREFIX_URN_NFC              (0x23)

#define PN532_GPIO_VALIDATIONBIT            (0x80)
#define PN532_GPIO_P30                      (0)
#define PN532_GPIO_P31                      (1)
#define PN532_GPIO_P32                      (2)
#define PN532_GPIO_P33                      (3)
#define PN532_GPIO_P34                      (4)
#define PN532_GPIO_P35 (5)

//======================================================================

void pn532_reset();
uint8_t pn532_SAMConfig(void);
uint32_t pn532_getFirmwareVersion(void);
uint8_t pn532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength, uint16_t timeout);
uint8_t pn532_mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData);
uint8_t pn532_mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data);
uint8_t pn532_mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data);

#endif /* INC_PN532_H_ */

pn532.c

#include "pn532.h"


#define PN532_PACKBUFFSIZ 64

uint8_t pn532_packetbuffer[PN532_PACKBUFFSIZ];
uint8_t pn532ack[] = {0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00};
uint8_t pn532response_firmwarevers[] = {0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03};
uint8_t writeBuffer[60];



uint8_t _uid[7];       // ISO14443A uid
uint8_t _uidLen;       // uid len
uint8_t _key[6];       // Mifare Classic key
uint8_t _inListedTag;  // Tg number of inlisted tag.


uint8_t pn532_sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout);
uint8_t pn532_readack() ;
uint8_t pn532_waitready(uint16_t timeout) ;
void pn532_readdata(uint8_t* buff, uint8_t n);
void pn532_writecommand(uint8_t* cmd, uint8_t cmdlen);
uint8_t pn532_isready();

//===============================================================================================
void pn532_reset()
{
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);
	HAL_Delay(400);
	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);
	HAL_Delay(10);
}
//===============================================================================================
uint32_t pn532_getFirmwareVersion(void)
{
	  uint32_t response;

	  pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;

	  if (pn532_sendCommandCheckAck(pn532_packetbuffer, 1,1000)==0)
	  {
	    return 0;
	  }

	  // read data packet
	  pn532_readdata(pn532_packetbuffer, 12);

	  // check some basic stuff
	  if (0 != strncmp((char *)pn532_packetbuffer, (char *)pn532response_firmwarevers, 6))
	  {
	    return 0;
	  }

	  int offset = 7;  // Skip a response byte when using I2C to ignore extra data.
	  response = pn532_packetbuffer[offset++];
	  response <<= 8;
	  response |= pn532_packetbuffer[offset++];
	  response <<= 8;
	  response |= pn532_packetbuffer[offset++];
	  response <<= 8;
	  response |= pn532_packetbuffer[offset++];

	  return response;
}


//===============================================================================================
uint8_t pn532_SAMConfig(void)
{
  pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
  pn532_packetbuffer[1] = 0x01; // normal mode;
  pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
  pn532_packetbuffer[3] = 0x01; // use IRQ pin!

  if (pn532_sendCommandCheckAck(pn532_packetbuffer, 4, 1000) == 0)
    return 0;

  // read data packet
  pn532_readdata(pn532_packetbuffer, 8);

  int offset =  6;

  if (pn532_packetbuffer[offset] == 0x15)
  { return 1; }
  else
  {return 0;}

}

//===============================================================================================

uint8_t pn532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t * uid, uint8_t * uidLength, uint16_t timeout)
{
  pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
  pn532_packetbuffer[1] = 1;  // max 1 cards at once (we can set this to 2 later)
  pn532_packetbuffer[2] = cardbaudrate;

  if (pn532_sendCommandCheckAck(pn532_packetbuffer, 3, 1000)==0)
  {
    return 0x0;  // no cards read
  }
  // wait for a card to enter the field (only possible with I2C)
    if (!pn532_waitready(timeout)) {
      return 0x0;
    }

  pn532_readdata(pn532_packetbuffer, 20);
  // check some basic stuff
  /* ISO14443A card response should be in the following format:
    byte            Description
    -------------   ------------------------------------------
    b0..6           Frame header and preamble
    b7              Tags Found
    b8              Tag Number (only one used in this example)
    b9..10          SENS_RES
    b11             SEL_RES
    b12             NFCID Length
    b13..NFCIDLen   NFCID                                      */

  if (pn532_packetbuffer[7] != 1)
    return 0;

  uint16_t sens_res = pn532_packetbuffer[9];
  sens_res <<= 8;
  sens_res |= pn532_packetbuffer[10];

  /* Card appears to be Mifare Classic */
  *uidLength = pn532_packetbuffer[12];
  for (uint8_t i=0; i < pn532_packetbuffer[12]; i++)
  {
    uid[i] = pn532_packetbuffer[13+i];
  }

  return 1;
}


/**************************************************************************/
/*!
    Tries to authenticate a block of memory on a MIFARE card using the
    INDATAEXCHANGE command.  See section 7.3.8 of the PN532 User Manual
    for more information on sending MIFARE and other commands.

    @param  uid           Pointer to a byte array containing the card UID
    @param  uidLen        The length (in bytes) of the card's UID (Should
                          be 4 for MIFARE Classic)
    @param  blockNumber   The block number to authenticate.  (0..63 for
                          1KB cards, and 0..255 for 4KB cards).
    @param  keyNumber     Which key type to use during authentication
                          (0 = MIFARE_CMD_AUTH_A, 1 = MIFARE_CMD_AUTH_B)
    @param  keyData       Pointer to a byte array containing the 6 bytes
                          key value

    @returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
uint8_t pn532_mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
{
	  uint8_t len;
	  uint8_t i;

	  // Hang on to the key and uid data
	  memcpy (_key, keyData, 6);
	  memcpy (_uid, uid, uidLen);
	  _uidLen = uidLen;

	  // Prepare the authentication command //
	  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;   /* Data Exchange Header */
	  pn532_packetbuffer[1] = 1;                              /* Max card numbers */
	  pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
	  pn532_packetbuffer[3] = blockNumber;                    /* Block Number (1K = 0..63, 4K = 0..255 */
	  memcpy (pn532_packetbuffer+4, _key, 6);
	  for (i = 0; i < _uidLen; i++)
	  {
	    pn532_packetbuffer[10+i] = _uid[i];                /* 4 byte card ID */
	  }

	  if (pn532_sendCommandCheckAck(pn532_packetbuffer, 10+_uidLen,1000)==0)
	    return 0;

	  // Read the response packet
	  pn532_readdata(pn532_packetbuffer, 12);

	  // check if the response is valid and we are authenticated???
	  // for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
	  // Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
	  if (pn532_packetbuffer[7] != 0x00)
	  {
	    return 0;
	  }

	  return 1;
}


/**************************************************************************/
/*!
    Tries to read an entire 16-byte data block at the specified block
    address.

    @param  blockNumber   The block number to authenticate.  (0..63 for
                          1KB cards, and 0..255 for 4KB cards).
    @param  data          Pointer to the byte array that will hold the
                          retrieved data (if any)

    @returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
uint8_t pn532_mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t * data)
{
  /* Prepare the command */
  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  pn532_packetbuffer[1] = 1;                      /* Card number */
  pn532_packetbuffer[2] = MIFARE_CMD_READ;        /* Mifare Read command = 0x30 */
  pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */

  /* Send the command */
  if (pn532_sendCommandCheckAck(pn532_packetbuffer, 4,1000)==0)
  {
    return 0;
  }

  /* Read the response packet */
  pn532_readdata(pn532_packetbuffer, 26);

  /* If byte 8 isn't 0x00 we probably have an error */
  if (pn532_packetbuffer[7] != 0x00)
  {
    return 0;
  }

  /* Copy the 16 data bytes to the output buffer        */
  /* Block content starts at byte 9 of a valid response */
  memcpy (data, pn532_packetbuffer+8, 16);

  return 1;
}

/**************************************************************************/
/*!
    Tries to write an entire 16-byte data block at the specified block
    address.

    @param  blockNumber   The block number to authenticate.  (0..63 for
                          1KB cards, and 0..255 for 4KB cards).
    @param  data          The byte array that contains the data to write.

    @returns 1 if everything executed properly, 0 for an error
*/
/**************************************************************************/
uint8_t pn532_mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t * data)
{

  /* Prepare the first command */
  pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
  pn532_packetbuffer[1] = 1;                      /* Card number */
  pn532_packetbuffer[2] = MIFARE_CMD_WRITE;       /* Mifare Write command = 0xA0 */
  pn532_packetbuffer[3] = blockNumber;            /* Block Number (0..63 for 1K, 0..255 for 4K) */
  memcpy (pn532_packetbuffer+4, data, 16);          /* Data Payload */

  /* Send the command */
  if ( pn532_sendCommandCheckAck(pn532_packetbuffer, 20,10000)==0)
  {
    return 0;
  }
  HAL_Delay(50);

  /* Read the response packet */
  pn532_readdata(pn532_packetbuffer, 26);

  return 1;
}

//===============================================================================================

uint8_t pn532_sendCommandCheckAck(uint8_t *cmd, uint8_t cmdlen, uint16_t timeout) {

  // write the command
  pn532_writecommand(cmd, cmdlen);

  // Wait for chip to say its ready!
  if (!pn532_waitready(timeout)) {
    return 0;
  }

  // read acknowledgement
  if (!pn532_readack()) {
    return 0;
  }

  return 1; // ack'd command
}
//===============================================================================================
uint8_t pn532_readack() {
  uint8_t ackbuff[6];

  pn532_readdata(ackbuff, 6);

  return (0 == strncmp((char *)ackbuff, (char *)pn532ack, 6));
}

//===============================================================================================
uint8_t pn532_waitready(uint16_t timeout) {
  uint16_t timer = 0;
  while(pn532_isready()==0) {
    if (timeout != 0) {
      timer += 10;
      if (timer > timeout) {
        //term_printf("TIME OUT \n\r");
        return 0;
      }
    }
    HAL_Delay(10);
  }
  return 1;
}
//===============================================================================================
uint8_t pn532_isready()
{
	uint8_t x;
	x = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_10);
	if (x==0) {return 1;} else {return 0;}
}

//===============================================================================================
void pn532_readdata(uint8_t* buff, uint8_t n) {
    // I2C write.
    uint8_t i;

    HAL_Delay(50);

    i2c1_ReadBuffer(PN532_I2C_ADDRESS, buff, n+2);

    // discard first byte
    for (i=0; i<n-1; i++)
     {
       buff[i] = buff[i+1];
     }

}
//===============================================================================================
void pn532_writecommand(uint8_t* cmd, uint8_t cmdlen) {

    // I2C command write.
    uint8_t checksum;
    //uint8_t writeBuffer[60];
    uint8_t i;

    cmdlen++;
    HAL_Delay(2);     // or whatever the delay is for waking up the board

    checksum = PN532_PREAMBLE + PN532_PREAMBLE + PN532_STARTCODE2;
    writeBuffer[0]= PN532_PREAMBLE; // 0x00
    writeBuffer[1]= PN532_PREAMBLE; // 0x00
    writeBuffer[2]= PN532_STARTCODE2; // 0xFF
    writeBuffer[3]= cmdlen;
    writeBuffer[4]= ~cmdlen + 1;
    writeBuffer[5]= PN532_HOSTTOPN532; // 0xD4
    checksum += PN532_HOSTTOPN532;

    i=0;
    while(i<cmdlen-1)
    {
    	writeBuffer[6+i]=cmd[i];
    	checksum += cmd[i];
    	i++;

    }
    i=i+6;
    writeBuffer[i]=~checksum;
    i=i+1;
    writeBuffer[i]=PN532_POSTAMBLE;


    i2c1_WriteBuffer(PN532_I2C_ADDRESS, writeBuffer, i+1);

}
//===============================================================================================

main.c

#include "main.h"
#include "pn532.h"

int writeToken=0;
char string_to_write[20];
int stringLength = 0;

//=========================================================
//	>>>>>>>>>>>>	MAIN	<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//=========================================================

int main(void)
{
uint32_t versiondata;
uint8_t success;
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
uint8_t data[16];
int i;

HAL_Init();
SystemClock_Config();
uart2_Init();
i2c1_Init();

HAL_Delay(1000);

pn532_reset();
HAL_Delay(100);

versiondata = pn532_getFirmwareVersion();
HAL_Delay(200);
if (! versiondata)
{
  term_printf("Didn't find PN53x board\n\r");
  while (1); // halt
}

term_printf("Found chip PN5%x\n\r",(versiondata>>24) & 0xFF);
term_printf("Firmware version %d.%d\n\r",(versiondata>>16) & 0xFF, (versiondata>>8) & 0xFF);

pn532_SAMConfig(); // configure board to read RFID tags
HAL_Delay(200);

term_printf("Write ? (esc for no ) \n\r");
// wait for string

writeToken = term_scanf(string_to_write, &stringLength);


term_printf("Waiting for an ISO14443A Card ...");

while(1)
{
	 // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
	  // 'uid' will be populated with the UID, and uidLength will indicate
	  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
	  success = pn532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength, 1000);

	  if (success)
	  {
		  term_printf("Found an ISO14443A card \n\r");
		  term_printf("UID Length: %d bytes \n\r", uidLength);


		    if (uidLength == 4)
		    {
		      // We probably have a Mifare Classic card ...
		     term_printf("Seems to be a Mifare Classic card (4 byte UID) \n\r");
			 term_printf("UID Value: 0x%x 0x%x 0x%x 0x%x\n\r", uid[0],uid[1],uid[2],uid[3] );

		      // Now we need to try to authenticate it for read/write access
		      // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
		      term_printf("Trying to authenticate block 4 with default KEYA value \n\r");
		      uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

			  // Start with block 4 (the first block of sector 1) since sector 0
			  // contains the manufacturer data and it's probably better just
			  // to leave it alone unless you know what you're doing
		      success = pn532_mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);
		      HAL_Delay(200);

		      if (success)
		      {
		        term_printf("Sector 1 (Blocks 4..7) has been authenticated \n\r");

		        // If you want to write something to block 4 to test with, uncomment
				// the following line and this text should be read back in a minute

		        if(writeToken == 1)
		        {
						term_printf("string to write : %s \n\r", string_to_write);
						//memcpy(data, (const uint8_t[]){ 'K', 'E', 'R', 'H', 'O', 'A', 'S', ' ', 'V','i','n','c','e','n','t',0}, sizeof data);

						memcpy(data, string_to_write, stringLength);
						success = pn532_mifareclassic_WriteDataBlock (4, data);

						 if(success)
						 {
							 term_printf("Writing Block Finished");
							 writeToken = 0;
						   }


		        }

		        // Try to read the contents of block 4
		        success = pn532_mifareclassic_ReadDataBlock(4, data);

		        if (success)
		        {
					  // Data seems to have been read ... spit it out
					  term_printf("Reading Block 4 (HEX): \n\r");
					  for(i=0 ; i<16 ; i++)
					  {
						  term_printf("%x ",data[i]);
					  }
					  term_printf("| %s",data);
					  term_printf("\n\r");

					  // Wait a bit before reading the card again
					  HAL_Delay(1000);
		        }
		        else
		        {
		        	term_printf("Ooops ... unable to read the requested block.  Try another key? \n\r");
		        }
		      }
		      else
		      {
		    	 term_printf("Ooops ... authentication failed: Try another key? \n\r");
		      }
		    }
	  }
	  HAL_Delay(500);
}  // END WHILE
return 0;
}