My working in progress - Porting MP to STM32F4xx

500 views
Skip to first unread message

Leonardo Garberoglio

unread,
May 1, 2015, 3:05:42 PM5/1/15
to uavdevb...@googlegroups.com
Hello team!

I want to share some of my work (and Robert work, of course) about porting MP to a new uC, the STM32F4xx.

We are working on this branch: https://code.google.com/p/gentlenav/source/browse/#svn%2Fbranches%2FMatrixPilot_nucleo
It's called that becous we are working on a Nucleo board as a development hardware (http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260320)
I'm using a STM32F411 but all code is compatible with F401 beouse I don't use extra memory.

PART 1 - Radio In
I started working on Radio In driver. I just consider PPM signal. We would like to avoid parallel software suport. For those people who don't have PPM output from their receiver we could add some simple hardware PPM encoder and enter to the uC with just 1 wire and 1 IC.
First I made a System Workbench project (ST free IDE for STM32 uC) and start to write code following MP radioIn.c functions, but working outside the MatrixPilot_Nucleo project. This way I was just to worrie about PPM decode and not other things of the rest of the MP project. I hope you can understand what I mean.
Once the driver was warking I've copy each functions to MatrixPilot_Nucleo project and test it with the rest of the project.
So, now, there is a SystemWorkbench workspace located on MatrixPilot_Nucleo branch called SystemWorkbench_WS. There is a System Workbench project called RC_Input_HAL01. This project configure timer's Input Capture, IC interrupt service routine and UART6 and mesure the with of one Rx channel connected to PA0.

I will write other parts on next posts.
Any question and sugestion are welcome!

BTW: Sorry by my english, I'm thinking on starting an english course next month....

Peter Hollands

unread,
May 1, 2015, 5:06:30 PM5/1/15
to uavdevb...@googlegroups.com
Hi Leonardo,

Thank you very much for the interesting update.

I was able to understand your English just fine.

Best wishes, Pete


--
You received this message because you are subscribed to the Google Groups "uavdevboard-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to uavdevboard-d...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Leonardo Garberoglio

unread,
May 1, 2015, 9:44:24 PM5/1/15
to uavdevb...@googlegroups.com
Thank Pete!

PART 2 - ServoOut
The second part I was working was on servo output. I'm using 6 timer chanel (each timer has 4 chanel) configured as PWM. This way all PWM stuff is solved on uC internal hardware and there is no need to load the CPU with PWM computation. I write a simple program to test it. I don't commit this example, becouse each project take 22megabyte becouse I can't figure out how to config shared HAL library for all project on workspace. I have to say that ST don't have a good IDE. System Workbench is new on ST and they are given support, but it is not ready.
when i was working on this topic I start to mess up my servos and Rx wires so I start to design a shield board to plug on nucleo board. I have a can make 2 layer board (with no PTH) relatively easy. So I made this board:


The mpu6000 was soldered by hand, with a heat gun and muh pasience!!!

Next I port servoOut code to matrixpilot_nucleo and test the group, radioIn and servoOut. I made a video:

https://www.youtube.com/watch?v=5-z1j77qZd8

there is a litle delay between Tx command and servo response, but I think it was becouse we don't have a heartbeat on MP_Nucleo and there is a freertos around the code that I have to study. The frame of the project was writing by Robert and now I'm trying to add driver's.

On next post I will show you my mpu6000 tests.


Robert Dickenson

unread,
May 2, 2015, 1:54:04 AM5/2/15
to uavdevb...@googlegroups.com
impressive handiwork Leo, and great to see your amazing progress!

i presume the generated HAL files are all the same? in which case you could consider archiving them up in a single instance and reference it for download/copy from a single set source/library. i wouldn't bother fighting with the development tool for too long..

i'm still interested in steering away from those HAL libraries...

Leonardo Garberoglio

unread,
May 2, 2015, 2:22:43 PM5/2/15
to uavdevb...@googlegroups.com
Thank Robert!

generated HAL file are similar for each project. But all project have same HAL driver's. So I have to add one HAL driver instanse and reference all project to this lib. But I don't know how to do it yet.... I'm trying right now.

Well I would like to show you my last progress.
I start to use SPI to read/write MPU6000 register.
I've started by reading Who am I register. Acording with Register Maps it is Reg 117 (0x75) and the contents will be 104 (0x68). I've started with 8bit mode and 667KHz as my SPI configuration. I've some problems with HAL functions. The documentation about them are very poor and there is no much examples around the web. But with a couple of hour of work I've able to read register.
This is the proof!:


On yellow there is CLK and on cyan there is MISO data. As you can see I have 01101000 -> 104!!!

Before I can read a register, I've started to write mpuWriteReg16 function and trying to read a datat register.
I've learnd a lot of SPI bus becouse I've never used before as a comunication bus (I've used to play with an OSD).
I've some problems writing registers so I think on implement a writing and reading back register to be sure that it is well configured.
I've workd to change to 16 bits mode and I have some problems with it yet. It seems that the order of 8 bit data (expected for HAL functions) are swaped.
I could config Interrupt on raw data ready and catch it on uC ISR. On it I just read Temperature data to clear MPU interrupt flag. This way I've obtain a 200Hz signal. I don't figure out how to transfor that 200Hz on heartbeat for MP yet.

Finally my most significant goal was change SPI freq to 10MHZ after mpu init to read data as fast as it posible (I have to try 15 or more MHz).
I have to investigate a lot of "dead" times. I see 7useg between Interrupt signal and CLK pulse coming out from SPI. HAL driver for ISR is a mess of code, there is 3 function calling to get my code runing...

Right now I'm working on separate driver library and use just a copy of them on a shared library for all project of workspace and starting reading gyro and accel data on the most efective/fastest way.

after that I hope I can undesrtand heartbeat and where do the code has to be place for each task on MP "firmware frame".

BR!

Leonardo Garberoglio

unread,
May 2, 2015, 5:52:30 PM5/2/15
to uavdevb...@googlegroups.com
and the time to read Accelerometer data has come...
I made a simple change on MPU-INT code and now I'm able to read accel, temp and gyro data.
Here is a video showing Accel data:

https://youtu.be/-mTO_K5-pIo

Finally I could configure HAL driver as external library and link project to them. So I will fill my new workspace with testing project code and will commit them.

Now is time to work on interrupt (instead of blocking) receiving code.

BR!

Tom Pittenger

unread,
May 2, 2015, 7:41:06 PM5/2/15
to uavdevb...@googlegroups.com

To make sure you're not hogging up the cpu for this one spi transaction, make sure to take advantage of DMA and spi Rx ISRs.

--

Leonardo Garberoglio

unread,
May 2, 2015, 10:50:12 PM5/2/15
to uavdevb...@googlegroups.com
"your wishes are orders" :-)

I decide to go directly to DMA becouse I think that it will be more interesting. And after 4 hour I have a working code with DMA receive. Hal driver makes my a litle difficult the task. I wanted to config one DMA stream to Tx (1 address byte and 15 dummys 0's) and another stream for Rx and 16 byte buffer input. But I can't make it. I have to transmit address first and then enable DMA Receive, my code is something like this:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    uint8_t addr;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
    addr=0x3B|0x80;
//    data[0]=0x3B|0x80;
    HAL_SPI_Transmit(&hspi2, &addr, 1, 10);
    HAL_SPI_Receive_DMA(&hspi2, data, 16);
//    HAL_SPI_TransmitReceive_DMA(&hspi2, &addr, data, 17);
}


and on Rx comlete ISR:

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{

    int16_t tmp=0;
    tmp=(data[6]<<8) | data[7];
    tempC = (double)(tmp)/340.0 + 36.53;
    X_accel = (int16_t)((data[0]<<8) | data[1])/16384.0;
    Y_accel = (int16_t)((data[2]<<8) | data[3])/16384.0;
    Z_accel = (int16_t)((data[4]<<8) | data[5])/16384.0;
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
}


here is a picture of DMA transfers:




I've read a lot of times people that rewrite HAL/Cube driver by their owns, I consider that as a future step, right now CubeMX is a usefull tool to initialization peripheral code...

BR!

Leonardo Garberoglio

unread,
May 9, 2015, 6:52:33 PM5/9/15
to uavdevb...@googlegroups.com
PART IV: GPS

I have a ublox-neo-6m from hobbyking (http://hobbyking.com/hobbyking/store/__31135__NEO_6M_GPS_Module.html) and start to experiment with it.
The first thing I have to do is to make a long cable (50cm) with connectors. I use it for put the module outside, on my window and connect to Nucleo shield on my desk. Next I have to download and install U-center (http://www.hobbyking.com/hobbyking/store/uploads/560377399X1095337X25.zip), becouse the GPS is configured to output ubx + NMEA strem over the uart, and most soft (MP included) expect NMEA msg.
It was a litle hard to get GPS configured and saved data into its eeprom.
Then I start to write some code. My original idea was ask for an char with interrupt, and on RX ISR transmit the receivd char to another UART (uart 6). Uart 6 is connected to a PC trough a TTL232-USB converter.
I made a project calld HAL_GPS_01 and put it on Nucleo brach.
main.c have something like this.
  while (1)
  {
      if(HAL_UART_GetState(&huart1) == HAL_UART_STATE_READY)
      {
          HAL_UART_Receive_IT(&huart1,&data,1);
      }
  }

uart1 is configured at 38400 bps.

Rx ISR is like this:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart6, &data, 1,10);
}


So, with this code I expect tha my Nucleo board function like a uart to uart bridge.
The result:

https://www.youtube.com/watch?v=DnocNiYSN9U

So it seems that read a gps with uart with STM32 is easy!




El viernes, 1 de mayo de 2015, 16:05:42 (UTC-3), Leonardo Garberoglio escribió:

Leonardo Garberoglio

unread,
May 9, 2015, 7:08:54 PM5/9/15
to uavdevb...@googlegroups.com
PART V: GPS Parser

Well, once I had nucleo and gps connected by uart6 I start to work on make MP NMEA parser working with my stream.
It take a couple of hour to understand parser method (function pointers are a litle tricky to follow at first). when I finish I can see that libDCM was independent from libUDB and dsPIC. So it could work just as it is. I workd a litle including just the minum .c/.h files to my project and after comment some lines, change others I was able to parse the stream.
The starting point was this:
void __attribute__((__interrupt__, __no_auto_psv__)) _U1RXInterrupt(void)
{
    _U1RXIF = 0; // clear the interrupt
    indicate_loading_inter;
    interrupt_save_set_corcon;

    while (U1STAbits.URXDA)
    {
        uint8_t rxchar = U1RXREG;
#if (HILSIM_USB != 1)
        udb_gps_callback_received_byte(rxchar);
#endif // HILSIM_USB
    }
    U1STAbits.OERR = 0;
    interrupt_restore_corcon;
}


I understand that on each char receive, there is a udb_gps_callback_received_byte call. So my serialIO Rx ISR is:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    HAL_UART_Transmit(&huart6, &data, 1,10);
    udb_gps_callback_received_byte(data);
}

first I retransmit  the char to uart6 (for debug purpose) and then call the callback function. That's all!!!! once on call_back function, all the code is the same of MP...

I have to say, the code on MP is so well writed!!!!!

Here there is a picture with gpsViewer receiving stream from nucleo uart6 and on the back you can see ecplise with the project running and lat_gps, lon_gps and alt_gps from the NMEA parser of MP:




El viernes, 1 de mayo de 2015, 16:05:42 (UTC-3), Leonardo Garberoglio escribió:

Leonardo Garberoglio

unread,
May 9, 2015, 7:09:57 PM5/9/15
to uavdevb...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages