Skip to content

Commit c74d67e

Browse files
authored
Merge pull request #10711 from geky/add-i2cee-driver
Add i2cee-driver to components
2 parents 1c32e3c + 3057ac1 commit c74d67e

File tree

6 files changed

+789
-0
lines changed

6 files changed

+789
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
dist: xenial
2+
language: python
3+
python: 2.7
4+
5+
install:
6+
# Get arm-none-eabi-gcc
7+
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
8+
- sudo apt-get update -qq
9+
- sudo apt-get install -qq gcc-arm-embedded
10+
# Get dependencies
11+
- git clone https://github.com/armmbed/mbed-os.git
12+
# Install python dependencies
13+
# - python -m pip install --upgrade pip==18.1
14+
# - python -m pip install --upgrade setuptools==40.4.3
15+
- pip install -r mbed-os/requirements.txt
16+
17+
script:
18+
# Check that examples compile
19+
- sed -n '/``` cpp/,${/```$/q;/```/d;p}' README.md > main.cpp &&
20+
PYTHONPATH=mbed-os python mbed-os/tools/make.py -t GCC_ARM -m K82F
21+
--source=. --build=BUILD/K82F/GCC_ARM -j0 &&
22+
rm main.cpp
23+
- sed -n '/@code/,${/@endcode/q;/@/d;s/^ \*//;p}' I2CEEBlockDevice.h > main.cpp &&
24+
PYTHONPATH=mbed-os python mbed-os/tools/make.py -t GCC_ARM -m K82F
25+
--source=. --build=BUILD/K82F/GCC_ARM -j0 &&
26+
rm main.cpp
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/* Simple access class for I2C EEPROM chips like Microchip 24LC
2+
* Copyright (c) 2015 Robin Hourahane
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#include "I2CEEBlockDevice.h"
17+
#include "rtos/ThisThread.h"
18+
using namespace mbed;
19+
20+
#define I2CEE_TIMEOUT 10000
21+
22+
23+
I2CEEBlockDevice::I2CEEBlockDevice(
24+
PinName sda, PinName scl, uint8_t addr,
25+
bd_size_t size, bd_size_t block, int freq)
26+
: _i2c_addr(addr), _size(size), _block(block)
27+
{
28+
_i2c = new (_i2c_buffer) I2C(sda, scl);
29+
_i2c->frequency(freq);
30+
}
31+
32+
I2CEEBlockDevice::I2CEEBlockDevice(
33+
I2C *i2c_obj, uint8_t addr,
34+
bd_size_t size, bd_size_t block)
35+
: _i2c_addr(addr), _size(size), _block(block)
36+
{
37+
_i2c = i2c_obj;
38+
}
39+
I2CEEBlockDevice::~I2CEEBlockDevice()
40+
{
41+
if (_i2c == (I2C *)_i2c_buffer) {
42+
_i2c->~I2C();
43+
}
44+
}
45+
46+
int I2CEEBlockDevice::init()
47+
{
48+
return _sync();
49+
}
50+
51+
int I2CEEBlockDevice::deinit()
52+
{
53+
return 0;
54+
}
55+
56+
int I2CEEBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size)
57+
{
58+
// Check the address and size fit onto the chip.
59+
MBED_ASSERT(is_valid_read(addr, size));
60+
61+
_i2c->start();
62+
63+
if (!_i2c->write(_i2c_addr | 0) ||
64+
!_i2c->write((char)(addr >> 8)) ||
65+
!_i2c->write((char)(addr & 0xff))) {
66+
return BD_ERROR_DEVICE_ERROR;
67+
}
68+
69+
_i2c->stop();
70+
71+
if (_i2c->read(_i2c_addr, static_cast<char *>(buffer), size) < 0) {
72+
return BD_ERROR_DEVICE_ERROR;
73+
}
74+
75+
return 0;
76+
}
77+
78+
int I2CEEBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size)
79+
{
80+
// Check the addr and size fit onto the chip.
81+
MBED_ASSERT(is_valid_program(addr, size));
82+
83+
// While we have some more data to write.
84+
while (size > 0) {
85+
uint32_t off = addr % _block;
86+
uint32_t chunk = (off + size < _block) ? size : (_block - off);
87+
88+
_i2c->start();
89+
90+
if (!_i2c->write(_i2c_addr | 0) ||
91+
!_i2c->write((char)(addr >> 8)) ||
92+
!_i2c->write((char)(addr & 0xff))) {
93+
return BD_ERROR_DEVICE_ERROR;
94+
}
95+
96+
for (unsigned i = 0; i < chunk; i++) {
97+
_i2c->write(static_cast<const char *>(buffer)[i]);
98+
}
99+
100+
_i2c->stop();
101+
102+
int err = _sync();
103+
104+
if (err) {
105+
return err;
106+
}
107+
108+
addr += chunk;
109+
size -= chunk;
110+
buffer = static_cast<const char *>(buffer) + chunk;
111+
}
112+
113+
return 0;
114+
}
115+
116+
int I2CEEBlockDevice::erase(bd_addr_t addr, bd_size_t size)
117+
{
118+
// No erase needed
119+
return 0;
120+
}
121+
122+
int I2CEEBlockDevice::_sync()
123+
{
124+
// The chip doesn't ACK while writing to the actual EEPROM
125+
// so loop trying to do a zero byte write until it is ACKed
126+
// by the chip.
127+
for (int i = 0; i < I2CEE_TIMEOUT; i++) {
128+
if (_i2c->write(_i2c_addr | 0, 0, 0) < 1) {
129+
return 0;
130+
}
131+
132+
rtos::ThisThread::sleep_for(1);
133+
}
134+
135+
return BD_ERROR_DEVICE_ERROR;
136+
}
137+
138+
bd_size_t I2CEEBlockDevice::get_read_size() const
139+
{
140+
return 1;
141+
}
142+
143+
bd_size_t I2CEEBlockDevice::get_program_size() const
144+
{
145+
return 1;
146+
}
147+
148+
bd_size_t I2CEEBlockDevice::get_erase_size() const
149+
{
150+
return 1;
151+
}
152+
153+
bd_size_t I2CEEBlockDevice::size() const
154+
{
155+
return _size;
156+
}
157+
158+
const char *I2CEEBlockDevice::get_type() const
159+
{
160+
return "I2CEE";
161+
}
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
/* Simple access class for I2C EEPROM chips like Microchip 24LC
2+
* Copyright (c) 2015 Robin Hourahane
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
#ifndef MBED_I2CEEPROM_BLOCK_DEVICE_H
17+
#define MBED_I2CEEPROM_BLOCK_DEVICE_H
18+
19+
#include "BlockDevice.h"
20+
#include "I2C.h"
21+
22+
/** BlockDevice for I2C based flash device such as
23+
* Microchip's 24LC or ATMEL's AT24C ranges
24+
*
25+
* @code
26+
* // Here's an example using a 24LC256 on a GR PEACH
27+
* #include "mbed.h"
28+
* #include "I2CEEBlockDevice.h"
29+
*
30+
* // Create EEPROM device on I2C bus with 32kbytes of memory
31+
* I2CEEBlockDevice i2cee(D14, D15, 0xa0, 32*1024);
32+
*
33+
* int main() {
34+
* printf("i2cee test\n");
35+
*
36+
* // Initialize the device and print the memory layout
37+
* i2cee.init();
38+
* printf("i2cee size: %llu\n", i2cee.size());
39+
* printf("i2cee read size: %llu\n", i2cee.get_read_size());
40+
* printf("i2cee program size: %llu\n", i2cee.get_program_size());
41+
* printf("i2cee erase size: %llu\n", i2cee.get_erase_size());
42+
*
43+
* // Write "Hello World!" to the first block
44+
* char *buffer = (char*)malloc(i2cee.get_erase_size());
45+
* sprintf(buffer, "Hello World!\n");
46+
* i2cee.erase(0, i2cee.get_erase_size());
47+
* i2cee.program(buffer, 0, i2cee.get_erase_size());
48+
*
49+
* // Read back what was stored
50+
* i2cee.read(buffer, 0, i2cee.get_erase_size());
51+
* printf("%s", buffer);
52+
*
53+
* // Deinitialize the device
54+
* i2cee.deinit();
55+
* }
56+
* @endcode
57+
*/
58+
class I2CEEBlockDevice : public BlockDevice {
59+
public:
60+
/** Constructor to create an I2CEEBlockDevice on I2C pins
61+
*
62+
* @param sda The pin name for the sda line of the I2C bus.
63+
* @param scl The pin name for the scl line of the I2C bus.
64+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
65+
* @param size The size of the device in bytes
66+
* @param block The page size of the device in bytes, defaults to 32bytes
67+
* @param freq The frequency of the I2C bus, defaults to 400K.
68+
*/
69+
I2CEEBlockDevice(
70+
PinName sda, PinName scl, uint8_t address,
71+
bd_size_t size, bd_size_t block = 32,
72+
int bus_speed = 400000);
73+
74+
/** Constructor to create an I2CEEBlockDevice on I2C pins
75+
*
76+
* @param i2c The I2C instance pointer
77+
* @param addr The 8bit I2C address of the chip, common range 0xa0 - 0xae.
78+
* @param size The size of the device in bytes
79+
* @param block The page size of the device in bytes, defaults to 32bytes
80+
* @param freq The frequency of the I2C bus, defaults to 400K.
81+
*/
82+
I2CEEBlockDevice(
83+
mbed::I2C *i2c_obj, uint8_t address,
84+
bd_size_t size, bd_size_t block = 32);
85+
86+
/** Destructor of I2CEEBlockDevice
87+
*/
88+
89+
virtual ~I2CEEBlockDevice();
90+
91+
/** Initialize a block device
92+
*
93+
* @return 0 on success or a negative error code on failure
94+
*/
95+
virtual int init();
96+
97+
/** Deinitialize a block device
98+
*
99+
* @return 0 on success or a negative error code on failure
100+
*/
101+
virtual int deinit();
102+
103+
/** Read blocks from a block device
104+
*
105+
* @param buffer Buffer to write blocks to
106+
* @param addr Address of block to begin reading from
107+
* @param size Size to read in bytes, must be a multiple of read block size
108+
* @return 0 on success, negative error code on failure
109+
*/
110+
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
111+
112+
/** Program blocks to a block device
113+
*
114+
* The blocks must have been erased prior to being programmed
115+
*
116+
* @param buffer Buffer of data to write to blocks
117+
* @param addr Address of block to begin writing to
118+
* @param size Size to write in bytes, must be a multiple of program block size
119+
* @return 0 on success, negative error code on failure
120+
*/
121+
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
122+
123+
/** Erase blocks on a block device
124+
*
125+
* The state of an erased block is undefined until it has been programmed
126+
*
127+
* @param addr Address of block to begin erasing
128+
* @param size Size to erase in bytes, must be a multiple of erase block size
129+
* @return 0 on success, negative error code on failure
130+
*/
131+
virtual int erase(bd_addr_t addr, bd_size_t size);
132+
133+
/** Get the size of a readable block
134+
*
135+
* @return Size of a readable block in bytes
136+
*/
137+
virtual bd_size_t get_read_size() const;
138+
139+
/** Get the size of a programable block
140+
*
141+
* @return Size of a programable block in bytes
142+
* @note Must be a multiple of the read size
143+
*/
144+
virtual bd_size_t get_program_size() const;
145+
146+
/** Get the size of a eraseable block
147+
*
148+
* @return Size of a eraseable block in bytes
149+
* @note Must be a multiple of the program size
150+
*/
151+
virtual bd_size_t get_erase_size() const;
152+
153+
/** Get the total size of the underlying device
154+
*
155+
* @return Size of the underlying device in bytes
156+
*/
157+
virtual bd_size_t size() const;
158+
159+
/** Get the BlockDevice class type.
160+
*
161+
* @return A string representation of the BlockDevice class type.
162+
*/
163+
virtual const char *get_type() const;
164+
165+
private:
166+
mbed::I2C *_i2c;
167+
uint32_t _i2c_buffer[sizeof(mbed::I2C) / sizeof(uint32_t)];
168+
uint8_t _i2c_addr;
169+
uint32_t _size;
170+
uint32_t _block;
171+
172+
int _sync();
173+
};
174+
175+
176+
#endif /* MBED_SD_BLOCK_DEVICE_H */

0 commit comments

Comments
 (0)