Martyn Gilbertson / M24512
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?

UserRevisionLine numberNew 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