OK, I2C read by DMA works

This commit is contained in:
Edward Emelianov 2025-09-19 21:24:19 +03:00
parent 934f4fbddd
commit 080be6a1ec
8 changed files with 103 additions and 109 deletions

View File

@ -136,40 +136,35 @@ static void i2cDMAsetup(int tx, uint16_t len){
// wait until bit set or clear; return 1 if OK, 0 in case of timeout // wait until bit set or clear; return 1 if OK, 0 in case of timeout
static uint8_t waitISRbit(uint32_t bit, uint8_t isset){ static uint8_t waitISRbit(uint32_t bit, uint8_t isset){
uint32_t waitwhile = (isset) ? 0 : bit; // wait until != uint32_t waitwhile = (isset) ? 0 : bit; // wait until !=
const char *errmsg = NULL; //const char *errmsg = NULL;
cntr = Tms; cntr = Tms;
if(bit != I2C_ISR_RXNE){ U("ISR wait "); U(uhex2str(bit)); USND(isset ? "set" : "reset"); } //if(bit != I2C_ISR_RXNE){ U("ISR wait "); U(uhex2str(bit)); USND(isset ? "set" : "reset"); }
while((I2C1->ISR & bit) == waitwhile){ while((I2C1->ISR & bit) == waitwhile){
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
if(I2C1->ISR & I2C_ISR_NACKF){ if(I2C1->ISR & I2C_ISR_NACKF){
errmsg = "NAK"; //errmsg = "NAK";
goto goterr; goto goterr;
} }
if(Tms - cntr > I2C_TIMEOUT){ if(Tms - cntr > I2C_TIMEOUT){
errmsg = "timeout"; //errmsg = "timeout";
goto goterr; goto goterr;
} }
} }
return 1; return 1;
goterr: goterr:
U("wait ISR bit: "); USND(errmsg); /*U("wait ISR bit: "); USND(errmsg);
U("I2c->ISR = "); USND(uhex2str(I2C1->ISR)); U("I2c->ISR = "); USND(uhex2str(I2C1->ISR));*/
I2C1->ICR = 0xff; I2C1->ICR = 0xff;
return 0; return 0;
} }
// start writing // start writing
static uint8_t i2c_startw(uint8_t addr, uint16_t nbytes, uint8_t stop){ static uint8_t i2c_startw(uint8_t addr, uint8_t nbytes, uint8_t stop){
if(!waitISRbit(I2C_ISR_BUSY, 0)) return 0; if(!waitISRbit(I2C_ISR_BUSY, 0)) return 0;
I2C1->CR2 = nbytes << 16 | addr; uint32_t cr2 = nbytes << 16 | addr | I2C_CR2_START;
if(stop){ if(stop) cr2 |= I2C_CR2_AUTOEND;
I2C1->CR2 |= I2C_CR2_AUTOEND; // autoend
}else{
//I2C1->CR2 &= ~I2C_CR2_AUTOEND;
//I2C1->CR2 |= I2C_CR2_RELOAD;
}
// now start transfer // now start transfer
I2C1->CR2 |= I2C_CR2_START; I2C1->CR2 = cr2;
return 1; return 1;
} }
@ -181,7 +176,7 @@ static uint8_t i2c_startw(uint8_t addr, uint16_t nbytes, uint8_t stop){
* @param stop - to set STOP * @param stop - to set STOP
* @return 0 if error * @return 0 if error
*/ */
static uint8_t write_i2cs(uint8_t addr, uint8_t *data, uint16_t nbytes, uint8_t stop){ static uint8_t i2c_writes(uint8_t addr, uint8_t *data, uint8_t nbytes, uint8_t stop){
if(!i2c_startw(addr, nbytes, stop)) return 0; if(!i2c_startw(addr, nbytes, stop)) return 0;
for(int i = 0; i < nbytes; ++i){ for(int i = 0; i < nbytes; ++i){
cntr = Tms; cntr = Tms;
@ -189,16 +184,16 @@ static uint8_t write_i2cs(uint8_t addr, uint8_t *data, uint16_t nbytes, uint8_t
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
if(I2C1->ISR & I2C_ISR_NACKF){ if(I2C1->ISR & I2C_ISR_NACKF){
I2C1->ICR |= I2C_ICR_NACKCF; I2C1->ICR |= I2C_ICR_NACKCF;
USND("write_i2cs: NAK"); //USND("i2c_writes: NAK");
return 0; return 0;
} }
if(Tms - cntr > I2C_TIMEOUT){ if(Tms - cntr > I2C_TIMEOUT){
USND("write_i2cs: Timeout"); //USND("i2c_writes: Timeout");
return 0; return 0;
} }
} }
I2C1->TXDR = data[i]; // send data I2C1->TXDR = data[i]; // send data
U("write_i2cs: "); USND(uhex2str(data[i])); //U("i2c_writes: "); USND(uhex2str(data[i]));
} }
cntr = Tms; cntr = Tms;
if(stop){ if(stop){
@ -209,19 +204,13 @@ static uint8_t write_i2cs(uint8_t addr, uint8_t *data, uint16_t nbytes, uint8_t
return 1; return 1;
} }
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint16_t nbytes){ uint8_t i2c_write(uint8_t addr, uint8_t *data, uint8_t nbytes){
if(isI2Cbusy()) return 0; if(isI2Cbusy()) return 0;
return write_i2cs(addr, data, nbytes, 1); return i2c_writes(addr, data, nbytes, 1);
} }
/* uint8_t i2c_write_dma(uint8_t addr, uint8_t *data, uint8_t nbytes){
uint8_t write_i2c16(uint8_t addr, uint8_t *data, uint8_t nbytes){ if(!data || nbytes < 1) return 0;
if(isI2Cbusy()) return 0;
return write_i2cs(addr, data, nbytes, 1);
}*/
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint16_t nbytes){
if(!data || nbytes < 1 || nbytes > I2C_BUFSIZE) return 0;
if(isI2Cbusy()) return 0; if(isI2Cbusy()) return 0;
memcpy(I2Cbuf, data, nbytes); memcpy(I2Cbuf, data, nbytes);
i2cDMAsetup(1, nbytes); i2cDMAsetup(1, nbytes);
@ -232,8 +221,8 @@ uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint16_t nbytes){
return 1; return 1;
} }
uint8_t write_i2c_dma16(uint8_t addr, uint16_t *data, uint16_t nwords){ uint8_t i2c_write_dma16(uint8_t addr, uint16_t *data, uint8_t nwords){
if(!data || nwords < 1 || nwords > I2C_BUFSIZE/2) return 0; if(!data || nwords < 1 || nwords > 127) return 0;
if(isI2Cbusy()) return 0; if(isI2Cbusy()) return 0;
uint16_t nbytes = nwords << 1; uint16_t nbytes = nwords << 1;
if(bigendian){ if(bigendian){
@ -251,10 +240,8 @@ uint8_t write_i2c_dma16(uint8_t addr, uint16_t *data, uint16_t nwords){
// start reading of `nbytes` from `addr`; if `start`==`, set START // start reading of `nbytes` from `addr`; if `start`==`, set START
static uint8_t i2c_startr(uint8_t addr, uint16_t nbytes, uint8_t start){ static uint8_t i2c_startr(uint8_t addr, uint16_t nbytes, uint8_t start){
uint32_t cr2 = addr | I2C_CR2_RD_WRN; uint32_t cr2 = addr | I2C_CR2_RD_WRN;
if(nbytes > 255){ if(nbytes > 255) cr2 |= I2C_CR2_RELOAD | (0xff0000);
nbytes = 255; cr2 |= I2C_CR2_RELOAD; else cr2 |= I2C_CR2_AUTOEND | (nbytes << 16);
}else cr2 |= I2C_CR2_AUTOEND;
cr2 |= (nbytes << 16);
I2C1->CR2 = (start) ? cr2 | I2C_CR2_START : cr2; I2C1->CR2 = (start) ? cr2 | I2C_CR2_START : cr2;
return 1; return 1;
} }
@ -265,64 +252,64 @@ static uint8_t i2c_startr(uint8_t addr, uint16_t nbytes, uint8_t start){
* `data` should be an array with at least `nbytes` length * `data` should be an array with at least `nbytes` length
* @return 1 if all OK, 0 if NACK or no device found * @return 1 if all OK, 0 if NACK or no device found
*/ */
static uint8_t *read_i2cb(uint8_t addr, uint16_t nbytes, uint8_t busychk){ static uint8_t *i2c_readb(uint8_t addr, uint16_t nbytes){
if(busychk && !waitISRbit(I2C_ISR_BUSY, 0)) return NULL;
uint8_t start = 1; uint8_t start = 1;
uint8_t *bptr = I2Cbuf; uint8_t *bptr = I2Cbuf;
while(nbytes){ while(nbytes){
U("Read "); U(u2str(nbytes)); USND(" bytes"); //U("Read "); U(u2str(nbytes)); USND(" bytes");
if(!i2c_startr(addr, nbytes, start)) return NULL; if(!i2c_startr(addr, nbytes, start)) return NULL;
if(nbytes < 256){ if(nbytes < 256){
for(int i = 0; i < nbytes; ++i){ for(int i = 0; i < nbytes; ++i){
if(!waitISRbit(I2C_ISR_RXNE, 1)) goto tmout; if(!waitISRbit(I2C_ISR_RXNE, 1)) goto tmout;
*bptr++ = I2C1->RXDR; *bptr++ = I2C1->RXDR;
} }
while(waitISRbit(I2C_ISR_RXNE, 1)){ /*while(waitISRbit(I2C_ISR_RXNE, 1)){
U("OOOps! We have another byte: "); USND(uhex2str(I2C1->RXDR)); U("OOOps! We have another byte: "); USND(uhex2str(I2C1->RXDR));
} }*/
break; break;
}else while(!(I2C1->ISR & I2C_ISR_TCR)){ // until first part read }else while(!(I2C1->ISR & I2C_ISR_TCR)){ // until first part read
if(!waitISRbit(I2C_ISR_RXNE, 1)) goto tmout; if(!waitISRbit(I2C_ISR_RXNE, 1)) goto tmout;
*bptr++ = I2C1->RXDR; *bptr++ = I2C1->RXDR;
} }
USND("next"); //USND("next");
nbytes -= 255; nbytes -= 255;
start = 0; start = 0;
} }
return I2Cbuf; return I2Cbuf;
tmout: tmout:
USND("read I2C: Timeout"); //USND("read I2C: Timeout");
return NULL; return NULL;
} }
uint8_t *read_i2c(uint8_t addr, uint16_t nbytes){ uint8_t *i2c_read(uint8_t addr, uint16_t nbytes){
if(isI2Cbusy()) return 0; if(isI2Cbusy() || !waitISRbit(I2C_ISR_BUSY, 0)) return 0;
return read_i2cb(addr, nbytes, 1); return i2c_readb(addr, nbytes);
} }
static uint8_t dmard(uint8_t addr, uint16_t nbytes, uint8_t stop){ static uint8_t dmard(uint8_t addr, uint16_t nbytes){
if(nbytes < 1 || nbytes > I2C_BUFSIZE) return 0; if(nbytes < 1 || nbytes > I2C_BUFSIZE) return 0;
if(isI2Cbusy()) return 0;
i2cDMAsetup(0, nbytes); i2cDMAsetup(0, nbytes);
goterr = 0; goterr = 0;
i2c_got_DMA = 0; i2c_got_DMA = 0;
if(!i2c_startr(addr, nbytes, stop)) return 0;
dma_remain = nbytes > 255 ? nbytes - 255 : 0; // remainder after first read finish
(void) I2C1->RXDR; // avoid wrong first byte (void) I2C1->RXDR; // avoid wrong first byte
DMA1_Channel7->CCR = DMARXCCR | DMA_CCR_EN; // init DMA before START sequence DMA1_Channel7->CCR = DMARXCCR | DMA_CCR_EN; // init DMA before START sequence
if(!i2c_startr(addr, nbytes, 1)) return 0;
dma_remain = nbytes > 255 ? nbytes - 255 : 0; // remainder after first read finish
I2Cbusy = 1; I2Cbusy = 1;
return 1; return 1;
} }
uint8_t read_i2c_dma(uint8_t addr, uint16_t nbytes){ uint8_t i2c_read_dma(uint8_t addr, uint16_t nbytes){
uint8_t got = dmard(addr, nbytes, 1); if(isI2Cbusy() || !waitISRbit(I2C_ISR_BUSY, 0)) return 0;
uint8_t got = dmard(addr, nbytes);
if(got) dma16bit = 0; if(got) dma16bit = 0;
return got; return got;
} }
uint8_t read_i2c_dma16(uint8_t addr, uint16_t nwords){ uint8_t i2c_read_dma16(uint8_t addr, uint16_t nwords){
if(nwords > I2C_BUFSIZE/2) return 0; // what if `nwords` is very large? we should check it if(nwords > I2C_BUFSIZE/2) return 0; // what if `nwords` is very large? we should check it
uint8_t got = dmard(addr, nwords<<1, 1); if(isI2Cbusy() || !waitISRbit(I2C_ISR_BUSY, 0)) return 0;
uint8_t got = dmard(addr, nwords<<1);
if(got) dma16bit = 1; if(got) dma16bit = 1;
return got; return got;
} }
@ -334,30 +321,29 @@ static void swapbytes(uint16_t *data, uint16_t datalen){
} }
// read register reg // read register reg
uint8_t *read_i2c_reg(uint8_t addr, uint8_t reg, uint16_t nbytes, uint8_t isdma){ uint8_t *i2c_read_reg(uint8_t addr, uint8_t reg, uint16_t nbytes, uint8_t isdma){
if(isI2Cbusy()) return NULL; if(isI2Cbusy() || !waitISRbit(I2C_ISR_BUSY, 0)) return NULL;
if(!write_i2cs(addr, &reg, 1, 0)) return NULL; if(!i2c_writes(addr, &reg, 1, 0)) return NULL;
if(isdma){ if(isdma){
if(dmard(addr, nbytes, 0)){ dma16bit = 0; return I2Cbuf;} // for DMA we just return something non-null to check OK if(dmard(addr, nbytes)){ dma16bit = 0; return I2Cbuf;} // for DMA we just return something non-null to check OK
return NULL; return NULL;
} }
return read_i2cb(addr, nbytes, 0); return i2c_readb(addr, nbytes);
} }
// read 16bit register reg // read 16bit register reg
uint16_t *read_i2c_reg16(uint8_t addr, uint16_t reg16, uint16_t nwords, uint8_t isdma){ uint16_t *i2c_read_reg16(uint8_t addr, uint16_t reg16, uint16_t nwords, uint8_t isdma){
if(isI2Cbusy() || nwords < 1 || nwords > I2C_BUFSIZE/2) return 0; if(isI2Cbusy() || !waitISRbit(I2C_ISR_BUSY, 0) || nwords < 1 || nwords > I2C_BUFSIZE/2) return 0;
if(bigendian) reg16 = __REV16(reg16); if(bigendian) reg16 = __REV16(reg16);
if(!write_i2cs(addr, (uint8_t*)&reg16, 2, 0)) return NULL; if(!i2c_writes(addr, (uint8_t*)&reg16, 2, 0)) return NULL;
if(isdma){ if(isdma){
if(dmard(addr, nwords<<1, 0)){ dma16bit = 1; return (uint16_t*)I2Cbuf; } if(dmard(addr, nwords<<1)){ dma16bit = 1; return (uint16_t*)I2Cbuf; }
return NULL; return NULL;
} }
if(!read_i2cb(addr, nwords*2, 0)) return NULL; if(!i2c_readb(addr, nwords<<1)) return NULL;
uint16_t *buf = (uint16_t*)I2Cbuf; if(bigendian) swapbytes((uint16_t*)I2Cbuf, nwords);
if(bigendian) swapbytes(buf, nwords); return (uint16_t*)I2Cbuf;
return buf;
} }
void i2c_init_scan_mode(){ void i2c_init_scan_mode(){
@ -376,7 +362,7 @@ int i2c_scan_next_addr(uint8_t *addr){
i2c_scanmode = 0; i2c_scanmode = 0;
return 0; return 0;
} }
if(!read_i2c((i2caddr++)<<1, 1)) return 0; if(!i2c_read((i2caddr++)<<1, 1)) return 0;
return 1; return 1;
} }
@ -389,31 +375,30 @@ void i2c_bufdudump(){
if(i2cbuflen < 1) return; if(i2cbuflen < 1) return;
USND("I2C buffer:"); USND("I2C buffer:");
if(dma16bit) hexdump16(USB_sendstr, (uint16_t*)I2Cbuf, i2cbuflen); if(dma16bit) hexdump16(USB_sendstr, (uint16_t*)I2Cbuf, i2cbuflen);
hexdump(USB_sendstr, I2Cbuf, i2cbuflen); else hexdump(USB_sendstr, I2Cbuf, i2cbuflen);
} }
// get DMA buffer with conversion to little-endian (if transfer was for 16-bit) // get DMA buffer with conversion to little-endian (if transfer was for 16-bit)
uint8_t *i2cdma_getbuf(uint16_t *len){ uint8_t *i2c_dma_getbuf(uint16_t *len){
if(!i2c_got_DMA || i2cbuflen < 1) return NULL; if(!i2c_got_DMA || i2cbuflen < 1) return NULL;
i2c_got_DMA = 0; i2c_got_DMA = 0;
if(dma16bit){ if(dma16bit){
i2cbuflen >>= 1; // for hexdump16 - now buffer have uint16_t! i2cbuflen >>= 1; // for hexdump16 - now buffer have uint16_t!
uint16_t *b = (uint16_t*)I2Cbuf; if(bigendian) swapbytes((uint16_t*)I2Cbuf, i2cbuflen);
if(bigendian){
for(int i = 0; i < i2cbuflen; ++i) b[i] = __REV(b[i]);
}
} }
if(len) *len = i2cbuflen; if(len) *len = i2cbuflen;
return I2Cbuf; return I2Cbuf;
} }
int i2cdma_haderr(){ int i2c_dma_haderr(){
int r = goterr; int r = goterr;
goterr = 0; goterr = 0;
return r; return r;
} }
void endianness(uint8_t isbig){ int i2c_busy(){ return I2Cbusy;}
void i2c_endianness(uint8_t isbig){
bigendian = isbig; bigendian = isbig;
} }

View File

@ -38,20 +38,22 @@ extern volatile uint8_t i2c_scanmode;
#define I2C_TIMEOUT (5) #define I2C_TIMEOUT (5)
void i2c_setup(i2c_speed_t speed); void i2c_setup(i2c_speed_t speed);
uint8_t *read_i2c(uint8_t addr, uint16_t nbytes); int i2c_busy();
uint8_t *read_i2c_reg(uint8_t addr, uint8_t reg, uint16_t nbytes, uint8_t isdma);
uint16_t *read_i2c_reg16(uint8_t addr, uint16_t reg16, uint16_t nbytes, uint8_t isdma);
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint16_t nbytes);
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint16_t nbytes); uint8_t *i2c_read(uint8_t addr, uint16_t nbytes);
uint8_t write_i2c_dma16(uint8_t addr, uint16_t *data, uint16_t nwords); uint8_t i2c_read_dma(uint8_t addr, uint16_t nbytes);
uint8_t read_i2c_dma(uint8_t addr, uint16_t nbytes); uint8_t i2c_read_dma16(uint8_t addr, uint16_t nwords);
uint8_t *i2c_read_reg(uint8_t addr, uint8_t reg, uint16_t nbytes, uint8_t isdma);
uint16_t *i2c_read_reg16(uint8_t addr, uint16_t reg16, uint16_t nbytes, uint8_t isdma);
uint8_t i2c_write(uint8_t addr, uint8_t *data, uint8_t nbytes);
uint8_t i2c_write_dma(uint8_t addr, uint8_t *data, uint8_t nbytes);
uint8_t i2c_write_dma16(uint8_t addr, uint16_t *data, uint8_t nwords);
void i2c_bufdudump(); void i2c_bufdudump();
int i2cdma_haderr(); int i2c_dma_haderr();
uint8_t *i2cdma_getbuf(uint16_t *len); uint8_t *i2c_dma_getbuf(uint16_t *len);
uint8_t read_i2c_dma16(uint8_t addr, uint16_t nwords); void i2c_endianness(uint8_t isbig);
void endianness(uint8_t isbig);
int i2c_getwords(uint16_t *buf, int bufsz); int i2c_getwords(uint16_t *buf, int bufsz);
void i2c_init_scan_mode(); void i2c_init_scan_mode();

Binary file not shown.

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 17.0.1, 2025-09-18T23:52:40. --> <!-- Written by QtCreator 17.0.1, 2025-09-19T20:47:53. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>

View File

@ -53,7 +53,7 @@ int main(void){
if(l < 0) USND("ERROR: USB buffer overflow or string was too long"); if(l < 0) USND("ERROR: USB buffer overflow or string was too long");
else if(l){ else if(l){
const char *ans = parse_cmd(inbuff); const char *ans = parse_cmd(inbuff);
if(ans) USND(ans); if(ans) U(ans);
} }
if(i2c_scanmode){ if(i2c_scanmode){
uint8_t addr; uint8_t addr;
@ -65,7 +65,7 @@ int main(void){
U(") - found device\n"); U(") - found device\n");
} }
} }
if(i2cdma_haderr()) USND("Error reading I2C using DMA"); if(i2c_dma_haderr()) USND("Error reading I2C using DMA");
if(i2cdma_getbuf(NULL)) i2c_bufdudump(); if(i2c_dma_getbuf(NULL)) i2c_bufdudump();
} }
} }

View File

@ -26,6 +26,7 @@
#define LOCBUFFSZ (32) #define LOCBUFFSZ (32)
// local buffer for I2C data to send // local buffer for I2C data to send
static uint8_t locBuffer[LOCBUFFSZ]; static uint8_t locBuffer[LOCBUFFSZ];
static uint8_t I2Caddress = 0x33 << 1;
extern volatile uint32_t Tms; extern volatile uint32_t Tms;
static const char *OK = "OK\n"; static const char *OK = "OK\n";
@ -33,6 +34,7 @@ static const char *helpstring =
"https://github.com/eddyem/stm32samples/tree/master/F3:F303/I2C_scan build#" BUILD_NUMBER " @ " BUILD_DATE "\n" "https://github.com/eddyem/stm32samples/tree/master/F3:F303/I2C_scan build#" BUILD_NUMBER " @ " BUILD_DATE "\n"
"i0..3 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!)\n" "i0..3 - setup I2C with speed 10k, 100k, 400k, 1M or 2M (experimental!)\n"
"B - switch to big-endian format for 16-bit registers\n" "B - switch to big-endian format for 16-bit registers\n"
"G - get busy state\n"
"Ia addr - set I2C address\n" "Ia addr - set I2C address\n"
"Ig - dump content of I2Cbuf\n" "Ig - dump content of I2Cbuf\n"
"Iw bytes - send bytes (hex/dec/oct/bin) to I2C\n" "Iw bytes - send bytes (hex/dec/oct/bin) to I2C\n"
@ -59,7 +61,6 @@ TRUE_INLINE const char *setupI2C(char *buf){
return OK; return OK;
} }
static uint8_t I2Caddress = 0;
TRUE_INLINE const char *saI2C(const char *buf){ TRUE_INLINE const char *saI2C(const char *buf){
uint32_t addr; uint32_t addr;
U("saI2C: '"); U(buf); U("'\n"); U("saI2C: '"); U(buf); U("'\n");
@ -98,24 +99,24 @@ static void rdI2C(const char *buf, int is16, int dmaflag){
if(noreg){ // don't write register if(noreg){ // don't write register
if(dmaflag){ if(dmaflag){
U("Try to read using DMA .. "); U("Try to read using DMA .. ");
if(!read_i2c_dma(I2Caddress, N)) U(erd); if(!i2c_read_dma(I2Caddress, N)) U(erd);
else U(OK); else U(OK);
return; return;
}else{ }else{
USND("Simple read:"); USND("Simple read:");
if(!(b8 = read_i2c(I2Caddress, N))){ if(!(b8 = i2c_read(I2Caddress, N))){
U(erd); U(erd);
return; return;
} }
} }
}else{ }else{
if(is16){ if(is16){
if(!(b16 = read_i2c_reg16(I2Caddress, reg, N, dmaflag))){ if(!(b16 = i2c_read_reg16(I2Caddress, reg, N, dmaflag))){
U(erd); U(erd);
return; return;
} }
}else{ }else{
if(!(b8 = read_i2c_reg(I2Caddress, reg, N, dmaflag))){ if(!(b8 = i2c_read_reg(I2Caddress, reg, N, dmaflag))){
U(erd); U(erd);
return; return;
} }
@ -142,8 +143,8 @@ TRUE_INLINE uint16_t readNnumbers(const char *buf){
static const char *wrI2C(const char *buf, int isdma){ static const char *wrI2C(const char *buf, int isdma){
uint16_t N = readNnumbers(buf); uint16_t N = readNnumbers(buf);
if(N == 0) return "Enter at least one number\n"; if(N == 0) return "Enter at least one number\n";
int result = isdma ? write_i2c_dma(I2Caddress, locBuffer, N) : int result = isdma ? i2c_write_dma(I2Caddress, locBuffer, N) :
write_i2c(I2Caddress, locBuffer, N); i2c_write(I2Caddress, locBuffer, N);
if(!result) return "Error writing I2C\n"; if(!result) return "Error writing I2C\n";
return OK; return OK;
} }
@ -185,11 +186,14 @@ const char *parse_cmd(char *buf){
switch(*buf){ switch(*buf){
case 'i': return setupI2C(NULL); // current settings case 'i': return setupI2C(NULL); // current settings
case 'B': case 'B':
endianness(1); i2c_endianness(1);
return OK; return OK;
break; break;
case 'G':
U("I2Cbusy="); USB_putbyte('0' + i2c_busy()); newline();
break;
case 'L': case 'L':
endianness(0); i2c_endianness(0);
return OK; return OK;
break; break;
case 'T': case 'T':

View File

@ -15,6 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <string.h>
#include "ringbuffer.h" #include "ringbuffer.h"
static int datalen(ringbuffer *b){ static int datalen(ringbuffer *b){
@ -58,10 +60,11 @@ int RB_hasbyte(ringbuffer *b, uint8_t byte){
return ret; return ret;
} }
/*
// poor memcpy // poor memcpy
static void mcpy(uint8_t *targ, const uint8_t *src, int l){ static void mcpy(uint8_t *targ, const uint8_t *src, int l){
while(l--) *targ++ = *src++; while(l--) *targ++ = *src++;
} }*/
// increment head or tail // increment head or tail
TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){ TRUE_INLINE void incr(ringbuffer *b, volatile int *what, int n){
@ -76,9 +79,9 @@ static int read(ringbuffer *b, uint8_t *s, int len){
int _1st = b->length - b->head; int _1st = b->length - b->head;
if(_1st > l) _1st = l; if(_1st > l) _1st = l;
if(_1st > len) _1st = len; if(_1st > len) _1st = len;
mcpy(s, b->data + b->head, _1st); memcpy(s, b->data + b->head, _1st);
if(_1st < len && l > _1st){ if(_1st < len && l > _1st){
mcpy(s+_1st, b->data, l - _1st); memcpy(s+_1st, b->data, l - _1st);
incr(b, &b->head, l); incr(b, &b->head, l);
return l; return l;
} }
@ -132,9 +135,9 @@ static int write(ringbuffer *b, const uint8_t *str, int l){
if(l > r || !l) return 0; if(l > r || !l) return 0;
int _1st = b->length - b->tail; int _1st = b->length - b->tail;
if(_1st > l) _1st = l; if(_1st > l) _1st = l;
mcpy(b->data + b->tail, str, _1st); memcpy(b->data + b->tail, str, _1st);
if(_1st < l){ // add another piece from start if(_1st < l){ // add another piece from start
mcpy(b->data, str+_1st, l-_1st); memcpy(b->data, str+_1st, l-_1st);
} }
incr(b, &b->tail, l); incr(b, &b->tail, l);
return l; return l;

View File

@ -1,2 +1,2 @@
#define BUILD_NUMBER "136" #define BUILD_NUMBER "152"
#define BUILD_DATE "2025-09-18" #define BUILD_DATE "2025-09-19"