STM32F767ZI-NUCLEO odd behaviour Topic is solved

Report here problems in any of ChibiOS components. This forum is NOT for support.
rolanddixon
Posts: 26
Joined: Wed Feb 25, 2015 9:45 pm
Has thanked: 1 time
Been thanked: 2 times

STM32F767ZI-NUCLEO odd behaviour  Topic is solved

Postby rolanddixon » Tue Nov 01, 2016 12:47 pm

Hi All

I have been testing the double fpu performance on the STM32F767ZI with a few matrix multiplication operations. I decided to try the Eigen C++ library and have run into a problem that is stretching my knowledge of embedded startup routines, memory regions, linker scripts etc. So I was wondering if I could get some help with this.

I have to two code instances, one with the Eigen C++ operations and one without. The one without simple flashes an led in the main loop as show below (I still have the Eigen matrices declared as globals).

Code: Select all

#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "Eigen/Core"

using namespace Eigen;
#define MSIZE 7
typedef double tReal;

Eigen::Matrix<tReal,MSIZE,MSIZE> A;
Eigen::Matrix<tReal,MSIZE,MSIZE> B;
Eigen::Matrix<tReal,MSIZE,MSIZE> C;

char buf[128] = {0};

int main(void)
{
  halInit();
  chSysInit();

  sdStart(&SD3, NULL);

  while (true)
  {
     palToggleLine(LINE_LED1);
     chThdSleepMilliseconds(100);
  }
}


This results in a Reset_Handler that looks something like this in dissasembly (notice the lack of D cache initialisation):

Code: Select all

   Reset_Handler:
      cpsid   i
      ldr     r0, [pc, #220]  ; (0x2002f0 <endfiniloop+4>)
      msr     PSP, r0
      ldr     r0, [pc, #216]  ; (0x2002f4 <endfiniloop+8>)
      movw    r1, #60680      ; 0xed08
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      movw    r0, #0
      movt    r0, #49152      ; 0xc000
      movw    r1, #61236      ; 0xef34
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      dsb     sy
      isb     sy
      movw    r0, #0
      movt    r0, #240        ; 0xf0
      movw    r1, #60808      ; 0xed88
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      dsb     sy
      isb     sy
      mov.w   r0, #0
      vmsr    fpscr, r0
      movw    r1, #61244      ; 0xef3c
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      movs    r0, #6
      msr     CONTROL, r0
      isb     sy
      bl      0x202e50 <__core_init>
      bl      0x202070 <__early_init()>


Now, if I put some Eigen operations in, like this:

Code: Select all


#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "Eigen/Core"

using namespace Eigen;
#define MSIZE 7
typedef double tReal;

Eigen::Matrix<tReal,MSIZE,MSIZE> A;
Eigen::Matrix<tReal,MSIZE,MSIZE> B;
Eigen::Matrix<tReal,MSIZE,MSIZE> C;

char buf[128] = {0};

int main(void)
{
  halInit();
  chSysInit();

  sdStart(&SD3, NULL);

  while (true)
  {
     A.setRandom();
     B.setRandom();
     C = A*B;

     int sz = chsnprintf(buf, sizeof(buf), "%d, %d\r\n", (int)C(0,0));
     chnWrite(&SD3, (uint8_t*)buf, sz);

     palToggleLine(LINE_LED1);
     chThdSleepMilliseconds(100);
  }
}



The disassembly for the Reset_Handler looks like this:

Code: Select all

                 ; <UNDEFINED> instruction: 0xffffffff
                 ; <UNDEFINED> instruction: 0xffffffff
                 ; <UNDEFINED> instruction: 0xffffffff
      cpsid   i
      ldr     r0, [pc, #220]  ; (0x2002f0 <bloop+10>)
      msr     PSP, r0
      ldr     r0, [pc, #216]  ; (0x2002f4 <bloop+14>)
      movw    r1, #60680      ; 0xed08
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      movw    r0, #0
      movt    r0, #49152      ; 0xc000
      movw    r1, #61236      ; 0xef34
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      dsb     sy
      isb     sy
      movw    r0, #0
      movt    r0, #240        ; 0xf0
      movw    r1, #60808      ; 0xed88
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      dsb     sy
      isb     sy
      mov.w   r0, #0
      vmsr    fpscr, r0
      movw    r1, #61244      ; 0xef3c
      movt    r1, #57344      ; 0xe000
      str     r0, [r1, #0]
      movs    r0, #6
      msr     CONTROL, r0
      isb     sy
      bl      0x2072d0 <SCB_EnableDCache+80>
      bl      0x205650 <sd_lld_start+32>


And it all ends up in the SCB_EnableDCache function in a _unhandled_exception. This is weird because __core_init isn't called and that's where the SCB_EnableICache() and SCB_EnableDCache() functions seemed to be called from. __early_init() isn't called either, which is clearly called at line 245 in crt0_v7m.S.

This code has been built on the trunk svn repo and it was pulled today to make sure there hasn't been a fix put in place before I write this up. This is using the RT-STM32F767ZI-NUCLEO144 demo that has been adapted for c++. I've made the process stack size ridiculously large so I don't think it's an overflow. I've linked libm, libstdc++, turned off lto, turned it back on again, used -std=gnu++11 and nothing seems to work.

Any help would be greatly appreciated.

rolanddixon
Posts: 26
Joined: Wed Feb 25, 2015 9:45 pm
Has thanked: 1 time
Been thanked: 2 times

Re: STM32F767ZI-NUCLEO odd behaviour

Postby rolanddixon » Tue Nov 01, 2016 12:53 pm

It's probably worth mentioning that this all works on a STM32F4DISCOVERY and sorry if I have put the post in the wrong forum...

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F767ZI-NUCLEO odd behaviour

Postby Giovanni » Tue Nov 01, 2016 1:38 pm

Hi,

The destinations of those "bl" are messed up.

It is very strange, no idea about what it could be, try compiling with -O0 and see if you get the same problem.

You could also check addresses in the map file.

Giovanni

rolanddixon
Posts: 26
Joined: Wed Feb 25, 2015 9:45 pm
Has thanked: 1 time
Been thanked: 2 times

Re: STM32F767ZI-NUCLEO odd behaviour

Postby rolanddixon » Tue Nov 01, 2016 1:48 pm

Hi Giovanni. Yeah, the example above was compiled with the -O0 flag.

As far as the map file is concerned, that is above my level of understanding. Is there anything specific I should be looking for?

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F767ZI-NUCLEO odd behaviour

Postby Giovanni » Tue Nov 01, 2016 2:03 pm

Try posting it here in a code block, the .dmp would be useful too.

At very least I can give it a look.

Giovanni

rolanddixon
Posts: 26
Joined: Wed Feb 25, 2015 9:45 pm
Has thanked: 1 time
Been thanked: 2 times

Re: STM32F767ZI-NUCLEO odd behaviour

Postby rolanddixon » Tue Nov 01, 2016 2:55 pm

Thank you Giovanni. I am only able to post 60000 characters and, together, the .map and .dmp constitute a lot more than that, so I have zipped and attached them. Is that alright?
Attachments
ch.zip
(83.27 KiB) Downloaded 165 times

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F767ZI-NUCLEO odd behaviour

Postby Giovanni » Tue Nov 01, 2016 4:29 pm

Hi,

I suspect there is something wrong with handling of static initializers:

This is from an application without initializers:

Code: Select all

Idx Name          Size      VMA       LMA       File off  Algn
  0 .mstack       00000400  20000000  20000000  00020000  2**0
                  ALLOC
  1 .pstack       00000400  20000400  20000400  00020000  2**0
                  ALLOC
  2 .nocache      00000000  20000800  20000800  000184fc  2**2
                  CONTENTS
  3 .eth          00000000  20000800  20000800  000184fc  2**2
                  CONTENTS
  4 vectors       00000200  00200000  08000000  00008000  2**7
                  CONTENTS, ALLOC, LOAD, DATA
  5 .text         0000a8e4  00200200  08000200  00008200  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, CODE


This is from your application which contains an initializer, probably from the library:

Code: Select all

Idx Name          Size      VMA       LMA       File off  Algn
  0 .mstack       00000400  20000000  20000000  00060000  2**0
                  ALLOC
  1 .pstack       00008000  20000400  20000400  00060000  2**0
                  ALLOC
  2 .nocache      00000000  20008400  20008400  000509b0  2**2
                  CONTENTS
  3 .eth          00000000  20008400  20008400  000509b0  2**2
                  CONTENTS
  4 vectors       00000200  00200000  08000000  00010000  2**7
                  CONTENTS, ALLOC, LOAD, DATA
  5 xtors         00000008  00200200  08000200  00010200  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .text         00015d64  00200240  08000210  00010240  2**6
                  CONTENTS, ALLOC, LOAD, READONLY, CODE


Note how LMA and VMA of the .text segment are no more aligned because there is xtors in between, not sure if this is the cause but there is something strange going on, I need more time to study it.

If confirmed then it would be a bug, moving this thread in the bug reports section for handling.

Giovanni

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F767ZI-NUCLEO odd behaviour

Postby Giovanni » Tue Nov 01, 2016 4:32 pm

You could try removing the static constructor and see if it solves the problem, that would help confirm.

Giovanni

rolanddixon
Posts: 26
Joined: Wed Feb 25, 2015 9:45 pm
Has thanked: 1 time
Been thanked: 2 times

Re: STM32F767ZI-NUCLEO odd behaviour

Postby rolanddixon » Tue Nov 01, 2016 5:47 pm

Ah, so I am using Eigen purely for its static nature. I have written a tiny templated matrix class to test a static constructor. The main loop is the same as it was before:

Code: Select all

#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "Eigen/Core"
#include "time.h"
#include "stdlib.h"

using namespace Eigen;
#define MSIZE 7
typedef double tReal;

template <typename T, uint32_t ROWS, uint32_t COLS>
class Mat
{
public:
   enum {rows = ROWS, cols = COLS, byteSize = sizeof(T)*ROWS*COLS};
public:

   Mat() {}

   Mat(const Mat& rhs)
   {
      memcpy(&this->data[0][0], &rhs.data[0][0], byteSize);
   }

   void setRandom(const T min = (T)-100.0, const T max = (T)100.0)
   {
      srand(randCount++);
      for (unsigned int i = 0; i < ROWS; i++)
      {
         for (unsigned int j = 0; j < COLS; j++)
         {
            T val = (T)rand() / RAND_MAX;
            data[i][j] = min + val*(max - min);
         }
      }
   }

   ~Mat() {}

   inline Mat operator*(const Mat& rhs)
   {
      Mat C;
      multiply(rhs, C);
      return C;
   }

   void multiply(const Mat& rhs, Mat& res)
   {
      for (unsigned int i = 0; i < ROWS; i++)
      {
         for (unsigned int j = 0; j < rhs.cols; j++)
         {
            res.data[i][j] = 0;
            for (unsigned int k = 0; k < COLS; k++)
            {
               res.data[i][j] += this->data[i][k] * rhs.data[k][j];
            }
         }
      }
   }

   T& operator()(unsigned int i, unsigned int j)
    {
      return data[i][j];
    }

private:

   T data[ROWS][COLS];
   static uint32_t randCount;
};

template <typename T, uint32_t ROWS, uint32_t COLS>
uint32_t Mat<T, ROWS, COLS>::randCount = 0;

//Eigen::Matrix<tReal,MSIZE,MSIZE> A;
//Eigen::Matrix<tReal,MSIZE,MSIZE> B;
//Eigen::Matrix<tReal,MSIZE,MSIZE> C;
Mat<tReal,MSIZE,MSIZE> A;
Mat<tReal,MSIZE,MSIZE> B;
Mat<tReal,MSIZE,MSIZE> C;

char buf[128] = {0};

int main(void)
{
  halInit();
  chSysInit();

  sdStart(&SD3, NULL);

  while (true)
  {
     A.setRandom();
     B.setRandom();
     C = A*B;

     int sz = chsnprintf(buf, sizeof(buf), "%d\r\n", (int)C(0,0));
     chnWrite(&SD3, (uint8_t*)buf, sz);

     palToggleLine(LINE_LED1);
     chThdSleepMilliseconds(100);
  }
}


This compiles and works fine. Here is the relevant section from the .dmp:

Code: Select all

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .mstack       00000400  20000000  20000000  00040000  2**0
                  ALLOC
  1 .pstack       00008000  20000400  20000400  00040000  2**0
                  ALLOC
  2 .nocache      00000000  20008400  20008400  0003042c  2**2
                  CONTENTS
  3 .eth          00000000  20008400  20008400  0003042c  2**2
                  CONTENTS
  4 vectors       00000200  00200000  08000000  00010000  2**7
                  CONTENTS, ALLOC, LOAD, DATA
  5 xtors         00000004  00200200  08000200  00010200  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  6 .text         000057b4  00200210  08000210  00010210  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE


I have attached the .dmp and .map files as before.
Attachments
ch.zip
(33.56 KiB) Downloaded 164 times

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: STM32F767ZI-NUCLEO odd behaviour

Postby Giovanni » Tue Nov 01, 2016 8:50 pm

Hi,

I just committed a tentative fix, could you give it a try?

Giovanni


Return to “Bug Reports”

Who is online

Users browsing this forum: No registered users and 10 guests