Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2194 | - | 1 | /***************************************************************************** |
2 | * |
||
3 | * Atmel Corporation |
||
4 | * |
||
5 | * File : TWI_Slave.c |
||
6 | * Compiler : IAR EWAAVR 2.28a/3.10c |
||
7 | * Revision : $Revision: 2475 $ |
||
8 | * Date : $Date: 2007-09-20 12:00:43 +0200 (to, 20 sep 2007) $ |
||
9 | * Updated by : $Author: mlarsson $ |
||
10 | * |
||
11 | * Support mail : avr@atmel.com |
||
12 | * |
||
13 | * Supported devices : All devices with a TWI module can be used. |
||
14 | * The example is written for the ATmega16 |
||
15 | * |
||
16 | * AppNote : AVR311 - TWI Slave Implementation |
||
17 | * |
||
18 | * Description : This is sample driver to AVRs TWI module. |
||
19 | * It is interupt driveren. All functionality is controlled through |
||
20 | * passing information to and from functions. Se main.c for samples |
||
21 | * of how to use the driver. |
||
22 | * |
||
23 | ****************************************************************************/ |
||
24 | /*! \page MISRA |
||
25 | * |
||
26 | * General disabling of MISRA rules: |
||
27 | * * (MISRA C rule 1) compiler is configured to allow extensions |
||
28 | * * (MISRA C rule 111) bit fields shall only be defined to be of type unsigned int or signed int |
||
29 | * * (MISRA C rule 37) bitwise operations shall not be performed on signed integer types |
||
30 | * As it does not work well with 8bit architecture and/or IAR |
||
31 | |||
32 | * Other disabled MISRA rules |
||
33 | * * (MISRA C rule 109) use of union - overlapping storage shall not be used |
||
34 | * * (MISRA C rule 61) every non-empty case clause in a switch statement shall be terminated with a break statement |
||
35 | */ |
||
36 | |||
37 | #if defined(__ICCAVR__) |
||
38 | #include "ioavr.h" |
||
39 | #include "inavr.h" |
||
40 | #else |
||
41 | #include <avr/io.h> |
||
42 | #include <avr/interrupt.h> |
||
43 | #endif |
||
44 | #include "twi_slave.h" |
||
45 | |||
46 | // Emulate GCC ISR() statement in IAR |
||
47 | #if defined(__ICCAVR__) |
||
48 | #define PRAGMA(x) _Pragma( #x ) |
||
49 | #define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void) |
||
50 | #endif |
||
51 | |||
52 | static unsigned char TWI_buf[TWI_BUFFER_SIZE]; // Transceiver buffer. Set the size in the header file |
||
53 | static unsigned char TWI_msgSize = 0; // Number of bytes to be transmitted. |
||
54 | static unsigned char TWI_state = TWI_NO_STATE; // State byte. Default set to TWI_NO_STATE. |
||
55 | |||
56 | // This is true when the TWI is in the middle of a transfer |
||
57 | // and set to false when all bytes have been transmitted/received |
||
58 | // Also used to determine how deep we can sleep. |
||
59 | static volatile unsigned char TWI_busy = 0; |
||
60 | |||
61 | union TWI_statusReg_t TWI_statusReg = {0}; // TWI_statusReg is defined in TWI_Slave.h |
||
62 | |||
63 | /**************************************************************************** |
||
64 | Call this function to set up the TWI slave to its initial standby state. |
||
65 | Remember to enable interrupts from the main application after initializing the TWI. |
||
66 | Pass both the slave address and the requrements for triggering on a general call in the |
||
67 | same byte. Use e.g. this notation when calling this function: |
||
68 | TWI_Slave_Initialise( (TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) ); |
||
69 | The TWI module is configured to NACK on any requests. Use a TWI_Start_Transceiver function to |
||
70 | start the TWI. |
||
71 | ****************************************************************************/ |
||
72 | void twi_slave_init( unsigned char TWI_ownAddress ) |
||
73 | { |
||
74 | TWAR = TWI_ownAddress; // Set own TWI slave address. Accept TWI General Calls. |
||
75 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins. |
||
76 | (0<<TWIE)|(0<<TWINT)| // Disable TWI Interupt. |
||
77 | (0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Do not ACK on any requests, yet. |
||
78 | (0<<TWWC); // |
||
79 | TWI_busy = 0; |
||
80 | } |
||
81 | |||
82 | /**************************************************************************** |
||
83 | Call this function to test if the TWI_ISR is busy transmitting. |
||
84 | ****************************************************************************/ |
||
85 | unsigned char twi_slave_busy( void ) |
||
86 | { |
||
87 | return TWI_busy; |
||
88 | } |
||
89 | |||
90 | /**************************************************************************** |
||
91 | Call this function to fetch the state information of the previous operation. The function will hold execution (loop) |
||
92 | until the TWI_ISR has completed with the previous operation. If there was an error, then the function |
||
93 | will return the TWI State code. |
||
94 | ****************************************************************************/ |
||
95 | unsigned char twi_slave_get_status( void ) |
||
96 | { |
||
97 | while ( twi_slave_busy() ) {} // Wait until TWI has completed the transmission. |
||
98 | return ( TWI_state ); // Return error state. |
||
99 | } |
||
100 | |||
101 | /**************************************************************************** |
||
102 | Call this function to send a prepared message, or start the Transceiver for reception. Include |
||
103 | a pointer to the data to be sent if a SLA+W is received. The data will be copied to the TWI buffer. |
||
104 | Also include how many bytes that should be sent. Note that unlike the similar Master function, the |
||
105 | Address byte is not included in the message buffers. |
||
106 | The function will hold execution (loop) until the TWI_ISR has completed with the previous operation, |
||
107 | then initialize the next operation and return. |
||
108 | ****************************************************************************/ |
||
109 | void twi_slave_start_with_data( unsigned char *msg, unsigned char msgSize ) |
||
110 | { |
||
111 | unsigned char temp; |
||
112 | |||
113 | while ( twi_slave_busy() ) {} // Wait until TWI is ready for next transmission. |
||
114 | |||
115 | TWI_msgSize = msgSize; // Number of data to transmit. |
||
116 | for ( temp = 0; temp < msgSize; temp++ ) // Copy data that may be transmitted if the TWI Master requests data. |
||
117 | { |
||
118 | TWI_buf[ temp ] = msg[ temp ]; |
||
119 | } |
||
120 | TWI_statusReg.all = 0; |
||
121 | TWI_state = TWI_NO_STATE ; |
||
122 | TWCR = (1<<TWEN)| // TWI Interface enabled. |
||
123 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag. |
||
124 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Prepare to ACK next time the Slave is addressed. |
||
125 | (0<<TWWC); // |
||
126 | TWI_busy = 1; |
||
127 | } |
||
128 | |||
129 | /**************************************************************************** |
||
130 | Call this function to start the Transceiver without specifing new transmission data. Useful for restarting |
||
131 | a transmission, or just starting the transceiver for reception. The driver will reuse the data previously put |
||
132 | in the transceiver buffers. The function will hold execution (loop) until the TWI_ISR has completed with the |
||
133 | previous operation, then initialize the next operation and return. |
||
134 | ****************************************************************************/ |
||
135 | void twi_slave_start( void ) |
||
136 | { |
||
137 | while ( twi_slave_busy() ) {} // Wait until TWI is ready for next transmission. |
||
138 | TWI_statusReg.all = 0; |
||
139 | TWI_state = TWI_NO_STATE ; |
||
140 | TWCR = (1<<TWEN)| // TWI Interface enabled. |
||
141 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag. |
||
142 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Prepare to ACK next time the Slave is addressed. |
||
143 | (0<<TWWC); // |
||
144 | TWI_busy = 0; |
||
145 | } |
||
146 | /**************************************************************************** |
||
147 | Call this function to read out the received data from the TWI transceiver buffer. I.e. first call |
||
148 | TWI_Start_Transceiver to get the TWI Transceiver to fetch data. Then Run this function to collect the |
||
149 | data when they have arrived. Include a pointer to where to place the data and the number of bytes |
||
150 | to fetch in the function call. The function will hold execution (loop) until the TWI_ISR has completed |
||
151 | with the previous operation, before reading out the data and returning. |
||
152 | If there was an error in the previous transmission the function will return the TWI State code. |
||
153 | ****************************************************************************/ |
||
154 | unsigned char twi_slave_get_data( unsigned char *msg, unsigned char msgSize ) |
||
155 | { |
||
156 | unsigned char i; |
||
157 | |||
158 | while ( twi_slave_busy() ) {} // Wait until TWI is ready for next transmission. |
||
159 | |||
160 | if( TWI_statusReg.lastTransOK ) // Last transmission completed successfully. |
||
161 | { |
||
162 | for ( i=0; i<msgSize; i++ ) // Copy data from Transceiver buffer. |
||
163 | { |
||
164 | msg[ i ] = TWI_buf[ i ]; |
||
165 | } |
||
166 | TWI_statusReg.RxDataInBuf = FALSE; // Slave Receive data has been read from buffer. |
||
167 | } |
||
168 | return( TWI_statusReg.lastTransOK ); |
||
169 | } |
||
170 | |||
171 | |||
172 | // ********** Interrupt Handlers ********** // |
||
173 | /**************************************************************************** |
||
174 | This function is the Interrupt Service Routine (ISR), and called when the TWI interrupt is triggered; |
||
175 | that is whenever a TWI event has occurred. This function should not be called directly from the main |
||
176 | application. |
||
177 | ****************************************************************************/ |
||
178 | ISR(TWI_vect) |
||
179 | { |
||
180 | static unsigned char TWI_bufPtr; |
||
181 | |||
182 | switch (TWSR) |
||
183 | { |
||
184 | case TWI_STX_ADR_ACK: // Own SLA+R has been received; ACK has been returned |
||
185 | // case TWI_STX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned |
||
186 | TWI_bufPtr = 0; // Set buffer pointer to first data location |
||
187 | case TWI_STX_DATA_ACK: // Data byte in TWDR has been transmitted; ACK has been received |
||
188 | TWDR = TWI_buf[TWI_bufPtr++]; |
||
189 | TWCR = (1<<TWEN)| // TWI Interface enabled |
||
190 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte |
||
191 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // |
||
192 | (0<<TWWC); // |
||
193 | TWI_busy = 1; |
||
194 | break; |
||
195 | case TWI_STX_DATA_NACK: // Data byte in TWDR has been transmitted; NACK has been received. |
||
196 | // I.e. this could be the end of the transmission. |
||
197 | if (TWI_bufPtr == TWI_msgSize) // Have we transceived all expected data? |
||
198 | { |
||
199 | TWI_statusReg.lastTransOK = TRUE; // Set status bits to completed successfully. |
||
200 | } |
||
201 | else // Master has sent a NACK before all data where sent. |
||
202 | { |
||
203 | TWI_state = TWSR; // Store TWI State as errormessage. |
||
204 | } |
||
205 | |||
206 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins |
||
207 | (1<<TWIE)|(1<<TWINT)| // Keep interrupt enabled and clear the flag |
||
208 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Answer on next address match |
||
209 | (0<<TWWC); // |
||
210 | |||
211 | TWI_busy = 0; // Transmit is finished, we are not busy anymore |
||
212 | break; |
||
213 | case TWI_SRX_GEN_ACK: // General call address has been received; ACK has been returned |
||
214 | // case TWI_SRX_GEN_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned |
||
215 | TWI_statusReg.genAddressCall = TRUE; |
||
216 | case TWI_SRX_ADR_ACK: // Own SLA+W has been received ACK has been returned |
||
217 | // case TWI_SRX_ADR_ACK_M_ARB_LOST: // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned |
||
218 | // Dont need to clear TWI_S_statusRegister.generalAddressCall due to that it is the default state. |
||
219 | TWI_statusReg.RxDataInBuf = TRUE; |
||
220 | TWI_bufPtr = 0; // Set buffer pointer to first data location |
||
221 | |||
222 | // Reset the TWI Interupt to wait for a new event. |
||
223 | TWCR = (1<<TWEN)| // TWI Interface enabled |
||
224 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte |
||
225 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Expect ACK on this transmission |
||
226 | (0<<TWWC); |
||
227 | TWI_busy = 1; |
||
228 | |||
229 | break; |
||
230 | case TWI_SRX_ADR_DATA_ACK: // Previously addressed with own SLA+W; data has been received; ACK has been returned |
||
231 | case TWI_SRX_GEN_DATA_ACK: // Previously addressed with general call; data has been received; ACK has been returned |
||
232 | // TODO: What is this? Seems to be no bounds checking! |
||
233 | TWI_buf[TWI_bufPtr++] = TWDR; |
||
234 | TWI_statusReg.lastTransOK = TRUE; // Set flag transmission successfull. |
||
235 | // Reset the TWI Interupt to wait for a new event. |
||
236 | TWCR = (1<<TWEN)| // TWI Interface enabled |
||
237 | (1<<TWIE)|(1<<TWINT)| // Enable TWI Interupt and clear the flag to send byte |
||
238 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Send ACK after next reception |
||
239 | (0<<TWWC); // |
||
240 | TWI_busy = 1; |
||
241 | break; |
||
242 | case TWI_SRX_STOP_RESTART: // A STOP condition or repeated START condition has been received while still addressed as Slave |
||
243 | // Enter not addressed mode and listen to address match |
||
244 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins |
||
245 | (1<<TWIE)|(1<<TWINT)| // Enable interrupt and clear the flag |
||
246 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Wait for new address match |
||
247 | (0<<TWWC); // |
||
248 | |||
249 | TWI_busy = 0; // We are waiting for a new address match, so we are not busy |
||
250 | |||
251 | break; |
||
252 | case TWI_SRX_ADR_DATA_NACK: // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned |
||
253 | case TWI_SRX_GEN_DATA_NACK: // Previously addressed with general call; data has been received; NOT ACK has been returned |
||
254 | case TWI_STX_DATA_ACK_LAST_BYTE: // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received |
||
255 | // case TWI_NO_STATE // No relevant state information available; TWINT = �0� |
||
256 | case TWI_BUS_ERROR: // Bus error due to an illegal START or STOP condition |
||
257 | TWI_state = TWSR; //Store TWI State as errormessage, operation also clears noErrors bit |
||
258 | TWCR = (1<<TWSTO)|(1<<TWINT); //Recover from TWI_BUS_ERROR, this will release the SDA and SCL pins thus enabling other devices to use the bus |
||
259 | break; |
||
260 | default: |
||
261 | TWI_state = TWSR; // Store TWI State as errormessage, operation also clears the Success bit. |
||
262 | TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins |
||
263 | (1<<TWIE)|(1<<TWINT)| // Keep interrupt enabled and clear the flag |
||
264 | (1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // Acknowledge on any new requests. |
||
265 | (0<<TWWC); // |
||
266 | |||
267 | TWI_busy = 0; // Unknown status, so we wait for a new address match that might be something we can handle |
||
268 | } |
||
269 | } |
||
270 | |||
271 | /* |
||
272 | void example(){ |
||
273 | unsigned char messageBuf[TWI_BUFFER_SIZE]; |
||
274 | unsigned char TWI_slaveAddress; |
||
275 | |||
276 | // LED feedback port - connect port B to the STK500 LEDS |
||
277 | DDRB = 0xFF; // Set to ouput |
||
278 | PORTB = 0x55; // Startup pattern |
||
279 | |||
280 | // Own TWI slave address |
||
281 | TWI_slaveAddress = 0x10; |
||
282 | |||
283 | // Initialise TWI module for slave operation. Include address and/or enable General Call. |
||
284 | TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); |
||
285 | |||
286 | SEI(); |
||
287 | |||
288 | // Start the TWI transceiver to enable reseption of the first command from the TWI Master. |
||
289 | TWI_Start_Transceiver(); |
||
290 | |||
291 | // This example is made to work together with the AVR315 TWI Master application note. In adition to connecting the TWI |
||
292 | // pins, also connect PORTB to the LEDS. The code reads a message as a TWI slave and acts according to if it is a |
||
293 | // general call, or an address call. If it is an address call, then the first byte is considered a command byte and |
||
294 | // it then responds differently according to the commands. |
||
295 | |||
296 | // This loop runs forever. If the TWI is busy the execution will just continue doing other operations. |
||
297 | for(;;) |
||
298 | { |
||
299 | #ifdef POWER_MANAGEMENT_ENABLED |
||
300 | // Sleep while waiting for TWI transceiver to complete or waiting for new commands. |
||
301 | // If we have data in the buffer, we can't enter sleep because we have to take care |
||
302 | // of it first. |
||
303 | // If the transceiver is busy, we enter idle mode because it will wake up by all TWI |
||
304 | // interrupts. |
||
305 | // If the transceiver not is busy, we can enter power-down mode because next receive |
||
306 | // should be a TWI address match and it wakes the device up from all sleep modes. |
||
307 | if( ! TWI_statusReg.RxDataInBuf ) { |
||
308 | if(TWI_Transceiver_Busy()) { |
||
309 | MCUCR = (1<<SE)|(0<<SM2)|(0<<SM1)|(0<<SM0); // Enable sleep with idle mode |
||
310 | } else { |
||
311 | MCUCR = (1<<SE)|(0<<SM2)|(1<<SM1)|(0<<SM0); // Enable sleep with power-down mode |
||
312 | } |
||
313 | SLEEP(); |
||
314 | } else { |
||
315 | NOP(); // There is data in the buffer, code below takes care of it. |
||
316 | } |
||
317 | #else // No power management |
||
318 | // Here you can add your own code that should be run while waiting for the TWI to finish |
||
319 | NOP(); // Put own code here. |
||
320 | #endif |
||
321 | |||
322 | |||
323 | // Check if the TWI Transceiver has completed an operation. |
||
324 | if ( ! TWI_Transceiver_Busy() ) |
||
325 | { |
||
326 | // Check if the last operation was successful |
||
327 | if ( TWI_statusReg.lastTransOK ) |
||
328 | { |
||
329 | // Check if the last operation was a reception |
||
330 | if ( TWI_statusReg.RxDataInBuf ) |
||
331 | { |
||
332 | TWI_Get_Data_From_Transceiver(messageBuf, 2); |
||
333 | // Check if the last operation was a reception as General Call |
||
334 | if ( TWI_statusReg.genAddressCall ) |
||
335 | { |
||
336 | // Put data received out to PORTB as an example. |
||
337 | PORTB = messageBuf[0]; |
||
338 | } |
||
339 | else // Ends up here if the last operation was a reception as Slave Address Match |
||
340 | { |
||
341 | // Example of how to interpret a command and respond. |
||
342 | |||
343 | // TWI_CMD_MASTER_WRITE stores the data to PORTB |
||
344 | if (messageBuf[0] == TWI_CMD_MASTER_WRITE) |
||
345 | { |
||
346 | PORTB = messageBuf[1]; |
||
347 | } |
||
348 | // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. |
||
349 | if (messageBuf[0] == TWI_CMD_MASTER_READ) |
||
350 | { |
||
351 | messageBuf[0] = PINB; |
||
352 | TWI_Start_Transceiver_With_Data( messageBuf, 1 ); |
||
353 | } |
||
354 | } |
||
355 | } |
||
356 | else // Ends up here if the last operation was a transmission |
||
357 | { |
||
358 | NOP(); // Put own code here. |
||
359 | } |
||
360 | // Check if the TWI Transceiver has already been started. |
||
361 | // If not then restart it to prepare it for new receptions. |
||
362 | if ( ! TWI_Transceiver_Busy() ) |
||
363 | { |
||
364 | TWI_Start_Transceiver(); |
||
365 | } |
||
366 | } |
||
367 | else // Ends up here if the last operation completed unsuccessfully |
||
368 | { |
||
369 | TWI_Act_On_Failure_In_Last_Transmission( TWI_Get_State_Info() ); |
||
370 | } |
||
371 | } |
||
372 | } |
||
373 | }*/ |