1.1 --- a/pkg/devices/lib/i2c/include/i2c-jz4730.h Sun Jan 31 22:47:14 2021 +0100
1.2 +++ b/pkg/devices/lib/i2c/include/i2c-jz4730.h Sat Jun 10 22:45:34 2023 +0200
1.3 @@ -31,6 +31,22 @@
1.4 #include <l4/devices/cpm-jz4730.h>
1.5 #include <l4/devices/hw_mmio_register_block.h>
1.6
1.7 +
1.8 +
1.9 +// State machine states.
1.10 +
1.11 +enum I2c_jz4730_state
1.12 +{
1.13 + I2c_jz4730_end = 0,
1.14 + I2c_jz4730_pre_start,
1.15 + I2c_jz4730_start_read,
1.16 + I2c_jz4730_perform_read,
1.17 + I2c_jz4730_perform_write,
1.18 + I2c_jz4730_stop_write
1.19 +};
1.20 +
1.21 +
1.22 +
1.23 // I2C channel.
1.24
1.25 class I2c_jz4730_channel
1.26 @@ -51,9 +67,30 @@
1.27 unsigned int read(uint8_t address, uint8_t buf[], unsigned int length);
1.28 unsigned int write(uint8_t address, uint8_t buf[], unsigned int length);
1.29
1.30 + // Statistics.
1.31 +
1.32 + unsigned int start_not_possible = 0, read_not_ready = 0, read_not_ready_clear = 0, read_not_ready_stx = 0,
1.33 + read_not_possible = 0, read_nack = 0, read_complete = 0,
1.34 + write_not_possible = 0, write_complete = 0, total_reads = 0;
1.35 +
1.36 protected:
1.37 void set_frequency();
1.38
1.39 + // State machine activities.
1.40 +
1.41 + unsigned int _nread, _nwritten, _length, _limit;
1.42 + uint8_t _address;
1.43 + uint8_t *_buf;
1.44 + bool _read;
1.45 +
1.46 + void communicate();
1.47 +
1.48 + enum I2c_jz4730_state pre_start();
1.49 + enum I2c_jz4730_state start_read();
1.50 + enum I2c_jz4730_state perform_read();
1.51 + enum I2c_jz4730_state perform_write();
1.52 + enum I2c_jz4730_state stop_write();
1.53 +
1.54 // Transaction control.
1.55
1.56 bool set_address(uint8_t address, bool read);
1.57 @@ -113,4 +150,24 @@
1.58
1.59 unsigned int jz4730_i2c_write(void *i2c_channel, uint8_t address, uint8_t buf[], unsigned int length);
1.60
1.61 +unsigned int jz4730_i2c_start_not_possible(void *i2c_channel);
1.62 +
1.63 +unsigned int jz4730_i2c_read_not_ready(void *i2c_channel);
1.64 +
1.65 +unsigned int jz4730_i2c_read_not_ready_clear(void *i2c_channel);
1.66 +
1.67 +unsigned int jz4730_i2c_read_not_ready_stx(void *i2c_channel);
1.68 +
1.69 +unsigned int jz4730_i2c_read_not_possible(void *i2c_channel);
1.70 +
1.71 +unsigned int jz4730_i2c_read_nack(void *i2c_channel);
1.72 +
1.73 +unsigned int jz4730_i2c_read_complete(void *i2c_channel);
1.74 +
1.75 +unsigned int jz4730_i2c_write_not_possible(void *i2c_channel);
1.76 +
1.77 +unsigned int jz4730_i2c_write_complete(void *i2c_channel);
1.78 +
1.79 +unsigned int jz4730_i2c_total_reads(void *i2c_channel);
1.80 +
1.81 EXTERN_C_END
2.1 --- a/pkg/devices/lib/i2c/src/jz4730.cc Sun Jan 31 22:47:14 2021 +0100
2.2 +++ b/pkg/devices/lib/i2c/src/jz4730.cc Sat Jun 10 22:45:34 2023 +0200
2.3 @@ -133,31 +133,207 @@
2.4 _regs[I2c_clock] = division;
2.5 }
2.6
2.7 -// Present the address on the bus.
2.8 +// State machine controller.
2.9
2.10 -bool
2.11 -I2c_jz4730_channel::set_address(uint8_t address, bool read)
2.12 +void
2.13 +I2c_jz4730_channel::communicate()
2.14 {
2.15 - // Waiting for long enough may eliminate a busy condition and thus permit a
2.16 - // new transaction. 10ms appears to be long enough, whereas 1ms does not
2.17 - // appear to be. In case this is insufficient, permit failure.
2.18 -
2.19 - unsigned int limit = 10;
2.20 + enum I2c_jz4730_state state = I2c_jz4730_pre_start;
2.21 + _limit = 1;
2.22
2.23 do
2.24 {
2.25 - if (!wait_for_irq(1000) && !(--limit))
2.26 - return false;
2.27 + wait_for_irq(100000);
2.28 +
2.29 + switch (state)
2.30 + {
2.31 + case I2c_jz4730_pre_start:
2.32 + state = pre_start();
2.33 + break;
2.34 +
2.35 + case I2c_jz4730_start_read:
2.36 + state = start_read();
2.37 + break;
2.38 +
2.39 + case I2c_jz4730_perform_read:
2.40 + state = perform_read();
2.41 + break;
2.42 +
2.43 + case I2c_jz4730_perform_write:
2.44 + state = perform_write();
2.45 + break;
2.46 +
2.47 + case I2c_jz4730_stop_write:
2.48 + state = stop_write();
2.49 + break;
2.50 +
2.51 + default:
2.52 + break;
2.53 + }
2.54 }
2.55 - while (busy());
2.56 + while (state != I2c_jz4730_end);
2.57 +}
2.58 +
2.59 +// State machine implementation handlers.
2.60 +
2.61 +// Assert not busy state, issue start, present the address on the bus.
2.62 +
2.63 +enum I2c_jz4730_state
2.64 +I2c_jz4730_channel::pre_start()
2.65 +{
2.66 + // Wait again if busy up to the limit.
2.67 +
2.68 + if (busy())
2.69 + {
2.70 + if (!(--_limit))
2.71 + {
2.72 + start_not_possible++;
2.73 + return I2c_jz4730_end;
2.74 + }
2.75 + else
2.76 + return I2c_jz4730_pre_start;
2.77 + }
2.78 +
2.79 + // Use a longer time limit in subsequent activities.
2.80 +
2.81 + _limit = 1;
2.82 +
2.83 + // Start, send address, proceed to the operation.
2.84
2.85 start();
2.86
2.87 - _regs[I2c_data] = (address << 1) | (read ? 1 : 0);
2.88 + _regs[I2c_data] = (_address << 1) | (_read ? 1 : 0);
2.89
2.90 send_next();
2.91
2.92 - return true;
2.93 + return _read ? I2c_jz4730_start_read : I2c_jz4730_perform_write;
2.94 +}
2.95 +
2.96 +// Wait for an opportunity to begin reading.
2.97 +
2.98 +enum I2c_jz4730_state
2.99 +I2c_jz4730_channel::start_read()
2.100 +{
2.101 + // Wait again if not ready to read.
2.102 +
2.103 + if (transferring() || (!data_valid() && !nack()))
2.104 + {
2.105 + read_not_ready++;
2.106 + if (transferring())
2.107 + read_not_ready_stx++;
2.108 + else
2.109 + read_not_ready_clear++;
2.110 + return I2c_jz4730_start_read;
2.111 + }
2.112 +
2.113 + return I2c_jz4730_perform_read;
2.114 +}
2.115 +
2.116 +// Attempt to read from the device.
2.117 +
2.118 +enum I2c_jz4730_state
2.119 +I2c_jz4730_channel::perform_read()
2.120 +{
2.121 + // Wait again if no available data.
2.122 +
2.123 + if (!data_valid() && !nack())
2.124 + {
2.125 + if (!(--_limit))
2.126 + {
2.127 + read_not_possible++;
2.128 + stop();
2.129 + return I2c_jz4730_end;
2.130 + }
2.131 + else
2.132 + return I2c_jz4730_perform_read;
2.133 + }
2.134 +
2.135 + // Stop if NACK received.
2.136 +
2.137 + if (nack())
2.138 + {
2.139 + read_nack++;
2.140 + stop();
2.141 + return I2c_jz4730_end;
2.142 + }
2.143 +
2.144 + // Signal last byte if appropriate.
2.145 +
2.146 + if ((!_nread && (_length == 1)) || (_nread == _length - 2))
2.147 + signal_last();
2.148 +
2.149 + // Store and solicit data.
2.150 +
2.151 + _buf[_nread++] = _regs[I2c_data];
2.152 + clear_next();
2.153 +
2.154 + // Stop if all data received.
2.155 +
2.156 + if (_nread >= _length)
2.157 + {
2.158 + read_complete++;
2.159 + stop();
2.160 + return I2c_jz4730_end;
2.161 + }
2.162 +
2.163 + // Wait for more data otherwise.
2.164 +
2.165 + _limit = 1;
2.166 + return I2c_jz4730_perform_read;
2.167 +}
2.168 +
2.169 +// Attempt to write to the device.
2.170 +
2.171 +enum I2c_jz4730_state
2.172 +I2c_jz4730_channel::perform_write()
2.173 +{
2.174 + // Wait for data (address or previous data) to be sent.
2.175 +
2.176 + if (data_valid() && !nack())
2.177 + {
2.178 + if (!(--_limit))
2.179 + {
2.180 + write_not_possible++;
2.181 + stop();
2.182 + return I2c_jz4730_end;
2.183 + }
2.184 + else
2.185 + return I2c_jz4730_perform_write;
2.186 + }
2.187 +
2.188 + // Stop if all data written or NACK received.
2.189 +
2.190 + if ((_nwritten >= _length) || nack())
2.191 + {
2.192 + write_complete++;
2.193 + stop();
2.194 + _limit = 1;
2.195 + return I2c_jz4730_stop_write;
2.196 + }
2.197 +
2.198 + // Write more data.
2.199 +
2.200 + _regs[I2c_data] = _buf[_nwritten++];
2.201 + send_next();
2.202 +
2.203 + // Wait for the data to be sent.
2.204 +
2.205 + _limit = 1;
2.206 + return I2c_jz4730_perform_write;
2.207 +}
2.208 +
2.209 +// Terminate the write transaction.
2.210 +
2.211 +enum I2c_jz4730_state
2.212 +I2c_jz4730_channel::stop_write()
2.213 +{
2.214 + if (!transferred())
2.215 + {
2.216 + if (--_limit)
2.217 + return I2c_jz4730_stop_write;
2.218 + }
2.219 +
2.220 + return I2c_jz4730_end;
2.221 }
2.222
2.223 // Wait up to the given timeout (in microseconds) for an interrupt request,
2.224 @@ -174,54 +350,16 @@
2.225 unsigned int
2.226 I2c_jz4730_channel::read(uint8_t address, uint8_t buf[], unsigned int length)
2.227 {
2.228 - unsigned int nread = 0;
2.229 -
2.230 - if (!set_address(address, true))
2.231 - return 0;
2.232 -
2.233 - // Wait for an opportunity to begin reading.
2.234 -
2.235 - do
2.236 - {
2.237 - if (!wait_for_irq(1000000))
2.238 - printf("start (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
2.239 - }
2.240 - while (transferring() || (!data_valid() && !nack()));
2.241 -
2.242 - // Device apparently unavailable.
2.243 -
2.244 - if (nack())
2.245 - {
2.246 - stop();
2.247 - return nread;
2.248 - }
2.249 -
2.250 - // Attempt to read from the device.
2.251 + _nread = 0;
2.252 + _length = length;
2.253 + _address = address;
2.254 + _buf = &buf[0];
2.255 + _read = true;
2.256 + total_reads++;
2.257
2.258 - while (nread < length)
2.259 - {
2.260 - do
2.261 - {
2.262 - if (!wait_for_irq(1000000))
2.263 - {
2.264 - stop();
2.265 - return nread;
2.266 - }
2.267 - }
2.268 - while (!data_valid() && !nack());
2.269 + communicate();
2.270
2.271 - if (nack())
2.272 - break;
2.273 -
2.274 - if ((!nread && (length == 1)) || (nread == length - 2))
2.275 - signal_last();
2.276 -
2.277 - buf[nread++] = _regs[I2c_data];
2.278 - clear_next();
2.279 - }
2.280 -
2.281 - stop();
2.282 - return nread;
2.283 + return _nread;
2.284 }
2.285
2.286 // Write data to the bus.
2.287 @@ -229,49 +367,15 @@
2.288 unsigned int
2.289 I2c_jz4730_channel::write(uint8_t address, uint8_t buf[], unsigned int length)
2.290 {
2.291 - unsigned int nwritten = 0;
2.292 -
2.293 - if (!set_address(address, false))
2.294 - return 0;
2.295 -
2.296 - do
2.297 - {
2.298 - if (!wait_for_irq(1000000))
2.299 - {
2.300 - printf("write (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
2.301 - stop();
2.302 - return nwritten;
2.303 - }
2.304 - }
2.305 - while (data_valid() && !nack());
2.306 -
2.307 - while ((nwritten < length) && !nack())
2.308 - {
2.309 - _regs[I2c_data] = buf[nwritten++];
2.310 - send_next();
2.311 + _nwritten = 0;
2.312 + _length = length;
2.313 + _address = address;
2.314 + _buf = &buf[0];
2.315 + _read = false;
2.316
2.317 - do
2.318 - {
2.319 - if (!wait_for_irq(1000000))
2.320 - {
2.321 - printf("write (no irq): status = %x\n", (uint32_t) _regs[I2c_status]);
2.322 - stop();
2.323 - return nwritten;
2.324 - }
2.325 - }
2.326 - while (data_valid() && !nack());
2.327 - }
2.328 + communicate();
2.329
2.330 - stop();
2.331 -
2.332 - do
2.333 - {
2.334 - if (!wait_for_irq(1000000))
2.335 - break;
2.336 - }
2.337 - while (!transferred());
2.338 -
2.339 - return nwritten;
2.340 + return _nwritten;
2.341 }
2.342
2.343 // Test for data validity.
2.344 @@ -409,3 +513,33 @@
2.345 {
2.346 return static_cast<I2c_jz4730_channel *>(i2c_channel)->write(address, buf, length);
2.347 }
2.348 +
2.349 +unsigned int jz4730_i2c_start_not_possible(void *i2c_channel)
2.350 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->start_not_possible; }
2.351 +
2.352 +unsigned int jz4730_i2c_read_not_ready(void *i2c_channel)
2.353 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_not_ready; }
2.354 +
2.355 +unsigned int jz4730_i2c_read_not_ready_clear(void *i2c_channel)
2.356 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_not_ready_clear; }
2.357 +
2.358 +unsigned int jz4730_i2c_read_not_ready_stx(void *i2c_channel)
2.359 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_not_ready_stx; }
2.360 +
2.361 +unsigned int jz4730_i2c_read_not_possible(void *i2c_channel)
2.362 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_not_possible; }
2.363 +
2.364 +unsigned int jz4730_i2c_read_nack(void *i2c_channel)
2.365 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_nack; }
2.366 +
2.367 +unsigned int jz4730_i2c_read_complete(void *i2c_channel)
2.368 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->read_complete; }
2.369 +
2.370 +unsigned int jz4730_i2c_write_not_possible(void *i2c_channel)
2.371 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->write_not_possible; }
2.372 +
2.373 +unsigned int jz4730_i2c_write_complete(void *i2c_channel)
2.374 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->write_complete; }
2.375 +
2.376 +unsigned int jz4730_i2c_total_reads(void *i2c_channel)
2.377 +{ return reinterpret_cast<I2c_jz4730_channel *>(i2c_channel)->total_reads; }
3.1 --- a/pkg/landfall-examples/letux400_i2c/letux400_i2c.cc Sun Jan 31 22:47:14 2021 +0100
3.2 +++ b/pkg/landfall-examples/letux400_i2c/letux400_i2c.cc Sat Jun 10 22:45:34 2023 +0200
3.3 @@ -258,6 +258,22 @@
3.4 sleep(5);
3.5 }
3.6
3.7 + printf("start_not_possible = %d\n"
3.8 + "read_not_ready = %d\n"
3.9 + "read_not_ready_clear = %d\n"
3.10 + "read_not_ready_stx = %d\n"
3.11 + "read_not_possible = %d\n"
3.12 + "read_nack = %d\n"
3.13 + "read_complete = %d\n"
3.14 + "write_not_possible = %d\n"
3.15 + "write_complete = %d\n"
3.16 + "total_reads = %d\n",
3.17 + jz4730_i2c_start_not_possible(i2c0), jz4730_i2c_read_not_ready(i2c0), jz4730_i2c_read_not_ready_clear(i2c0), jz4730_i2c_read_not_ready_stx(i2c0),
3.18 + jz4730_i2c_read_not_possible(i2c0), jz4730_i2c_read_nack(i2c0), jz4730_i2c_read_complete(i2c0),
3.19 + jz4730_i2c_write_not_possible(i2c0), jz4730_i2c_write_complete(i2c0), jz4730_i2c_total_reads(i2c0));
3.20 +
3.21 + sleep(30);
3.22 +
3.23 /* Issue a shutdown request. */
3.24
3.25 buf[0] = 0xd8; buf[1] = 1;