1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
#ifndef CYGONCE_IO_I2C_H
#define CYGONCE_IO_I2C_H
//=============================================================================
//
// i2c.h
//
// Generic API for accessing devices on an I2C bus
//
//=============================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2004 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//####DESCRIPTIONBEGIN####
//
// Author(s): bartv
// Date: 2004-10-05
//####DESCRIPTIONEND####
//=============================================================================
#include <pkgconf/infra.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/hal/drv_api.h>
#include <cyg/hal/hal_tables.h>
#include <cyg/hal/hal_io.h>
// The information needed for interacting with a specific I2C device.
// The bus provides the tx and rx functions. The address is (usually)
// a 7-bit number sent at the start of each operation. The flags is
// not currently used, but provides room for future expansion such as
// 10-bit addresses. The delay should be a clock period in
// nanoseconds. For the default 100KHz clock that gives a value of
// 10000
typedef struct cyg_i2c_device {
struct cyg_i2c_bus* i2c_bus;
cyg_uint16 i2c_address;
cyg_uint16 i2c_flags;
cyg_uint32 i2c_delay;
} cyg_i2c_device;
#define CYG_I2C_DEFAULT_DELAY 10000
// A utility macro for defining an I2C device
#define CYG_I2C_DEVICE(_name_, _bus_, _address_, _flags_, _delay_) \
cyg_i2c_device _name_ = { \
.i2c_bus = _bus_, \
.i2c_address = _address_, \
.i2c_flags = _flags_, \
.i2c_delay = _delay_ \
}
// The information needed for interacting over a particular I2C bus.
// Most hardware will only have one bus, but multiple buses are
// supported. Thread synchronization happens on a per-bus level.
#ifndef CYGBLD_I2C_DEVICE_CONST
#define CYGBLD_I2C_DEVICE_CONST const
#endif
typedef struct cyg_i2c_bus {
cyg_drv_mutex_t i2c_lock;
#ifdef CYGDBG_USE_ASSERTS
const cyg_i2c_device* i2c_current_device;
#endif
// The hardware-specific functions that do the real work
void (*i2c_init_fn)(struct cyg_i2c_bus*);
cyg_uint32 (*i2c_tx_fn)(CYGBLD_I2C_DEVICE_CONST cyg_i2c_device*, cyg_bool, const cyg_uint8*, cyg_uint32, cyg_bool);
cyg_uint32 (*i2c_rx_fn)(CYGBLD_I2C_DEVICE_CONST cyg_i2c_device*, cyg_bool, cyg_uint8*, cyg_uint32, cyg_bool, cyg_bool);
void (*i2c_stop_fn)(const cyg_i2c_device*);
// A spare field for use by the driver
void* i2c_extra;
} CYG_HAL_TABLE_TYPE cyg_i2c_bus;
#define CYG_I2C_BUS(_name_, _init_fn_, _tx_fn_, _rx_fn_, _stop_fn_, _extra_) \
cyg_i2c_bus _name_ CYG_HAL_TABLE_ENTRY( i2c_buses ) = { \
.i2c_init_fn = _init_fn_, \
.i2c_tx_fn = _tx_fn_, \
.i2c_rx_fn = _rx_fn_, \
.i2c_stop_fn = _stop_fn_, \
.i2c_extra = _extra_ \
}
// To support static initialization all buses are held in a table.
// Of course usually this table will only contain a single entry
extern cyg_i2c_bus cyg_i2c_buses[], cyg_i2c_buses_end;
// The main exported interface. There are high-level operations for
// simple transmits and receives, and transaction-oriented routines
// for more complicated operations including those involving repeated
// starts.
externC cyg_uint32 cyg_i2c_tx(const cyg_i2c_device*, const cyg_uint8*, cyg_uint32);
externC cyg_uint32 cyg_i2c_rx(const cyg_i2c_device*, cyg_uint8*, cyg_uint32);
externC void cyg_i2c_transaction_begin(const cyg_i2c_device*);
externC cyg_bool cyg_i2c_transaction_begin_nb(const cyg_i2c_device*);
externC cyg_uint32 cyg_i2c_transaction_tx(const cyg_i2c_device*, cyg_bool, const cyg_uint8*, cyg_uint32, cyg_bool);
externC cyg_uint32 cyg_i2c_transaction_rx(const cyg_i2c_device*, cyg_bool, cyg_uint8*, cyg_uint32, cyg_bool, cyg_bool);
externC void cyg_i2c_transaction_stop(const cyg_i2c_device*);
externC void cyg_i2c_transaction_end(const cyg_i2c_device*);
// Bit-bang support. This merely requires the platform HAL to provide
// a function for the actual bit-bang operation. The rest is handled
// by the generic code.
typedef enum cyg_i2c_bitbang_op {
CYG_I2C_BITBANG_INIT = 0,
CYG_I2C_BITBANG_SCL_HIGH = 1,
CYG_I2C_BITBANG_SCL_LOW = 2,
CYG_I2C_BITBANG_SCL_HIGH_CLOCKSTRETCH = 3,
CYG_I2C_BITBANG_SCL_LOW_SDA_INPUT = 4,
CYG_I2C_BITBANG_SDA_OUTPUT = 5,
CYG_I2C_BITBANG_SDA_HIGH = 6,
CYG_I2C_BITBANG_SDA_LOW = 7,
CYG_I2C_BITBANG_SDA_READ = 8
} cyg_i2c_bitbang_op;
typedef cyg_bool (*cyg_i2c_bitbang_fn)(cyg_i2c_bus*, cyg_i2c_bitbang_op);
// A bitbang bus can be instantiated by just providing the bitbang function.
// That is held in the extra field.
#define CYG_I2C_BITBANG_BUS(_name_, _bitbang_fn_) \
CYG_I2C_BUS(_name_, \
&cyg_i2c_bitbang_init, \
&cyg_i2c_bitbang_tx, \
&cyg_i2c_bitbang_rx, \
&cyg_i2c_bitbang_stop, \
(void*) _bitbang_fn_)
// The generic bit-bang functions. These are not called directly,
// but must be exported for use by the above macro.
externC void cyg_i2c_bitbang_init(cyg_i2c_bus*);
externC cyg_uint32 cyg_i2c_bitbang_tx(const cyg_i2c_device*, cyg_bool, const cyg_uint8*, cyg_uint32, cyg_bool);
externC cyg_uint32 cyg_i2c_bitbang_rx(const cyg_i2c_device*, cyg_bool, cyg_uint8*, cyg_uint32, cyg_bool, cyg_bool);
externC void cyg_i2c_bitbang_stop(const cyg_i2c_device*);
// Allow the HAL to export the buses and named devices. There are
// circular dependencies between this header and the HAL ones so
// it is not easy for the HAL headers to define cyg_i2c_device
// externs directly. Instead the HAL can define this macro which
// provides the externs.
#ifdef HAL_I2C_EXPORTED_DEVICES
HAL_I2C_EXPORTED_DEVICES
#endif
//-----------------------------------------------------------------------------
#endif // ifndef CYGONCE_IO_I2C_H
// End of i2c.h
|