1 // ************************************************************************** 2 // Custom DPA Handler code example - Using SPI MCU peripheral by OS calls * 3 // ************************************************************************** 4 // Copyright (c) IQRF Tech s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-SPI.c,v $ 7 // Version: $Revision: 1.23 $ 8 // Date: $Date: 2017/08/09 12:24:47 $ 9 // 10 // Revision history: 11 // 2017/03/13 Release for DPA 3.00 12 // 2015/08/05 Release for DPA 2.20 13 // 2014/10/31 Release for DPA 2.10 14 // 2014/04/30 Release for DPA 2.00 15 // 16 // ************************************************************************** 17 18 // Online DPA documentation http://www.iqrf.org/DpaTechGuide/ 19 20 // Default IQRF include (modify the path according to your setup) 21 #include "IQRF.h" 22 23 // Default DPA header (modify the path according to your setup) 24 #include "DPA.h" 25 // Default Custom DPA Handler header (modify the path according to your setup) 26 #include "DPAcustomHandler.h" 27 28 // This example shows how to connect custom peripheral with MCU SPI HW peripheral controlled by IQRF OS 29 30 // The example will not work at demo DPA version because demo DPA does not support the following Custom DPA Handler events: DpaEvent_Interrupt, DpaEvent_BeforeSleep, DpaEvent_AfterSleep, DpaEvent_Reset, DpaEvent_DisableInterrupts, DpaEvent_ReceiveDpaResponse, DpaEvent_IFaceReceive, DpaEvent_ReceiveDpaRequest, DpaEvent_BeforeSendingDpaResponse 31 32 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 33 //############################################################################################ 34 bit CustomDpaHandler() 35 //############################################################################################ 36 { 37 // Handler presence mark 38 clrwdt(); 39 40 // Place for local static variables used only within CustomDpaHandler() among more events 41 // example: static bit interruptOccured; 42 43 // Detect DPA event to handle (unused event handlers can be commented out or even deleted) 44 switch ( GetDpaEvent() ) 45 { 46 // ------------------------------------------------- 47 case DpaEvent_Interrupt: 48 // Do an extra quick background interrupt work 49 // ! The time spent handling this event is critical.If there is no interrupt to handle return immediately otherwise keep the code as fast as possible. 50 // ! Make sure the event is the 1st case in the main switch statement at the handler routine.This ensures that the event is handled as the 1st one. 51 // ! It is desirable that this event is handled with immediate return even if it is not used by the custom handler because the Interrupt event is raised on every MCU interrupt and the “empty” return handler ensures the shortest possible interrupt routine response time. 52 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 53 // ! Make sure race condition does not occur when accessing those variables at other places. 54 // ! Make sure( inspect.lst file generated by C compiler ) compiler does not create any hidden temporary local variable( occurs when using division, multiplication or bit shifts ) at the event handler code.The name of such variable is usually Cnumbercnt. 55 // ! Do not call any OS functions except setINDFx(). 56 // ! Do not use any OS variables especially for writing access. 57 // ! All above rules apply also to any other function being called from the event handler code, although calling any function from Interrupt event is not recommended because of additional MCU stack usage. 58 59 DpaHandleReturnTRUE: 60 return TRUE; 61 62 // ------------------------------------------------- 63 case DpaEvent_Idle: 64 // Do a quick background work when RF packet is not received 65 66 // Is there anything at SPI received? 67 if ( !getStatusSPI() && _SPIRX ) 68 { 69 if ( _SPICRCok ) 70 { 71 stopSPI(); 72 73 // PeripheralRam[0] stores length of received data 74 PeripheralRam[0] = SPIpacketLength; 75 76 // Limit to max. length of Peripheral RAM 77 if ( PeripheralRam[0] > sizeof( PeripheralRam ) - 1 ) 78 PeripheralRam[0] = sizeof( PeripheralRam ) - 1; 79 80 // Store data to PeripheralRam[1...] 81 copyMemoryBlock( bufferCOM, PeripheralRam + 1, PeripheralRam[0] ); 82 83 // Now data can be read by 84 // 1. reading from Peripheral RAM 85 // 2. by user peripheral _Pnum=PNUM_USER and _PCMD=1 86 } 87 88 startSPI( 0 ); 89 } 90 break; 91 92 // ------------------------------------------------- 93 case DpaEvent_Reset: 94 { 95 // Called after module is reset 96 //goto DpaHandleReturnTRUE; // return TRUE only if you handle node bonding/unbonding 97 static onlyOnce; 98 99 if ( !onlyOnce ) 100 { 101 onlyOnce = TRUE; 102 103 // Enable SPI after reset 104 enableSPI(); 105 bufferCOM[0] = 'R'; 106 bufferCOM[1] = 'e'; 107 bufferCOM[2] = 's'; 108 bufferCOM[3] = 'e'; 109 bufferCOM[4] = 't'; 110 startSPI( 5 ); 111 } 112 break; 113 } 114 115 // ------------------------------------------------- 116 case DpaEvent_Init: 117 // Do a one time initialization work before main loop starts 118 119 PeripheralRam[0] = 0; 120 // SPI stays enabled after reset event 121 bufferCOM[0] = 'I'; 122 bufferCOM[1] = 'n'; 123 bufferCOM[2] = 'i'; 124 bufferCOM[3] = 't'; 125 startSPI( 4 ); 126 break; 127 128 // ------------------------------------------------- 129 case DpaEvent_DpaRequest: 130 // Called to interpret DPA request for peripherals 131 // ------------------------------------------------- 132 // Peripheral enumeration 133 if ( IsDpaEnumPeripheralsRequest() ) 134 { 135 _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1; 136 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 ); 137 _DpaMessage.EnumPeripheralsAnswer.HWPID = 0x000F; 138 _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0; 139 140 goto DpaHandleReturnTRUE; 141 } 142 // ------------------------------------------------- 143 // Get information about peripheral 144 else if ( IsDpaPeripheralInfoRequest() ) 145 { 146 if ( _PNUM == PNUM_USER + 0 ) 147 { 148 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA; 149 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 150 _DpaMessage.PeripheralInfoAnswer.Par1 = 0; 151 _DpaMessage.PeripheralInfoAnswer.Par2 = 0; 152 goto DpaHandleReturnTRUE; 153 } 154 155 break; 156 } 157 // ------------------------------------------------- 158 else 159 { 160 // Handle peripheral command 161 if ( _PNUM == PNUM_USER + 0 ) 162 { 163 switch ( _PCMD ) 164 { 165 case 0: 166 // Write one byte from PData to SPI 167 if ( _DpaDataLength != 1 ) 168 goto Error_FAIL; 169 170 bufferCOM[0] = 'C'; 171 bufferCOM[1] = 'm'; 172 bufferCOM[2] = 'd'; 173 bufferCOM[3] = '='; 174 bufferCOM[4] = _DpaMessage.Request.PData[0]; 175 // SPI is enabled from reset event 176 startSPI( 5 ); 177 _DpaDataLength = 0; 178 goto DpaHandleReturnTRUE; 179 180 case 1: 181 if ( _DpaDataLength != 0 ) 182 goto Error_FAIL; 183 184 // Read data originally read from SPI 185 copyMemoryBlock( PeripheralRam + 1, _DpaMessage.Response.PData, _DpaDataLength = PeripheralRam[0] ); 186 goto DpaHandleReturnTRUE; 187 188 default:; 189 // For simplicity reasons we report only one type of error 190 Error_FAIL: 191 DpaApiReturnPeripheralError( ERROR_FAIL ); 192 } 193 } 194 } 195 196 break; 197 } 198 199 DpaHandleReturnFALSE: 200 return FALSE; 201 } 202 //############################################################################################ 203 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 204 #include "DPAcustomHandler.h" 205 //############################################################################################