1 // ******************************************************************* 2 // NFC Library for Custom DPA Handlers, chip is ST25DV04K * 3 // ******************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: NFC.c,v $ 7 // Version: $Revision: 1.11 $ 8 // Date: $Date: 2021/08/18 20:43:06 $ 9 // 10 // Revision history: 11 // 2021/08/18 Release for DPA 4.16 12 // 2020/01/02 Release for DPA 4.11 13 // 14 // ********************************************************************* 15 16 #ifndef __I2C_NFC_LIB__ 17 #define __I2C_NFC_LIB__ 18 19 //############################################################################################ 20 21 // Define to avoid deadlock when the NFC chip is not connect to the I2C bus. Pull-up resistors are required anyway! 22 // #define NFC_UPDATE_IGNORE_IF_MISSING 23 24 // I2C chips addresses 25 #define I2C_ADDRESS_NFC 0b1010.0110 26 #define I2C_ADDRESS_NFC_SYS 0b1010.1110 27 28 // NFC chip ID 29 #ifndef NFC_IC_REF 30 #define NFC_IC_REF 0x24 // = ST25DV04K 31 #endif 32 33 // NFC routines 34 void NfcUpdateIQRFcode(); 35 void NfcConfigure(); 36 37 // NFC low level routines 38 uns8 NfcReadByte( uns16 addr, uns8 device ); 39 void NfcSysWriteByte( uns8 addrLow, uns8 data ); 40 // Reads bytes to bufferRF 41 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ); 42 // Writes bytes from bufferRF 43 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device ); 44 45 #ifndef USE_FSRx 46 void setINDF1inc( uns8 data ); 47 #else 48 #define setINDF1inc( data ) do { *FSR1++ = data; } while(0) 49 #endif 50 51 #if DPA_VERSION_MASTER >= 0x0416 52 #define _i2c_start _DpaApiI2Cstart 53 #define _i2c_stop _DpaApiI2Cstop 54 #define _i2c_read _DpaApiI2Cread 55 #define _i2c_write _DpaApiI2Cwrite 56 #define _i2c_waitForIdle _DpaApiI2CwaitForIdle 57 #else 58 #define _i2c_start i2c_start 59 #define _i2c_stop i2c_stop 60 #define _i2c_read i2c_read 61 #define _i2c_write i2c_write 62 #define _i2c_waitForIdle i2c_waitForIdle 63 64 #ifndef __I2C_MASTER__ 65 #define __INCLUDE__I2C_MASTER__ 66 #include "lib/I2Cmaster.c" 67 #endif 68 69 #endif 70 71 //############################################################################################ 72 #else 73 74 #pragma library 1 // Compile only used methods 75 76 #ifdef __INCLUDE__I2C_MASTER__ 77 #include "lib/I2Cmaster.c" 78 #endif 79 80 #ifndef USE_FSRx 81 // ############################################################################################ 82 void setINDF1inc( uns8 data @ W ) 83 // ############################################################################################ 84 { 85 setINDF1( data ); 86 FSR1++; 87 } 88 #endif 89 90 // ############################################################################################ 91 uns8 NfcCfgByte( uns8 addr @ W ) 92 // ############################################################################################ 93 { 94 skip( addr ); 95 #pragma computedGoto 1 96 return 0xC6; // GPO-generuje impuls pokud dojde k RF zapisu do EEPROM a RF command EOF to response EOF. 97 return 0x00; // IT_TIME-delka pulsu GPO 301us - (0x00 * 37.5us) 98 return 0x01; // EH_MODE-energy harvesting 0x01 na vyzadani 99 return 0x00; // RF_MNGT-RF komunikace povolena 100 return 0x0C; // RFA1SS-Area1 bez hesla a povoleno pouze RF cteni, RF zapis je zakazany (tam prave ulozim IQRF code) 101 return 0x03; // ENDA1-Area1 adresa 0 až 127B 102 return 0x06; // RFA2SS-Area2 RF cteni bez hesla a RF zapis s heslem RF_PWD1 (zde je mozne zapsat pouze pomoci RF hesla) 103 return 0x07; // ENDA2-Area2 adresa 128 až 255B 104 return 0x00; // RFA3SS-Area3 RF cteni/RF zapis bez hesla 105 return 0x0B; // ENDA3-Area3 adresa 256 až 383B, zbytek je Area4 384 až 512B 106 return 0x00; // RFA4SS-Area4 RF cteni/RF zapis bez hesla 107 return 0x00; // I2CSS-I2C pristup do pameti bez hesla 108 #pragma computedGoto 0 109 } 110 111 //############################################################################################ 112 void NfcConfigure() 113 //############################################################################################ 114 { 115 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 116 if ( NfcReadByte( 0x0017 /* IC_REF */, I2C_ADDRESS_NFC_SYS ) != NFC_IC_REF ) 117 return; 118 #endif 119 120 // Enter I2C password (8x zero) 121 clearBufferRF(); 122 // I2C password validation code between 2 repeated passwords 123 bufferRF[8] = 0x09; 124 // Write password (password+0x90+password) 125 NfcWriteBytes( 0x0900, 8 + 1 + 8, I2C_ADDRESS_NFC_SYS ); 126 127 // Check the password was correct (I2C_SSO_Dyn register) 128 if ( NfcReadByte( 0x2004, I2C_ADDRESS_NFC ) != 1 ) 129 { 130 _NfcError: 131 // No, pulse both LEDs 132 pulsingLEDR(); 133 pulsingLEDG(); 134 for ( ;; ); 135 } 136 137 // Now configure NFC 138 uns8 addr = 0; // System configuration memory address 139 do { 140 uns8 cfgByte = NfcCfgByte( addr ); 141 NfcSysWriteByte( addr, cfgByte ); 142 // Check the configuration was written 143 if ( NfcReadByte( addr, I2C_ADDRESS_NFC_SYS ) != cfgByte ) 144 goto _NfcError; 145 } while ( ++addr != ( 0x0B /* I2CSS-I2C register */ + 1 ) ); 146 } 147 148 //############################################################################################ 149 void NfcUpdateIQRFcode() 150 //############################################################################################ 151 { 152 #ifdef NFC_UPDATE_IGNORE_IF_MISSING 153 if ( NfcReadByte( 0x0017 /* IC_REF */, I2C_ADDRESS_NFC_SYS ) != NFC_IC_REF ) 154 return; 155 #endif 156 157 // Check MID for the valid IQRF Code at the NFC EEPROM, read user area from address 1 where the reversed (Big Endian) MID is supposed to be 158 uns8 addr = 1 + sizeof( ModuleInfo.MID ); 159 // My MID address to the FSR1 160 #if &ModuleInfo.MID[0] == &bufferINFO[0] 161 moduleInfo(); 162 setFSR1( _FSR_INFO ); 163 #else 164 #error Cannot optimize FSR to MID address 165 #endif 166 do 167 { 168 // MID matches? 169 if ( NfcReadByte( --addr, I2C_ADDRESS_NFC ) != *FSR1 ) 170 { 171 // No, configure NFC and write IQRF Code 172 173 // Enter I2C password (8x zero) 174 clearBufferRF(); 175 // I2C password validation code between 2 repeated passwords 176 bufferRF[8] = 0x09; 177 // Write password (password+0x90+password) 178 NfcWriteBytes( 0x0900, 8 + 1 + 8, I2C_ADDRESS_NFC_SYS ); 179 180 // Check the password was correct (I2C_SSO_Dyn register) 181 if ( NfcReadByte( 0x2004, I2C_ADDRESS_NFC ) != 1 ) 182 { 183 _NfcError: 184 // No, pulse both LEDs 185 pulsingLEDR(); 186 pulsingLEDG(); 187 for ( ;; ); 188 } 189 190 // Now configure NFC 191 addr = 0; // System configuration memory address 192 do { 193 uns8 cfgByte = NfcCfgByte( addr ); 194 NfcSysWriteByte( addr, cfgByte ); 195 // Check the configuration was written 196 if ( NfcReadByte( addr, I2C_ADDRESS_NFC_SYS ) != cfgByte ) 197 goto _NfcError; 198 } while ( ++addr != ( 0x0B /* I2CSS-I2C register */ + 1 ) ); 199 200 // Writes IQRF Code to the EEPROM to the address 0, prepare it at bufferRF 201 202 // Prepare MID reversed, i.e. MSB first 203 setFSR01( _FSR_INFO, _FSR_RF ); 204 FSR0 += offsetof( TModuleInfo, MID ) + sizeof( ModuleInfo.MID ); 205 // Example: 0x15 ,0x81,0x11,0x2f,0x0e 206 setINDF1inc( 0x15 ); // Nop tag + MID tag 207 uns8 loop = sizeof( ModuleInfo.MID ); 208 do { 209 setINDF1inc( *--FSR0 ); 210 } while ( --loop != 0 ); 211 212 // Prepare IBK 213 memoryOffsetFrom |= 16; 214 moduleInfo(); // FSR0 = BUFFER_INFO = IBK 215 setFSR01( _FSR_INFO, _FSR_RF ); 216 FSR1 += 1 + sizeof( ModuleInfo.MID ); 217 // Example: 0x25 ,0xb6,0x03,0x3e,0x8f,0xb0,0x8c,0x9b,0xd1,0x74,0xa1,0x9f,0xc0,0x91,0xb8,0xb9,0xbf 218 setINDF1inc( 0x25 ); // Nop tag + IBK tag 219 loop = 16; // IBK size 220 do { 221 setINDF1inc( *FSR0++ ); 222 } while ( --loop != 0 ); 223 224 // Prepare HWPID 225 // Example: 0x35 ,0x50,0x02 226 setINDF1inc( 0x35 ); // Nop tag + HWPID tag 227 setINDF1inc( _HWPID_ >> 8 ); 228 setINDF1inc( _HWPID_ & 0xFF ); 229 230 // End tag 231 setINDF1inc( 0 ); 232 233 // Write prepared IQRF Code to NFC EEPROM at address 0 234 NfcWriteBytes( 0, 1 + sizeof( ModuleInfo.MID ) + 1 + 16 + 1 + sizeof( _HWPID ) + 1, I2C_ADDRESS_NFC ); 235 236 return; 237 } 238 239 // Note: *FSR1++ cannot be used in the "if" condition above, because CC5X cannot generate code 240 FSR1++; 241 } while ( addr != 1 ); 242 } 243 244 //############################################################################################ 245 void NfcWaitIsReady() 246 //############################################################################################ 247 { 248 _i2c_stop(); 249 do 250 { 251 _i2c_start( I2C_ADDRESS_NFC ); 252 _i2c_waitForIdle(); 253 } while ( ACKSTAT ); 254 _i2c_stop(); 255 } 256 257 //############################################################################################ 258 void NfcSysWriteByte( uns8 addrLow, uns8 data ) 259 //############################################################################################ 260 { 261 _i2c_start( I2C_ADDRESS_NFC_SYS ); 262 _i2c_write( 0 ); 263 _i2c_write( addrLow ); 264 _i2c_write( data ); 265 NfcWaitIsReady(); 266 } 267 268 //############################################################################################ 269 uns8 NfcReadByte( uns16 addr, uns8 device ) 270 //############################################################################################ 271 { 272 _i2c_start( device ); 273 _i2c_write( addr.high8 ); 274 _i2c_write( addr.low8 ); 275 _i2c_start( device | 1 ); 276 uns8 data = _i2c_read( FALSE ); 277 _i2c_stop(); 278 return data; 279 } 280 281 //############################################################################################ 282 void NfcWriteBytes( uns16 addr, uns8 length, uns8 device @ W ) 283 //############################################################################################ 284 { 285 _i2c_start( device ); 286 _i2c_write( addr.high8 ); 287 _i2c_write( addr.low8 ); 288 setFSR1( _FSR_RF ); 289 do { 290 _i2c_write( *FSR1++ ); 291 } while ( --length != 0 ); 292 NfcWaitIsReady(); 293 } 294 295 //############################################################################################ 296 void NfcReadBytes( uns16 addr, uns8 length, uns8 device ) 297 //############################################################################################ 298 { 299 _i2c_start( device ); 300 _i2c_write( addr.high8 ); 301 _i2c_write( addr.low8 ); 302 _i2c_start( device | 1 ); 303 setFSR1( _FSR_RF ); 304 do { 305 setINDF1inc( _i2c_read( length != 1 ) ); 306 } while ( --length != 0 ); 307 _i2c_stop(); 308 } 309 310 #pragma library 0 311 312 #endif 313 //############################################################################################