Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
M24512.cpp@3:b6d7714cd171, 2019-09-16 (annotated)
- Committer:
- Martyn Gilbertson
- Date:
- Mon Sep 16 16:30:00 2019 +0100
- Revision:
- 3:b6d7714cd171
- Parent:
- 0:11e6262c2981
- Child:
- 4:336ef5db5e78
v1.0.1
[+] retries on i2c write command
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Martyn Gilbertson |
0:11e6262c2981 | 1 | /* ISL MBED Libraries |
| Martyn Gilbertson |
0:11e6262c2981 | 2 | * Copyright (C) 2019 - Invisible Systems Ltd. All Rights Reserved. |
| Martyn Gilbertson |
0:11e6262c2981 | 3 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 4 | #include "M24512.h" |
| Martyn Gilbertson |
0:11e6262c2981 | 5 | |
| Martyn Gilbertson |
0:11e6262c2981 | 6 | |
| Martyn Gilbertson |
0:11e6262c2981 | 7 | /** I2C Frequency |
| Martyn Gilbertson |
0:11e6262c2981 | 8 | Roughly calculate time to write a full page based on freq |
| Martyn Gilbertson |
0:11e6262c2981 | 9 | ((1 / 500000) * (130*9) * 1000) + 5 |
| Martyn Gilbertson |
0:11e6262c2981 | 10 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 11 | #define M24512_DEFAULT_FREQUENCY (uint32_t)500000 |
| Martyn Gilbertson |
0:11e6262c2981 | 12 | |
| Martyn Gilbertson |
0:11e6262c2981 | 13 | /** Read command | on device address |
| Martyn Gilbertson |
0:11e6262c2981 | 14 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 15 | #define M24512_COMMAND_READ (uint8_t)0 |
| Martyn Gilbertson |
0:11e6262c2981 | 16 | |
| Martyn Gilbertson |
0:11e6262c2981 | 17 | /** Write command | on device address |
| Martyn Gilbertson |
0:11e6262c2981 | 18 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 19 | #define M24512_COMMAND_WRITE (uint8_t)1 |
| Martyn Gilbertson |
0:11e6262c2981 | 20 | |
| Martyn Gilbertson |
0:11e6262c2981 | 21 | /** Device Page Size |
| Martyn Gilbertson |
0:11e6262c2981 | 22 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 23 | #define M24512_EEPROM_PAGE_SIZE (uint16_t)128 |
| Martyn Gilbertson |
0:11e6262c2981 | 24 | |
| Martyn Gilbertson |
0:11e6262c2981 | 25 | /** Device Page Count |
| Martyn Gilbertson |
0:11e6262c2981 | 26 | */ |
| Martyn Gilbertson |
0:11e6262c2981 | 27 | #define M24512_EEPROM_PAGES (uint16_t)512 |
| Martyn Gilbertson |
0:11e6262c2981 | 28 | |
| Martyn Gilbertson |
0:11e6262c2981 | 29 | |
| Martyn Gilbertson |
0:11e6262c2981 | 30 | |
| Martyn Gilbertson |
0:11e6262c2981 | 31 | M24512::M24512(PinName sda, PinName scl, uint8_t address) : _i2c(sda,scl), _addr(address) |
| Martyn Gilbertson |
0:11e6262c2981 | 32 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 33 | frequency(M24512_DEFAULT_FREQUENCY); |
| Martyn Gilbertson |
0:11e6262c2981 | 34 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 35 | |
| Martyn Gilbertson |
0:11e6262c2981 | 36 | |
| Martyn Gilbertson |
0:11e6262c2981 | 37 | M24512::~M24512() |
| Martyn Gilbertson |
0:11e6262c2981 | 38 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 39 | |
| Martyn Gilbertson |
0:11e6262c2981 | 40 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 41 | |
| Martyn Gilbertson |
0:11e6262c2981 | 42 | |
| Martyn Gilbertson |
0:11e6262c2981 | 43 | void M24512::frequency(uint32_t hz) |
| Martyn Gilbertson |
0:11e6262c2981 | 44 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 45 | _i2c.frequency(hz); |
| Martyn Gilbertson |
0:11e6262c2981 | 46 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 47 | |
| Martyn Gilbertson |
0:11e6262c2981 | 48 | |
| Martyn Gilbertson |
0:11e6262c2981 | 49 | uint32_t M24512::get_total_memory() const |
| Martyn Gilbertson |
0:11e6262c2981 | 50 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 51 | return (get_page_size() * get_page_count()) / 1024 ; |
| Martyn Gilbertson |
0:11e6262c2981 | 52 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 53 | |
| Martyn Gilbertson |
0:11e6262c2981 | 54 | |
| Martyn Gilbertson |
0:11e6262c2981 | 55 | uint16_t M24512::get_page_size() const |
| Martyn Gilbertson |
0:11e6262c2981 | 56 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 57 | return M24512_EEPROM_PAGE_SIZE; |
| Martyn Gilbertson |
0:11e6262c2981 | 58 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 59 | |
| Martyn Gilbertson |
0:11e6262c2981 | 60 | |
| Martyn Gilbertson |
0:11e6262c2981 | 61 | uint16_t M24512::get_page_count() const |
| Martyn Gilbertson |
0:11e6262c2981 | 62 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 63 | return M24512_EEPROM_PAGES; |
| Martyn Gilbertson |
0:11e6262c2981 | 64 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 65 | |
| Martyn Gilbertson |
0:11e6262c2981 | 66 | |
| Martyn Gilbertson |
0:11e6262c2981 | 67 | M24512::status_t M24512::ready() |
| Martyn Gilbertson |
0:11e6262c2981 | 68 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 69 | int8_t ack; |
| Martyn Gilbertson |
0:11e6262c2981 | 70 | char cmd[2] = {0,0}; |
| Martyn Gilbertson |
0:11e6262c2981 | 71 | int timeout = 20000; |
| Martyn Gilbertson |
0:11e6262c2981 | 72 | |
| Martyn Gilbertson |
0:11e6262c2981 | 73 | // Wait for end of write |
| Martyn Gilbertson |
0:11e6262c2981 | 74 | do{ |
| Martyn Gilbertson |
0:11e6262c2981 | 75 | // read from addr 0 with a length of 0 just to check the i2c state |
| Martyn Gilbertson |
0:11e6262c2981 | 76 | ack = _i2c.write( _addr | M24512_COMMAND_READ, cmd, 0 ); |
| Martyn Gilbertson |
0:11e6262c2981 | 77 | if (timeout-- == 0) |
| Martyn Gilbertson |
0:11e6262c2981 | 78 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 79 | return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_RDY_TIMEOUT; |
| Martyn Gilbertson |
0:11e6262c2981 | 80 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 81 | }while(ack != 0); |
| Martyn Gilbertson |
0:11e6262c2981 | 82 | |
| Martyn Gilbertson |
0:11e6262c2981 | 83 | return (ack == 0) ? M24512::M24512_SUCCESS : M24512::M24512_I2C_ERROR; |
| Martyn Gilbertson |
0:11e6262c2981 | 84 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 85 | |
| Martyn Gilbertson |
0:11e6262c2981 | 86 | |
| Martyn Gilbertson |
0:11e6262c2981 | 87 | M24512::status_t M24512::read(uint16_t addr, char* data, uint16_t size) |
| Martyn Gilbertson |
0:11e6262c2981 | 88 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 89 | int ret = 0; |
| Martyn Gilbertson |
0:11e6262c2981 | 90 | char cmd[2]; |
| Martyn Gilbertson |
0:11e6262c2981 | 91 | |
| Martyn Gilbertson |
0:11e6262c2981 | 92 | // check for overflow |
| Martyn Gilbertson |
0:11e6262c2981 | 93 | if ( ( addr + size) > (get_page_size() * get_page_count()) ) |
| Martyn Gilbertson |
0:11e6262c2981 | 94 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 95 | return M24512::M24512_MEM_OVERFLOW; |
| Martyn Gilbertson |
0:11e6262c2981 | 96 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 97 | |
| Martyn Gilbertson |
0:11e6262c2981 | 98 | cmd[0] = addr >> 8; |
| Martyn Gilbertson |
0:11e6262c2981 | 99 | cmd[1] = addr; |
| Martyn Gilbertson |
0:11e6262c2981 | 100 | |
| Martyn Gilbertson |
0:11e6262c2981 | 101 | // set address to read from |
| Martyn Gilbertson |
0:11e6262c2981 | 102 | ret = _i2c.write(_addr | M24512_COMMAND_READ, (const char*)&cmd, 2, true ); |
| Martyn Gilbertson |
0:11e6262c2981 | 103 | if (ret != 0) |
| Martyn Gilbertson |
0:11e6262c2981 | 104 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 105 | return M24512::M24512_I2C_ERROR; |
| Martyn Gilbertson |
0:11e6262c2981 | 106 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 107 | |
| Martyn Gilbertson |
0:11e6262c2981 | 108 | // read data into buffer |
| Martyn Gilbertson |
0:11e6262c2981 | 109 | ret = _i2c.read(_addr | M24512_COMMAND_READ, (char*)data, size ); |
| Martyn Gilbertson |
0:11e6262c2981 | 110 | if (ret != 0) |
| Martyn Gilbertson |
0:11e6262c2981 | 111 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 112 | return M24512::M24512_I2C_ERROR; |
| Martyn Gilbertson |
0:11e6262c2981 | 113 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 114 | |
| Martyn Gilbertson |
0:11e6262c2981 | 115 | return ready(); |
| Martyn Gilbertson |
0:11e6262c2981 | 116 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 117 | |
| Martyn Gilbertson |
0:11e6262c2981 | 118 | |
| Martyn Gilbertson |
0:11e6262c2981 | 119 | M24512::status_t M24512::write_page(uint16_t addr, const char* data, uint16_t size) |
| Martyn Gilbertson |
0:11e6262c2981 | 120 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 121 | /** TODO - Change this to dynamic incase page size increase! */ |
| Martyn Gilbertson |
0:11e6262c2981 | 122 | char cmd[M24512_EEPROM_PAGE_SIZE]; |
| Martyn Gilbertson |
0:11e6262c2981 | 123 | int ret = 0; |
| Martyn Gilbertson |
3:b6d7714cd171 | 124 | int8_t retry = 3; |
| Martyn Gilbertson |
0:11e6262c2981 | 125 | |
| Martyn Gilbertson |
0:11e6262c2981 | 126 | // check for overflow |
| Martyn Gilbertson |
0:11e6262c2981 | 127 | if ( ( addr + size) > (get_page_size() * get_page_count()) ) |
| Martyn Gilbertson |
0:11e6262c2981 | 128 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 129 | return M24512::M24512_MEM_OVERFLOW; |
| Martyn Gilbertson |
0:11e6262c2981 | 130 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 131 | |
| Martyn Gilbertson |
0:11e6262c2981 | 132 | // check for page boundary |
| Martyn Gilbertson |
0:11e6262c2981 | 133 | /** TODO - Change this to get_page_size incase change in size */ |
| Martyn Gilbertson |
0:11e6262c2981 | 134 | if (size > M24512_EEPROM_PAGE_SIZE) |
| Martyn Gilbertson |
0:11e6262c2981 | 135 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 136 | return M24512::M24512_MEM_OVERFLOW; |
| Martyn Gilbertson |
0:11e6262c2981 | 137 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 138 | |
| Martyn Gilbertson |
0:11e6262c2981 | 139 | cmd[0] = addr >> 8; |
| Martyn Gilbertson |
0:11e6262c2981 | 140 | cmd[1] = addr; |
| Martyn Gilbertson |
0:11e6262c2981 | 141 | |
| Martyn Gilbertson |
0:11e6262c2981 | 142 | for (uint8_t i = 0; i < size ; i++) |
| Martyn Gilbertson |
0:11e6262c2981 | 143 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 144 | cmd[2+i] = data[i]; |
| Martyn Gilbertson |
0:11e6262c2981 | 145 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 146 | |
| Martyn Gilbertson |
3:b6d7714cd171 | 147 | while (retry--) |
| Martyn Gilbertson |
3:b6d7714cd171 | 148 | { |
| Martyn Gilbertson |
3:b6d7714cd171 | 149 | ret = _i2c.write(_addr | M24512_COMMAND_WRITE, (const char*)&cmd, size + 2 ); |
| Martyn Gilbertson |
3:b6d7714cd171 | 150 | if (ret != 0) |
| Martyn Gilbertson |
3:b6d7714cd171 | 151 | { |
| Martyn Gilbertson |
3:b6d7714cd171 | 152 | osDelay(100); |
| Martyn Gilbertson |
3:b6d7714cd171 | 153 | }else{ |
| Martyn Gilbertson |
3:b6d7714cd171 | 154 | break; |
| Martyn Gilbertson |
3:b6d7714cd171 | 155 | } |
| Martyn Gilbertson |
3:b6d7714cd171 | 156 | } |
| Martyn Gilbertson |
3:b6d7714cd171 | 157 | |
| Martyn Gilbertson |
0:11e6262c2981 | 158 | if (ret != 0) |
| Martyn Gilbertson |
0:11e6262c2981 | 159 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 160 | return M24512::M24512_I2C_ERROR; |
| Martyn Gilbertson |
0:11e6262c2981 | 161 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 162 | |
| Martyn Gilbertson |
0:11e6262c2981 | 163 | return ready(); |
| Martyn Gilbertson |
0:11e6262c2981 | 164 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 165 | |
| Martyn Gilbertson |
0:11e6262c2981 | 166 | |
| Martyn Gilbertson |
0:11e6262c2981 | 167 | M24512::status_t M24512::write(uint16_t addr, const char* data, uint16_t size) |
| Martyn Gilbertson |
0:11e6262c2981 | 168 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 169 | M24512::status_t ret = M24512_SUCCESS; |
| Martyn Gilbertson |
0:11e6262c2981 | 170 | |
| Martyn Gilbertson |
0:11e6262c2981 | 171 | int16_t wlen = 0; // write length |
| Martyn Gilbertson |
0:11e6262c2981 | 172 | int16_t dlen = size; // data length remaining |
| Martyn Gilbertson |
0:11e6262c2981 | 173 | int16_t addr_ofst = 0; // address to write |
| Martyn Gilbertson |
0:11e6262c2981 | 174 | |
| Martyn Gilbertson |
0:11e6262c2981 | 175 | while (dlen > 0) |
| Martyn Gilbertson |
0:11e6262c2981 | 176 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 177 | wlen = ((dlen > get_page_size()) ? get_page_size() : dlen); |
| Martyn Gilbertson |
0:11e6262c2981 | 178 | |
| Martyn Gilbertson |
0:11e6262c2981 | 179 | // if addr is not at the start of a page then write bytes until we hit the boundary |
| Martyn Gilbertson |
0:11e6262c2981 | 180 | if ( addr_ofst == 0 && (addr % get_page_size()) != 0 ) |
| Martyn Gilbertson |
0:11e6262c2981 | 181 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 182 | wlen = get_page_size() - (addr % get_page_size()); |
| Martyn Gilbertson |
0:11e6262c2981 | 183 | // check we have enough data to hit end of page if not just write the entire length |
| Martyn Gilbertson |
0:11e6262c2981 | 184 | if (size < wlen) |
| Martyn Gilbertson |
0:11e6262c2981 | 185 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 186 | wlen = size; |
| Martyn Gilbertson |
0:11e6262c2981 | 187 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 188 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 189 | |
| Martyn Gilbertson |
0:11e6262c2981 | 190 | //printf("Write: Addr:%d Write: %d Remain: %d next: %d\n", addr + addr_ofst, wlen, dlen - wlen , addr_ofst + wlen); |
| Martyn Gilbertson |
0:11e6262c2981 | 191 | |
| Martyn Gilbertson |
0:11e6262c2981 | 192 | // write in blocks of %page_size% |
| Martyn Gilbertson |
0:11e6262c2981 | 193 | ret = write_page( addr + addr_ofst, data + addr_ofst, wlen ); |
| Martyn Gilbertson |
0:11e6262c2981 | 194 | if ( ret != M24512::M24512_SUCCESS ) |
| Martyn Gilbertson |
0:11e6262c2981 | 195 | { |
| Martyn Gilbertson |
0:11e6262c2981 | 196 | return ret; |
| Martyn Gilbertson |
0:11e6262c2981 | 197 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 198 | |
| Martyn Gilbertson |
0:11e6262c2981 | 199 | dlen -= wlen; |
| Martyn Gilbertson |
0:11e6262c2981 | 200 | addr_ofst += wlen; |
| Martyn Gilbertson |
0:11e6262c2981 | 201 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 202 | |
| Martyn Gilbertson |
0:11e6262c2981 | 203 | return ret; |
| Martyn Gilbertson |
0:11e6262c2981 | 204 | } |
| Martyn Gilbertson |
0:11e6262c2981 | 205 | |
| Martyn Gilbertson |
0:11e6262c2981 | 206 |