STM32L4 Core

Cores are the underlying magic that make the Arduino API possible
gato_
Posts: 16
Joined: Mon Apr 03, 2017 10:18 am

Re: STM32L4 Core

Post by gato_ » Fri Dec 15, 2017 11:27 am

Well, learnt how to debug properly with opencd and dbg :). I'm posting what I've found out so far.
First, I had to deactivate clock stretching, as the incomplete transaction was hanging the system. the executed code is this one:

Code: Select all

#include <Wire.h>
const int N=6;
byte buffer[N];
void setup() {
  for (int i=0;i<N;i++){buffer[i]=i+1;};
  Wire.begin();
  Wire1.begin(3);
  Wire1.onRequest(requestEvent); // register event
  Serial.begin(9600);
}
void loop() {
  ////////request
  Wire.requestFrom(3, N);
  for (int i=0;i<N;i++) {
    uint8_t c = Wire.read();
    Serial.print(c,HEX);Serial.print(" ");
  }
  Serial.println();
  delay(500);  
}
void requestEvent() {
  int s=Wire1.write(buffer,N); // respond with message of 6 bytes
}
Notice that I am using the same board, with Wire as master and Wire1 as slave. Slave is meant to respond with 6 bytes (1..6), but what is shown after the first iteration is 1 FF FF FF FF FF, meaning only one byte is transfered.
The following (sorry, handmade) diagrams reflect the analysis performed with gdb
Image
Image
Left side explains what is shown, what breakpoints have been set and what variables are watched. Right side shows the contents of the registers on each step.

First impressions:

-Why is events initialized with ADDRESS_NACK, DATA_NACK,...?
-Why is events not changing on ANY of the steps?
-Slave's ISR contains an overrun condition from the begining. This is going to trigger an error on step 7 (Why not before?)

So, after startup (step 0), the cycle 1..7 is being repeated. What can be seen is no problem arises from the slave's transmit data being unavailable, but rather, the transmision of data is abandoned after the first byte. An overrun error is triggered then, but I'm not sure that is the cause.
Last edited by gato_ on Fri Dec 15, 2017 11:55 am, edited 1 time in total.

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

Re: STM32L4 Core

Post by gato_ » Fri Dec 15, 2017 11:54 am

Nope. Cleared manually slave's flags OVR, NACKF and STOPF. The error_interrupt routine keeps executing, but there is no error catched. And still, the result is the same. So it must be the logic telling when to stop transmitting. I'll check that

aonsquared
Posts: 6
Joined: Tue Nov 14, 2017 10:41 am

Re: STM32L4 Core

Post by aonsquared » Mon Dec 18, 2017 10:38 am

Hi gato_,

Could you share how you turned your sketch into an eclipse project with openocd debugging? I'm using this core too.

regards,
Arthur

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

Re: STM32L4 Core

Post by gato_ » Tue Jan 09, 2018 10:47 am

I didn't. I used openOCD+GDB with the elf file

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

Re: STM32L4 Core

Post by GrumpyOldPizza » Wed Jan 10, 2018 1:21 pm

gato_ wrote:
Fri Dec 15, 2017 11:27 am
Well, learnt how to debug properly with opencd and dbg :). I'm posting what I've found out so far.
First, I had to deactivate clock stretching, as the incomplete transaction was hanging the system. the executed code is this one:
Clock stretching is needed. Otherwise the Wire1.onRequest() callback has no time to put in data.

Code: Select all

#include <Wire.h>
const int N=6;
byte buffer[N];
void setup() {
  for (int i=0;i<N;i++){buffer[i]=i+1;};
  Wire.begin();
  Wire1.begin(3);
  Wire1.onRequest(requestEvent); // register event
  Serial.begin(9600);
}
void loop() {
  ////////request
  Wire.requestFrom(3, N);
  for (int i=0;i<N;i++) {
    uint8_t c = Wire.read();
    Serial.print(c,HEX);Serial.print(" ");
  }
  Serial.println();
  delay(500);  
}
void requestEvent() {
  int s=Wire1.write(buffer,N); // respond with message of 6 bytes
}
I'll take a peek at that code. It's not any different to what I used to check out the code, except that I used a string ("the quick brown fox ...")

The only thing suspicious is the I2C address. The standard reserves the first few addresses (and the last). You can only use 8-239. Perhaps this is confusing the I2C slave peripheral.
First impressions:

-Why is events initialized with ADDRESS_NACK, DATA_NACK,...?
-Why is events not changing on ANY of the steps?
In the STM32L0 system layer "i2c->events" is used a as mask to filter events that you callback wants to see. Kind of rendundant. Dropped for STM32L0.
-Slave's ISR contains an overrun condition from the begining. This is going to trigger an error on step 7 (Why not before?)
That's because you disabled clock stretching.

MGeo
Posts: 6
Joined: Wed Feb 03, 2016 9:55 am

Re: STM32L4 Core

Post by MGeo » Sun Jan 21, 2018 3:01 pm

Hello,

Very nice work on this core, I'm impressed. I'm still working through the 15 pages of posts here and I've been studying the code to familiarize myself. I've been introduced to this core through the interesting Hackflight work here https://github.com/simondlevy/Hackfligh ... master/src

I'm interested in sliding a simple time-triggered deterministic scheduler under an STM32L4 based flight controller as a learning exercise. I'm wondering if (and searching if) there is a mechanism to insert a SysTick callback or handler in this core (similar to the discussion here viewtopic.php?t=2117)? I've been using a Nucleo-L432KC for my test. Apologies in advance if the answer is obvious, most of my background has been AVR and I'm still climbing the ARM/CMSIS learning curve.

I've played around this with on the ST HAL based core using HAL_SYSTICK_Callback() (from here viewtopic.php?t=2542). but I prefer the design philosophy behind this core relative to ST HAL.

Best Regards,
George

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

Re: STM32L4 Core

Post by GrumpyOldPizza » Mon Jan 22, 2018 3:30 pm

MGeo wrote:
Sun Jan 21, 2018 3:01 pm
Hello,

Very nice work on this core, I'm impressed. I'm still working through the 15 pages of posts here and I've been studying the code to familiarize myself. I've been introduced to this core through the interesting Hackflight work here https://github.com/simondlevy/Hackfligh ... master/src

I'm interested in sliding a simple time-triggered deterministic scheduler under an STM32L4 based flight controller as a learning exercise. I'm wondering if (and searching if) there is a mechanism to insert a SysTick callback or handler in this core (similar to the discussion here viewtopic.php?t=2117)? I've been using a Nucleo-L432KC for my test. Apologies in advance if the answer is obvious, most of my background has been AVR and I'm still climbing the ARM/CMSIS learning curve.

I've played around this with on the ST HAL based core using HAL_SYSTICK_Callback() (from here viewtopic.php?t=2542). but I prefer the design philosophy behind this core relative to ST HAL.

Best Regards,
George
Yes, there is ... But it's not part of Arduino class (yet):

Code: Select all

typedef struct _armv7m_timer_t armv7m_timer_t;

typedef void (*armv7m_timer_callback_t)(armv7m_timer_t *timer);

struct _armv7m_timer_t {
    armv7m_timer_t                   *next;
    armv7m_timer_t                   *previous;
    volatile armv7m_timer_callback_t callback;
    uint32_t                         remaining;
};

#define ARMV7M_TIMER_INIT(_callback,_timeout) { NULL, NULL, (_callback), (_timeout) }

extern void armv7m_timer_create(armv7m_timer_t *timer, armv7m_timer_callback_t callback);
extern bool armv7m_timer_start(armv7m_timer_t *timer, uint32_t timeout);
extern bool armv7m_timer_stop(armv7m_timer_t *timer);
For the STM32L0 code I am working on, this got put into a TimerMillis class (https://github.com/GrumpyOldPizza/Ardui ... erMillis.h)

In the latter source base there is also this here: https://github.com/GrumpyOldPizza/Ardui ... 6m_event.h

This, although not complete yet, would be interesting for a simple time triggered system. It allows in essence 254 levels of preemptive priorities. In the latter source base, the USB/MSC code that reads/writes the SDCARD/SFLASH is it's own event handler (which is nothing more than a run to completion thread). Also the LoRaWAN stack was put into another set of event handlers for a quick trial. STM32L0 is substantially SRAM challenged, so a full RTOS is out of the question there ... But still a nice idea ...

MGeo
Posts: 6
Joined: Wed Feb 03, 2016 9:55 am

Re: STM32L4 Core

Post by MGeo » Tue Jan 23, 2018 11:29 am

Ok thanks trying to follow you.

I see there is armv7m_systick_notify() in armv7m.c, would I be able to register my own callback via this function, with context = NULL? Or is it best to set up a Timer object for that?

Code: Select all

void armv7m_systick_notify(armv7m_systick_callback_t callback, void *context)
{
    armv7m_systick_control.callback = NULL;
    armv7m_systick_control.context = context;
    armv7m_systick_control.callback = callback;
}
Best Regards,
George

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

Re: STM32L4 Core

Post by GrumpyOldPizza » Tue Jan 23, 2018 4:52 pm

MGeo wrote:
Tue Jan 23, 2018 11:29 am
Ok thanks trying to follow you.

I see there is armv7m_systick_notify() in armv7m.c, would I be able to register my own callback via this function, with context = NULL? Or is it best to set up a Timer object for that?

Code: Select all

void armv7m_systick_notify(armv7m_systick_callback_t callback, void *context)
{
    armv7m_systick_control.callback = NULL;
    armv7m_systick_control.context = context;
    armv7m_systick_control.callback = callback;
}
Best Regards,
George
The best thing is to use the build-in timer facility. That one works already around all the tricky business (how do you stop a timer from an ISR with higher priority, or how do you start a time from the THREAD level without having consistency problems).

Post Reply