OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [drivers/] [iic_v3_4/] [examples/] [xiic_multi_master_example.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
/******************************************************************************
2
*
3
* Copyright (C) 2006 - 2014 Xilinx, Inc.  All rights reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to deal
7
* in the Software without restriction, including without limitation the rights
8
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
* copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
14
*
15
* Use of the Software is limited solely to applications:
16
* (a) running on a Xilinx device, or
17
* (b) that interact with a Xilinx device through a bus or interconnect.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
* SOFTWARE.
26
*
27
* Except as contained in this notice, the name of the Xilinx shall not be used
28
* in advertising or otherwise to promote the sale, use or other dealings in
29
* this Software without prior written authorization from Xilinx.
30
*
31
******************************************************************************/
32
/*****************************************************************************/
33
/**
34
* @file xiic_multi_master_example.c
35
*
36
* This file consists of a Interrupt mode design example which uses the Xilinx
37
* IIC device and XIic driver to exercise the EEPROM on the Xilinx boards in a
38
* Multi master mode. This example has been tested with an off-board external
39
* IIC Master connected on the IIC bus.
40
*
41
* This example writes/reads from the lower 256 bytes of the IIC EEPROMS. Please
42
* refer to the datasheets of the IIC EEPROM's for details about the internal
43
* addressing and page size of these devices.
44
*
45
* The XIic_MasterSend() API is used to transmit the data and XIic_MasterRecv()
46
* API is used to receive the data.
47
*
48
* The example is tested on ML300/ML310/ML403/ML501 Xilinx boards.
49
*
50
* The ML310/ML410/ML510 boards have a on-board 64 Kb serial IIC EEPROM
51
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
52
* this board.
53
*
54
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
55
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
56
* The WP is connected to pin Y3 of the FPGA.
57
*
58
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
59
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
60
*
61
* The ML501/ML505/ML507/ML605/SP601/SP605 boards have an on-board 8 Kb serial
62
* IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is hardwired to
63
* ground on these boards.
64
*
65
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
66
* address pointer in the on board EEPROM is 2 bytes.
67
*
68
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
69
* be u8 as the address pointer for the on board EEPROM is 1 byte.
70
*
71
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
72
* ML501/ML505/ML507/ML510 boards is 0x50.
73
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605 boards
74
* is 0x54.
75
* Refer to the User Guide's of the respective boards for further information
76
* about the IIC slave address of IIC EEPROM's.
77
*
78
* The define EEPROM_ADDRESS in this file needs to be changed depending on
79
* the board on which this example is to be run.
80
* This code assumes that no Operating System is being used.
81
*
82
* @note
83
*
84
* None.
85
*
86
* <pre>
87
* MODIFICATION HISTORY:
88
*
89
* Ver   Who  Date        Changes
90
* ----- ---- -------- -----------------------------------------------
91
* 1.00a mta  03/01/06 Created.
92
* 2.00a sdm  09/22/09 Converted all register accesses to 32 bit access.
93
*                     Updated to use the HAL APIs, replaced call to
94
*                     XIic_Initialize API with XIic_LookupConfig and
95
*                     XIic_CfgInitialize.
96
* 2.01a ktn  03/17/10 Updated the information about the EEPROM's used on
97
*                     ML605/SP601/SP605 boards.
98
*
99
* </pre>
100
*
101
******************************************************************************/
102
 
103
/***************************** Include Files *********************************/
104
 
105
#include "xparameters.h"
106
#include "xiic.h"
107
#include "xintc.h"
108
#include "xil_exception.h"
109
 
110
/************************** Constant Definitions *****************************/
111
 
112
/*
113
 * The following constants map to the XPAR parameters created in the
114
 * xparameters.h file. They are defined here such that a user can easily
115
 * change all the needed parameters in one place.
116
 */
117
#define IIC_DEVICE_ID           XPAR_IIC_0_DEVICE_ID
118
#define INTC_DEVICE_ID          XPAR_INTC_0_DEVICE_ID
119
#define IIC_INTR_ID             XPAR_INTC_0_IIC_0_VEC_ID
120
 
121
/*
122
 * The following constant defines the address of the IIC Slave device on the
123
 * IIC bus. Note that since the address is only 7 bits, this constant is the
124
 * address divided by 2.
125
 * The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML501/
126
 * ML410/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
127
 * IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
128
 * Please refer the User Guide's of the respective boards for further
129
 * information about the IIC slave address of IIC EEPROM's.
130
 */
131
#define EEPROM_ADDRESS 0x50     /* 0xA0 as an 8 bit number. */
132
 
133
/*
134
 * The page size determines how much data should be written at a time.
135
 * The ML300 board supports a page size of 32 and 16.
136
 * The write function should be called with this as a maximum byte count.
137
 */
138
#define PAGE_SIZE   16
139
 
140
/*
141
 * The Starting address in the IIC EEPROM on which this test is performed.
142
 */
143
#define EEPROM_TEST_START_ADDRESS   128
144
 
145
/**************************** Type Definitions *******************************/
146
 
147
/*
148
 * The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
149
 * address pointer in the on board EEPROM is 2 bytes.
150
 * The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
151
 * be u8 as the address pointer in the on board EEPROM is 1 bytes.
152
 */
153
typedef u8 AddressType;
154
 
155
 
156
/***************** Macros (Inline Functions) Definitions *********************/
157
 
158
/************************** Function Prototypes ******************************/
159
 
160
int IicMultiMasterExample();
161
 
162
static int SetupInterruptSystem(XIic *IicInstPtr);
163
 
164
static void SendHandler(XIic *InstancePtr);
165
static void StatusHandler(XIic *InstancePtr, int Event);
166
 
167
/************************** Variable Definitions *****************************/
168
 
169
XIic IicInstance;               /* The instance of the IIC device. */
170
XIntc InterruptController;      /* The instance of the Interrupt Controller. */
171
 
172
/*
173
 * Write buffer for writing a page.
174
 */
175
u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE];
176
 
177
volatile u8 TransmitComplete;
178
volatile u8 ReceiveComplete;
179
volatile u8 BusNotBusy;
180
 
181
/************************** Function Definitions *****************************/
182
 
183
/*****************************************************************************/
184
/**
185
* Main function to call the Multi Master example.
186
*
187
* @param        None.
188
*
189
* @return       XST_SUCCESS if successful else XST_FAILURE.
190
*
191
* @note         None.
192
*
193
******************************************************************************/
194
int main(void)
195
{
196
        int Status;
197
 
198
        /*
199
         * Run the Multi master example.
200
         */
201
        Status = IicMultiMasterExample();
202
        if (Status != XST_SUCCESS) {
203
                return XST_FAILURE;
204
        }
205
 
206
        return XST_SUCCESS;
207
}
208
 
209
/*****************************************************************************/
210
/**
211
* This function writes the data to the IIC EEPROM.
212
*
213
* @param        None.
214
*
215
* @return       XST_SUCCESS if successful else XST_FAILURE.
216
*
217
* @note         None.
218
*
219
****************************************************************************/
220
int IicMultiMasterExample()
221
{
222
        u8 Index;
223
        int Status;
224
        XIic_Config *ConfigPtr; /* Pointer to configuration data */
225
        AddressType Address = EEPROM_TEST_START_ADDRESS;
226
 
227
        /*
228
         * Initialize the data to write and the read buffer.
229
         */
230
        if (sizeof(Address) == 1) {
231
                WriteBuffer[0] = (u8) (Address);
232
        }
233
        else {
234
                WriteBuffer[0] = (u8) (Address >> 8);
235
                WriteBuffer[1] = (u8) (Address);
236
        }
237
        for (Index = 0; Index < PAGE_SIZE; Index++) {
238
                WriteBuffer[sizeof(Address) + Index] = 0xFF;
239
        }
240
 
241
        /*
242
         * Include the multi master functionality.
243
         */
244
        XIic_MultiMasterInclude();
245
 
246
        /*
247
         * Initialize the IIC driver so that it is ready to use.
248
         */
249
        ConfigPtr = XIic_LookupConfig(XPAR_IIC_0_DEVICE_ID);
250
        if (ConfigPtr == NULL) {
251
                return XST_FAILURE;
252
        }
253
 
254
        Status = XIic_CfgInitialize(&IicInstance, ConfigPtr,
255
                                        ConfigPtr->BaseAddress);
256
        if (Status != XST_SUCCESS) {
257
                return XST_FAILURE;
258
        }
259
 
260
 
261
        /*
262
         * Setup the Interrupt System.
263
         */
264
        Status = SetupInterruptSystem(&IicInstance);
265
        if (Status != XST_SUCCESS) {
266
                return XST_FAILURE;
267
        }
268
 
269
        /*
270
         * Set the Transmit and status handlers.
271
         */
272
        XIic_SetSendHandler(&IicInstance, &IicInstance,
273
                                (XIic_Handler) SendHandler);
274
        XIic_SetStatusHandler(&IicInstance, &IicInstance,
275
                                  (XIic_StatusHandler) StatusHandler);
276
 
277
        /*
278
         * Set the address of the slave.
279
         */
280
        Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
281
                                 EEPROM_ADDRESS);
282
        if (Status != XST_SUCCESS) {
283
                return XST_FAILURE;
284
        }
285
 
286
        IicInstance.Stats.TxErrors = 0;
287
        /*
288
         * Set the defaults.
289
         */
290
        TransmitComplete = 1;
291
 
292
        /*
293
         * Start the IIC device.
294
         */
295
        Status = XIic_Start(&IicInstance);
296
        if (Status != XST_SUCCESS) {
297
                return XST_FAILURE;
298
        }
299
 
300
        /*
301
         * Write to the EEPROM.
302
         */
303
        XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
304
 
305
        while (1) {
306
                /*
307
                 * If arbitration is lost and some time later Bus if bus
308
                 * becomes free transmit the data.
309
                 */
310
                if (BusNotBusy) {
311
                        /*
312
                         * Start the IIC device.
313
                         */
314
                        Status = XIic_Start(&IicInstance);
315
                        if (Status != XST_SUCCESS) {
316
                                return XST_FAILURE;
317
                        }
318
 
319
                        /*
320
                         * Send the data.
321
                         */
322
                        XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
323
 
324
                        /*
325
                         * Clear the Flag.
326
                         */
327
                        BusNotBusy = 0;
328
                }
329
 
330
                /*
331
                 * This condition is required to be checked in the case where we
332
                 * are writing two consecutive buffers of data to the EEPROM.
333
                 * The EEPROM takes about 2 milliseconds time to update the data
334
                 * internally after a STOP has been sent on the bus.
335
                 * A NACK will be generated in the case of a second write before
336
                 * the EEPROM updates the data internally resulting in a
337
                 * Transmission Error.
338
                 */
339
                if (IicInstance.Stats.TxErrors != 0) {
340
                        /*
341
                         * If the Slave didn't acknowledge then we should keep
342
                         * making attempts to transmit the data.
343
                         */
344
                        IicInstance.Stats.TxErrors = 0;
345
                        /*
346
                         * Start the IIC device.
347
                         */
348
                        Status = XIic_Start(&IicInstance);
349
                        if (Status != XST_SUCCESS) {
350
                                return XST_FAILURE;
351
                        }
352
 
353
                        /*
354
                         * Send the data.
355
                         */
356
                        XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
357
                }
358
 
359
                if ((!TransmitComplete) &&
360
                        (XIic_IsIicBusy(&IicInstance) == FALSE))
361
                        break;
362
        }
363
 
364
        /*
365
         * Stop the IIC device.
366
         */
367
        Status = XIic_Stop(&IicInstance);
368
        if (Status != XST_SUCCESS) {
369
                return XST_FAILURE;
370
        }
371
 
372
        return XST_SUCCESS;
373
}
374
 
375
/****************************************************************************/
376
/**
377
* This function setups the interrupt system so interrupts can occur for the
378
* IIC. The function is application-specific since the actual system may or
379
* may not have an interrupt controller. The IIC device could be directly
380
* connected to a processor without an interrupt controller. The user should
381
* modify this function to fit the application.
382
*
383
* @param        IicInstPtr contains a pointer to the instance of the IIC which
384
*               is going to be connected to the interrupt controller.
385
*
386
* @return       XST_SUCCESS if successful else XST_FAILURE.
387
*
388
* @note         None.
389
*
390
****************************************************************************/
391
static int SetupInterruptSystem(XIic *IicInstPtr)
392
{
393
        int Status;
394
 
395
        if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
396
                return XST_SUCCESS;
397
        }
398
 
399
        /*
400
         * Initialize the interrupt controller driver so that it's ready to use.
401
         */
402
        Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
403
        if (Status != XST_SUCCESS) {
404
                return XST_FAILURE;
405
        }
406
 
407
        /*
408
         * Connect the device driver handler that will be called when an
409
         * interrupt for the device occurs, the handler defined above performs
410
         * the specific interrupt processing for the device.
411
         */
412
        Status = XIntc_Connect(&InterruptController, IIC_INTR_ID,
413
                                   (XInterruptHandler) XIic_InterruptHandler,
414
                                   IicInstPtr);
415
        if (Status != XST_SUCCESS) {
416
                return XST_FAILURE;
417
        }
418
 
419
        /*
420
         * Start the interrupt controller so interrupts are enabled for all
421
         * devices that cause interrupts.
422
         */
423
        Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
424
        if (Status != XST_SUCCESS) {
425
                return XST_FAILURE;
426
        }
427
 
428
        /*
429
         * Enable the interrupts for the IIC device.
430
         */
431
        XIntc_Enable(&InterruptController, IIC_INTR_ID);
432
 
433
 
434
 
435
        /*
436
         * Initialize the exception table.
437
         */
438
        Xil_ExceptionInit();
439
 
440
        /*
441
         * Register the interrupt controller handler with the exception table.
442
         */
443
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
444
                                 (Xil_ExceptionHandler) XIntc_InterruptHandler,
445
                                 &InterruptController);
446
 
447
        /*
448
         * Enable non-critical exceptions.
449
         */
450
        Xil_ExceptionEnable();
451
 
452
 
453
 
454
        return XST_SUCCESS;
455
}
456
 
457
 
458
/*****************************************************************************/
459
/**
460
* The Send handler is called asynchronously from an interrupt context and
461
* indicates that data in the specified buffer has been sent.
462
*
463
* @param        InstancePtr is a pointer to the IIC driver instance for which
464
*               the handler is being called for.
465
*
466
* @return       None.
467
*
468
* @note         None.
469
*
470
******************************************************************************/
471
static void SendHandler(XIic *InstancePtr)
472
{
473
        TransmitComplete = 0;
474
}
475
 
476
/*****************************************************************************/
477
/**
478
* The Status handler is called asynchronously from an interrupt context and
479
* indicates the events that have occured.
480
*
481
* @param        InstancePtr is a pointer to the IIC driver instance for which
482
*               the handler is being called for.
483
* @param        Event indicates the condition that has occurred.
484
*
485
* @return       None.
486
*
487
* @note         None.
488
*
489
******************************************************************************/
490
static void StatusHandler(XIic *InstancePtr, int Event)
491
{
492
        if (Event == XII_ARB_LOST_EVENT) {
493
                XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
494
                                   XIIC_CR_ENABLE_DEVICE_MASK);
495
                XIic_WriteIisr(InstancePtr->BaseAddress, XIIC_INTR_BNB_MASK);
496
                XIic_WriteIier(InstancePtr->BaseAddress, XIIC_INTR_BNB_MASK);
497
                InstancePtr->BNBOnly = TRUE;
498
        }
499
        else if (Event == XII_BUS_NOT_BUSY_EVENT) {
500
                XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
501
                                   0x0);
502
                BusNotBusy = 1;
503
        }
504
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.