STM32, Maple and Maple mini port to IDE 1.5.x

OK... We will see where the radio head thing gets us. Meanwhile I will start offering the minis for sale in the UK.

HiddenPilot:
So, when object "TestIt" of the class "myLib" is created, the file \hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\libmaple/gpio_f1.c is not running yet?
(the variable "init_RCC->APB2ENR" сonfirms this guess. Function gpio_init_all(void) is not runnig yet)

Alexey, this is very interesting ! I've been looking at the startup code in detail.

There seems to be a fundamental issue with the libmaple startup code, it relies on a constructor to initialise the board. But in C++ the order that constructors are called is not defined. This will cause strange behaviour like this. It might also explain the other strange startup problem.

Who know how to fix this problem in Arduino_STM32? :frowning:

It looks like the same issue could occur in Arduino Due for example. I'm not sure if there is a quick workaround, it might take some rework of the startup code to work correctly.

Edit: it seems this issue has existed in the AVR code since 2009 Calling delay() from within library class constructors halts execution [imported] · Issue #129 · arduino/Arduino · GitHub Although a fix was proposed, it was never implemented. I guess the bug was then ported to Due, and Maple :frowning:

One thing you can do is force a constructor calling order using the linker section name. You could use section names like 'init_sec_00', 'init_sec_01' etc .. and then use the linker script to sort the order of the functions addresses that get placed in it ctor function array list.

However this is a horrible work around. Any code that does peripheral initialization in a constructor is just wrong!

-rick

bobcousins:
Although a fix was proposed, it was never implemented. I guess the bug was then ported to Due, and Maple :frowning:

I dont think so. This is library UTFT works perfect at all Arduino based platforms.

UTFT::UTFT(byte model, int RS, int WR, int CS, int RST, int SER)
{ 
[.....................]
 if (display_transfer_mode!=1)
 {
 _set_direction_registers(display_transfer_mode);
 P_RS = portOutputRegister(digitalPinToPort(RS));
 B_RS = digitalPinToBitMask(RS);
 P_WR = portOutputRegister(digitalPinToPort(WR));
 B_WR = digitalPinToBitMask(WR);
 P_CS = portOutputRegister(digitalPinToPort(CS));
 B_CS = digitalPinToBitMask(CS);
 P_RST = portOutputRegister(digitalPinToPort(RST));
 B_RST = digitalPinToBitMask(RST);
 if (display_transfer_mode==LATCHED_16)

But at this port all variable init has been moved to separate function "void UTFT::initPins()"

some debugging info:

08005000 <__stm32_vector_table>:
$d():
 8005000: 00 50 00 20 51 52 00 08 a1 55 00 08 a5 55 00 08     .P. QR...U...U..
          top_of_stack    ;0000 Top of Stack = 20005000
          Reset_Handler   ;0004 Reset Handler = 08005250
          Reset_Handler   ;0008 NMI Handler = 080055a0
          Reset_Handler   ;000C Hard Fault Handler = 080055a4
  8005010: a9 55 00 08 ad 55 00 08 b1 55 00 08 01 56 00 08     .U...U...U...V..
        DCD     Reset_Handler   ;0010 MemManage Handler = 080055a8
        DCD     Reset_Handler   ;0014 Bus Fault Handler = 080055ac
        DCD     Reset_Handler   ;0018 Usage Fault Handler = 080055b0
        DCD     Reset_Handler   ;001C Reserved = 08005600
 8005020: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005030: 01 56 00 08 01 56 00 08 01 56 00 08 55 59 00 08     .V...V...V..UY..
 8005040: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005050: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005060: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005070: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005080: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 8005090: f9 5f 00 08 01 56 00 08 01 56 00 08 01 56 00 08     ._...V...V...V..
 80050a0: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 80050b0: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 80050c0: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 80050d0: 01 56 00 08 01 56 00 08 01 56 00 08 01 56 00 08     .V...V...V...V..
 80050e0: 01 56 00 08 01 56 00 08 01 56 00 08                 .V...V...V..
08005250 <__exc_reset>:
$t():
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:51

        .globl __start__
        .type __start__, %function
__start__:
        .fnstart
        ldr r1,=__msp_init
 8005250:	4901      	ldr	r1, [pc, #4]	; (8005258 <__exc_reset+0x8>)
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:52
        mov sp,r1
 8005252:	468d      	mov	sp, r1
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:53
        ldr r1,=start_c
 8005254:	4901      	ldr	r1, [pc, #4]	; (800525c <__exc_reset+0xc>)
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:54
        bx r1
 8005256:	4708      	bx	r1
$d():
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:51

        .globl __start__
        .type __start__, %function
__start__:
        .fnstart
        ldr r1,=__msp_init
 8005258:	20005000 	.word	0x20005000
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start.S:53
        mov sp,r1
        ldr r1,=start_c
 800525c:	08005261 	.word	0x08005261

08005260 <start_c>:
start_c():
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:63
    int *img_start;
};

extern char _lm_rom_img_cfgp;

void __attribute__((noreturn)) start_c(void) {
 8005260:	b508      	push	{r3, lr}
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:65
    struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp;
    int *src = img_cfg->img_start;
 8005262:	4b12      	ldr	r3, [pc, #72]	; (80052ac <start_c+0x4c>)
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:70
    int *dst = (int*)&__data_start__;
    int exit_code;

    /* Initialize .data, if necessary. */
    if (src != dst) {
 8005264:	4a12      	ldr	r2, [pc, #72]	; (80052b0 <start_c+0x50>)
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:65

extern char _lm_rom_img_cfgp;

void __attribute__((noreturn)) start_c(void) {
    struct rom_img_cfg *img_cfg = (struct rom_img_cfg*)&_lm_rom_img_cfgp;
    int *src = img_cfg->img_start;
 8005266:	6819      	ldr	r1, [r3, #0]
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:70
    int *dst = (int*)&__data_start__;
    int exit_code;

    /* Initialize .data, if necessary. */
    if (src != dst) {
 8005268:	4291      	cmp	r1, r2
 800526a:	d001      	beq.n	8005270 <start_c+0x10>
 800526c:	2300      	movs	r3, #0
 800526e:	e001      	b.n	8005274 <start_c+0x14>
 8005270:	4b10      	ldr	r3, [pc, #64]	; (80052b4 <start_c+0x54>)
 8005272:	e007      	b.n	8005284 <start_c+0x24>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:72 (discriminator 1)
        int *end = (int*)&__data_end__;
        while (dst < end) {
 8005274:	4810      	ldr	r0, [pc, #64]	; (80052b8 <start_c+0x58>)
 8005276:	18d4      	adds	r4, r2, r3
 8005278:	4284      	cmp	r4, r0
 800527a:	d2f9      	bcs.n	8005270 <start_c+0x10>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:73
            *dst++ = *src++;
 800527c:	58c8      	ldr	r0, [r1, r3]
 800527e:	50d0      	str	r0, [r2, r3]
 8005280:	3304      	adds	r3, #4
 8005282:	e7f7      	b.n	8005274 <start_c+0x14>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:79 (discriminator 1)
        }
    }

    /* Zero .bss. */
    dst = (int*)&__bss_start__;
    while (dst < (int*)&__bss_end__) {
 8005284:	4a0d      	ldr	r2, [pc, #52]	; (80052bc <start_c+0x5c>)
 8005286:	4293      	cmp	r3, r2
 8005288:	d203      	bcs.n	8005292 <start_c+0x32>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:80
        *dst++ = 0;
 800528a:	2200      	movs	r2, #0
 800528c:	f843 2b04 	str.w	r2, [r3], #4
 8005290:	e7f8      	b.n	8005284 <start_c+0x24>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:84
    }

    /* Run initializers. */
    __libc_init_array();
 8005292:	f002 fa09 	bl	80076a8 <__libc_init_array>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:87

    /* Jump to main. */
    exit_code = main(0, 0, 0);
 8005296:	2000      	movs	r0, #0
 8005298:	4601      	mov	r1, r0
 800529a:	4602      	mov	r2, r0
 800529c:	f000 fc2e 	bl	8005afc <main>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:88
    if (exit) {
 80052a0:	4b07      	ldr	r3, [pc, #28]	; (80052c0 <start_c+0x60>)
 80052a2:	b10b      	cbz	r3, 80052a8 <start_c+0x48>
C:\arduino-1.5.8\hardware\Arduino_STM32\STM32F1XX\variants\maple_mini\wirish/start_c.c:89
        exit(exit_code);
 80052a4:	f002 f9f0 	bl	8007688 <exit>
 80052a8:	e7fe      	b.n	80052a8 <start_c+0x48>
 80052aa:	bf00      	nop
 80052ac:	0800856c 	.word	0x0800856c
 80052b0:	20000c00 	.word	0x20000c00
 80052b4:	20001420 	.word	0x20001420
 80052b8:	20001420 	.word	0x20001420
 80052bc:	20001510 	.word	0x20001510
 80052c0:	08007689 	.word	0x08007689

080052c4 <_exit>:
_exit():
080076a8 <__libc_init_array>:
__libc_init_array():
 80076a8:	b570      	push	{r4, r5, r6, lr}
 80076aa:	4e0f      	ldr	r6, [pc, #60]	; (80076e8 <__libc_init_array+0x40>)
 80076ac:	4d0f      	ldr	r5, [pc, #60]	; (80076ec <__libc_init_array+0x44>)
 80076ae:	1b76      	subs	r6, r6, r5
 80076b0:	10b6      	asrs	r6, r6, #2
 80076b2:	d007      	beq.n	80076c4 <__libc_init_array+0x1c>
 80076b4:	3d04      	subs	r5, #4
 80076b6:	2400      	movs	r4, #0
 80076b8:	3401      	adds	r4, #1
 80076ba:	f855 3f04 	ldr.w	r3, [r5, #4]!
 80076be:	4798      	blx	r3
 80076c0:	42a6      	cmp	r6, r4
 80076c2:	d1f9      	bne.n	80076b8 <__libc_init_array+0x10>
 80076c4:	4e0a      	ldr	r6, [pc, #40]	; (80076f0 <__libc_init_array+0x48>)
 80076c6:	4d0b      	ldr	r5, [pc, #44]	; (80076f4 <__libc_init_array+0x4c>)
 80076c8:	f000 f93a 	bl	8007940 <_init>
 80076cc:	1b76      	subs	r6, r6, r5
 80076ce:	10b6      	asrs	r6, r6, #2
 80076d0:	d008      	beq.n	80076e4 <__libc_init_array+0x3c>
 80076d2:	3d04      	subs	r5, #4
 80076d4:	2400      	movs	r4, #0
 80076d6:	3401      	adds	r4, #1
 80076d8:	f855 3f04 	ldr.w	r3, [r5, #4]!
 80076dc:	4798      	blx	r3
 80076de:	42a6      	cmp	r6, r4
 80076e0:	d1f9      	bne.n	80076d6 <__libc_init_array+0x2e>
 80076e2:	bd70      	pop	{r4, r5, r6, pc}
 80076e4:	bd70      	pop	{r4, r5, r6, pc}
 80076e6:	bf00      	nop
 80076e8:	0800794c 	.word	0x0800794c
 80076ec:	0800794c 	.word	0x0800794c
 80076f0:	08007964 	.word	0x08007964
 80076f4:	0800794c 	.word	0x0800794c

sketch_dec29b.dasm.txt (433 KB)

@bobc

I didn't know Git had a revert feature. I've not had to use it before, (luckily)

I will do the revert and then double check that it fixes the issue, as it was rather tricky to test, as it doesn't manifest the bug until the second upload after the change and requires the IDE to be restarted etc

Ps. Someone else , who doesn't seem to be on the forum, commented on the issue saying that using the 1eb90... version didn't fix it. But they may have not done a hard reset by disconnecting the device.

I find after a couple of uploads, that the board needs to be powered down and up again to get it to work.

Guys

I've reverted the change and tested and upload

I think its OK now. But you may need to disconnect and reconnect the board even after you have uploaded from the new / good version of the repo.

@Chilltronix

Can you download or checkout the latest version (sorry if this blows away your upload files)

Actually, can you somehow post the files required for Linux so I can add them to the repo ?

Thanks

Roger

Give us a mo...

@bobc

Thanks for the tip about yield() requiring extern C.

I've updated the repo and yield() is now available, but doesn't actually do anything under normal conditions. i,e the comment in hooks.c reads...

  • This function is intended to be used by library writers to build
  • libraries or sketches that supports cooperative threads.
  • Its defined as a weak symbol and it can be redefined to implement a
  • real cooperative scheduler.

But RadioHead call's it, and its now part of the API, so we need it

OK, so for Linux, DFU upload seems easy. You start with pressing reset and then release and press the other button...

Requires dfu-utils installed.

Under the tools directory create a maple_upload script with 755 rights (execute etc) and with the following contents:

#!/bin/bash

set -e

if [ $# -lt 4 ]; then
    echo "Usage: $0 $# <dummy_port> <altID> <usbID> <binfile>" >&2
    exit 1
fi
dummy_port=$1; altID=$2; usbID=$3; binfile=$4

DFU_UTIL=/usr/bin/dfu-util
if [ ! -x ${DFU_UTIL} ]; then
    echo "$0: error: cannot find ${DFU_UTIL}" >&2
    exit 2
fi

${DFU_UTIL} -d ${usbID} -a ${altID} -D ${binfile}

Then platform.txt needs the following mods:

# Uploader tools
# -------------------

# Upload using Maple bootloader over DFU
tools.maple_upload.cmd=maple_upload
tools.maple_upload.cmd.windows=maple_upload.bat
tools.maple_upload.cmd.linux=maple_upload                                       ### Uncommented and modified
tools.maple_upload.path={runtime.hardware.path}/tools/win
tools.maple_upload.path.macosx={runtime.hardware.path}/tools/macosx
tools.maple_upload.path.linux={runtime.hardware.path}/tools/linux    ### Added

@chillitonix

I have modified platform.txt and add the linux folder and maple_upload script and also added a readme.txt next to the maple_upload script with instructions to set the rights to 755

Can you check if that looks OK ?

EDIT

Can you tell me how you stalled DFU utils e.g. is there an apt-get command etc

or is the documentation here ? Merge DFU support into mainline U-Boot - eLinux.org

Or can we put a copy of the DFU stuff in the repo, in case the other source vanishes ?

Edit2.
umm. Definately let me know where you got the DFU stuff from. The DFU-Monks stuff is no longer there
:frowning:

Anyway, I'll start to update the wiki

Edit 3

Wiki has been updated

@chillitronix

Let me know how you installed DFU Utils and where you got the files from etc.

I suspect it will be safer to add the DFU files to the repo if possible, we can stick them in the tools/linux folder e.g in a folder called dfu-utils-install

Some Arduino 1.6.0rc1 examples for Maple Mini

I threw together some examples, many from original examples, some I developed, some from the web but all have been tested to work with the BAITE Maple Mini and Serial over USB.

Most are elementary stuff (blush) but there a few advanced examples such as:
strtol_DecEquivalents.ino
StringEx_Parsing.ino

All examples utilize the USB with virtual comm port and either the Arduino Serial Console or a product like TtermPro.

There is the traditional Blink with a twist: Blink+Count

Anyway the intent is just to have a mixed bundle that is known to fully work and does a bit more than just blink a LED... and maybe just a weebit less dull.

In the example IntegerInput_FloatOutput I use the Serial.parseInt() which will automatically parse (space, comma, decimal are delimiters) the serial input stream. This is shown in the graphic; therefore, 355 Enter can be typed followed by 113 Enter or 355 113 followed by Enterkey.

ALL of the examples are intended to "wait" for the Serial Monitor to be opened before they continue into Loop(). It works on my Win8.1 system here, but I cannot promise it will work on all OS's ... we need to check it out.

Ray

MapleMini_Examples.zip (17.9 KB)

SerMon.jpg

Ray

Thanks

I'll add them to the repo

I've just remembered that I had included all the old Maple examples in already in the repo, but most of them are not going to work because they still reference SerialUSB

When I get chance I'll go though and change them all

I think its best if I differentiate between new and old examples

Perhaps I'll rename the existing examples folder to maple_examples

and put your new files in examples instead

DFU utils is a package available here, how to install it depends on the package manager on specific Linux distributions, and if it is available as a package on that distribution. On Arch Linux it is as simple as pacman -S dfu-utils

That doesn't work as is, though I put the ### comments to indicate what I changed, in fact it wasn't in my file, and the IDE reads that as part of the command line and can't find the file "####added by @chillitronix" so fails. Removing the comments from the end of the line fixes it.

Also I have found that you do not need the line:

tools.maple_upload.cmd.linux=maple_upload

As it is the same as the tools line above so does not need to be varied by OS. (It does work though so you just need to comment it out). Basically all that is needed is the path statement.

@chilltronix

I've pushed a update. Hopefully it fixes those issues

I think we need documentation on linux for the dfu-utils, especially for well known disro's e.g. Ubuntu, which don't use pacman ? do they?

I have Ubuntu on an old laptop, I think. I'll fire it up and see...

I suspect on Debian based systems (Ubuntu, Debian, Raspbian etc) it will be apt-get dfu-utils.

They may need to check the location of the program dfu-util. (It will probably be in /usr/bin/ which is where it says).

It would be best to say they need to install a package named dfu-utils with what ever their package management utility is...

That does work apart from the permissions on the maple_upload which then need to be modified. Is there anyway you can set permissions in the GIT to allow code execution?

Hi Guys,

I was just trying to compile some of the original Maple examples and I got a strange error, which I have distilled to this code

int index = 0;   

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

error is

sketch_dec30c.ino:1:5: error: 'int index' redeclared as different kind of symbol
In file included from c:\program files (x86)\arduino\hardware\tools\gcc-arm-none-eabi-4.8.3-2014q1\arm-none-eabi\include\stdlib.h:11:0,
from C:\Users\rclark\Documents\Arduino\hardware\Arduino_STM32\STM32F1XX\cores\maple/wirish.h:41,
from C:\Users\rclark\Documents\Arduino\hardware\Arduino_STM32\STM32F1XX\cores\maple/Arduino.h:30,
from sketch_dec30c.ino:1:
c:\program files (x86)\arduino\hardware\tools\gcc-arm-none-eabi-4.8.3-2014q1\arm-none-eabi\include\string.h:55:8: error: previous declaration of 'char* index(const char*, int)'
char *_EXFUN(index,(const char *, int));
^
Error compiling.

I suspect that string.h is being incorrectly included somewhere, but I"m not entirely sure where.

Edit

I've open an issue for this Sketches with global variables called index don't compile · Issue #16 · rogerclarkmelbourne/Arduino_STM32 · GitHub

Is that string.h or String.h?

rogerClark:
(...)
I suspect that string.h is being incorrectly included somewhere, but I"m not entirely sure where.

It is saying:

sketch_dec30c.ino:1:5: error: 'int index' redeclared as different kind of symbol
In file included from c:\program files (...)\include*stdlib.h*:11:0,
from C:\Users\rclark\Documents(...)\cores\maple/wirish.h:41,
from C:\Users\rclark\Documents(...)cores\maple/Arduino.h:30,
from sketch_dec30c.ino:1:
c:\program files (x86)\arduino\hardware\tools\gcc-arm-none-eabi-4.8.3-2014q1\arm-none-eabi\include\string.h:55:8: error: previous declaration of 'char* index(const char*, int)'
char *_EXFUN(index,(const char *, int));
^
Error compiling.

don't?