STM32L4 Core

Cores are the underlying magic that make the Arduino API possible
User avatar
GrumpyOldPizza
Posts: 184
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: STM32L4 Core

Post by GrumpyOldPizza » Tue Sep 19, 2017 2:08 pm

gato_ wrote:
Tue Sep 19, 2017 9:57 am
Actually, the onReceive() call doesn't seem to have any problems. And I am having some doubts about what happens with the onRequest() one. Are you using any environment to check the registers? if so, which one? what pins are employed for debugging? Thank you. Otherwise, the core is great
For debugging I am using gdb/stlink. Compile a sketch and then upload it via gdb/stlink.

I think with your discovery of _tx_active the code should perform mostly as all the other implementations do (whether that's good or bad, I don't know). There are only really 2 issues that needs to be addressed (again to be compatible). One is to send dummy data subsequence to a onRequest() callback if there is more data requested than buffered from the first onRequest() callback. And the other one is to send a NACK if the peer sends more data than can be buffered for a single onReceive() callback ... If you have your code setup so that those conditions are not hit, you should be fine.

IMHO the real issue is the API itself (AVR and SAMD cores). If you have a onRequest() callback, you need to stuff in all the data you think might be read, up to the buffer size (which is 32 bytes for AVR). The callback will not be called again. And worse, there is no way telling how many bytes had be transferred to the peer.

gato_
Posts: 15
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Tue Oct 24, 2017 8:35 am

curioser and curioser. And frustrating.
I have managed to make the requestFrom example work, under certain conditions:

-The slave device must be on before the master device AND a serial terminal must be open for the slave device. Under those conditions, the master (COM8) makes the request, and the slave (COM3) answers it
Image
-If the serial terminal of the slave is closed, then the master remains on MASTER_RECEIVE status (7) forever....
Image

So... the usb serial interrupts affect/ modify the I2C interruptions?

The library is great, but without an I2C slave mode, it just is not usable... I am not sure on how to continue with this

User avatar
GrumpyOldPizza
Posts: 184
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: STM32L4 Core

Post by GrumpyOldPizza » Tue Oct 24, 2017 3:07 pm

Did you sync to the latest code on github ? I just want to exclude the possibility where something is already fixed there, especially the USB Serial hanging.

gato_
Posts: 15
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Wed Oct 25, 2017 9:05 am

Well, it does show as the newest one in the boards manager. version 0.0.26

gato_
Posts: 15
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Wed Oct 25, 2017 9:40 am

tried not to even instantiate the serial object in the slave. it never answers the i2c request. Any interrupts that might not be initialized unless the serial object is called?
EDIT: okay, so just instantiating the object in the slave (Serial.begin()) does not fix things. It turns out that I inserted some print statements in the TwoWire::EventCallback funtion. Apparently, this is a delay type of problem. The time spent printing things at some particular moments give it enough time to finish other things...

zmemw16
Posts: 1489
Joined: Wed Jul 08, 2015 2:09 pm
Location: St Annes, Lancs,UK

Re: STM32L4 Core

Post by zmemw16 » Wed Oct 25, 2017 11:15 am

typical, i added prints to debug the problem and it works - truism :?:
:D

gato_
Posts: 15
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Wed Oct 25, 2017 11:30 am

Well, here is what I tried so far:

Inserted this to print statements int the EventCallback, I2C_EVENT_TRANSMIT_REQUEST case:

Code: Select all

if (events & I2C_EVENT_TRANSMIT_REQUEST) {
	    _tx_write = 0;

	    if(_requestCallback) {
		(*_requestCallback)();
	    }
	  for (int i=0;i<_tx_write;i++){Serial.print(_tx_data[i]);Serial.print(" ");}
	  Serial.println();
	    stm32l4_i2c_service(_i2c, &_tx_data[0], _tx_write);
		  Serial.println(_i2c->I2C->ISR&I2C_ISR_TXE);
	}
this works a few iterations, until (_i2c->I2C->ISR&I2C_ISR_TXE)=0.

Code: Select all

requestEvent()
1 2 3 4 5 6 
1
requestEvent()
1 2 3 4 5 6 
1
requestEvent()
1 2 3 4 5 6 
0
Obviously, I tried inserting a while(!(_i2c->I2C->ISR&I2C_ISR_TXE)) after the service routine, but that does not work...

I tried to work out the library flow for the slave part, involving stm32l4_i2c_event_interrup, stm32l4_i2c_slave_address_match, and TwoWire::EventCallback. Here is a scheme (sorry if it is not very readable)
Image
Now, I am slightly confused about the flow, starting with the I2C_EVENT_ADDRESS_MATCH event, and ending.... where? (the I2C_EVENT_TRANSMIT_DONE never fires i the EventCallback, the only place where I can print anything). It would help a lot if you could explain the logic chain. For example, the I2C->TXDR=*(i2c_txdata)++ appers in two different branches, belonging to two different functions...

User avatar
GrumpyOldPizza
Posts: 184
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: STM32L4 Core

Post by GrumpyOldPizza » Wed Oct 25, 2017 12:41 pm

I really like the diagram ;-) Need to send me a bigger image of that ;-)

It's actually pretty trivial (apart from the bazillion I2C peripheral flags). The interrupt handler is a simple state machine:

I2C_STATE_READY
I2C_STATE_SLAVE_RECEIVE
I2C_STATE_SLAVE_TRANSMIT
I2C_STATE_MASTER_RESTART
I2C_STATE_MASTER_RECEIVE
I2C_STATE_MASTER_TRANSMIT

In I2C_STATE_READY a address match is detected. The code that handles this is in stm32l4_i2c_slave_address_match(), detecting what address, and in which direction the transfer is going. This triggers I2C_EVENT_TRANSMIT_REQUEST / I2C_EVENT_RECEIVE_REQUEST to the Wire layer to supply either data to be written, or a buffer where read data can be placed into. Anyway the state machine then switches to I2S_STATE_SLAVE_RECEIVE or I2S_STATE_TRANSMIT. For the receive part, the next ISR will either have new data (triggers a I2C_EVENT_RECEIVE_REQUEST is the buffer is full), or a I2C_EVENT_RECEIVE_DONE is a STOP or a RESTART condition is detected. I2C_STATE_MASTER_TRANSMIT is similar, except that first STOP/RESTART are detected ...

The system code has a weakness in that it requires always data to be present to be send, rather than to send dummy bytes if no more TX data is supplied.

The Wire code now simply handles I2C_EVENT_RECEIVE_DONE, I2C_EVENT_RECEIVE_REQUEST and I2C_EVENT_TRANSMIT_REQUEST to supply a read buffer, or transmit data in a write buffer. The code is not 100% compatible to Arduino Zero, as there only one chunk to read/write is allowed, and overflow on the read buffer is simply ignored (data dropped), and for write 0xff bytes are sent (so no segmenting ...)

User avatar
GrumpyOldPizza
Posts: 184
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: STM32L4 Core

Post by GrumpyOldPizza » Wed Oct 25, 2017 12:42 pm

gato_ wrote:
Wed Oct 25, 2017 9:05 am
Well, it does show as the newest one in the boards manager. version 0.0.26
The board manager is not up to date I believe. There is some experimental code on github.

gato_
Posts: 15
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Fri Nov 10, 2017 11:17 am

I finally had time to setup the debugging toolchain in eclipse. Any advice on how to efficiently transform a sketch into an eclipse project? That would be helpful

Post Reply