I saw that Sheepdoll has a generic HALMX roadmap but the changes I have done so far are tested only MXBluePillF103C8 variant. Not to the entire HALMX variants. For that reason, I created this post that informs the members with the changes are made by me or any other member, to the MXBluePillF103C8 variant.
Things that work:
[14 May 2016]
* USBSerial. Added support to USB Virtual COM port.
* Bootloader. The Maple DFU firmware upload method is used to upload the compiled sketches to HALMX.
[09 May 2016]
* Added the interrupt based Serial transmission function on Serial1, 2 and 3 ports.
[19 April 2016]
* wiring_analog.c Support to AnalogRead() and AnalogWrite() functions
[14 April 2016]
* SPI library
* wiring.h The delayMicroseconds() was re-written for STM32. The previous assembly code wasn’t work correct to the tests I had made.
* wiring_digital.c The LOW and HIGH were placed in reverse on digitalRead(…). Fixed!
[09 April 2016]
* Hardware Serial ports. Serial 1, Serial 2 and Serial 3 work in Interrupt mode.
Things to do:
* Wiring library. Support to I2C interface
* SPI library in DMA and Interrupt mode.
Sorry I dont have time to do much of this myself.
Im not sure if you did a pull from my repo into yours, as I updated some files to allow use with the bootloader.
Re:Bootloader for all STM32
I dont think we can write one bootloader that would work for all.
I am not sure if all STM32 devices have USB support ??
We could write a serial bootloader for those devices that only have serial, but I doubt there would be much point as I suspect those devices have a built in serial bootloader, or people would just use STLink.
The F4 has built in DFU, but I dont know if its possible to enter DFU bootloader mode from code, or whether it can only be accessed by Boot0 and Boot1.
Anyway I think that writing new bootloaders would be the last think to do.
On March I did some tests to combine the stm32duino bootloader with CubeMX. That was totally failure. I had changed the flash address from the *.ld file but … nothing. The bootloader was partially worked. I had unpluged the blupill from the usp port. I pressed the upload button on arduino IDE and simultaneously I plugged in the bluepill to the usb port. With that trick the bluepill was programed successfully.
I am thinking right now one more test to do but it is too late for that now. I will try it tomorrow.
The only way I could get the BluePill to work with the bootloader was to unplug it, and then plug it back in, just when dfu-util was searching for dfu devices.
The maple mini worked better, as I just press the reset button when dfu-util is searching.
I dont know why the reset button is not resetting the usb on the BluePill, but the problem may also be because of the Skylake chipset in my new PC, as it is not BluePill friendly and it does not work with the GD32 at all.
Some of the problem with the BluePill is that when the sketch runs, the Windows device manager still shows the DFU device, even though the dfu code is no longer running in the BluePill.
We could force USB enumeration when the sketch starts, but it would then show probably show an unknown device.
I think we need to find some small CDC code to provide USB Serial, as the STM code seems far to big.
Perhaps the libopencm3 code, as used by the BMP could be used to provide the USB.
The interesting thing about the BMP is that it has 3 devices at the same time, i.e. it behaves as a composite device. I think this is the way forward, as I know there is a lot of interest in USB midi and also USB HID ( mouse and keyboard)
If we start with a USB composite device, even with only 1 sub device, it would make it much easier to add additional devices.
<…>
The maple mini worked better, as I just press the reset button when dfu-util is searching.
<…>
Code raised to 17KB, and the BSS segment to 5KB!, for the typical blink program with some printing. The same code with libmaple is about 14.5KB/1KB.
While this size increase is not a problem for larger devices, is a serious drawback for the small.
I am examining the map file to see what is allocated and why. Maybe, we have to “touch” the MX generated code specially in small devices like “Pills”.
I presume somehow the linker is linking functions that are not actually used.
We use the –whole-archive flag on libmaple, on the “archive” code, to ensure that things like the hardware timer ISR’s get linked correctly.
I tried removing it from the HALMX core, but unfortunately it didnt seem to reduce the code size.
So either I modified the wrong code in platform.txt, or its not the –whole-archive flag that could be causing the large code.
The other thing that could be tried is somehow compiling the code from the Cube using just a makefile, and see if the CDC code is still too large.
I think @sheepdoll has been trying to compile using Eclipse on OSX, but I’m not sure if she was using an Arduino plugin, or just the files from the Cube.
The most important is that the code works! Nice job Vassilis and Sheepdoll!
Here is the size report of libcore.a (is the library of all sources):
arm-none-eabi-size _build/g103c/libcore.a
text data bss dec hex filename
49 0 0 49 31 dtostrf.o (ex _build/g103c/libcore.a)
200 0 0 200 c8 itoa.o (ex _build/g103c/libcore.a)
16 0 0 16 10 new.o (ex _build/g103c/libcore.a)
904 0 0 904 388 Print.o (ex _build/g103c/libcore.a)
56 0 0 56 38 RingBuffer.o (ex _build/g103c/libcore.a)
891 0 0 891 37b Stream.o (ex _build/g103c/libcore.a)
292 0 4 296 128 syscalls.o (ex _build/g103c/libcore.a)
594 0 2 596 254 UARTClass.o (ex _build/g103c/libcore.a)
94 0 0 94 5e USARTClass.o (ex _build/g103c/libcore.a)
6 0 0 6 6 wiring.o (ex _build/g103c/libcore.a)
132 0 0 132 84 wiring_digital.o (ex _build/g103c/libcore.a)
144 0 0 144 90 wiring_shift.o (ex _build/g103c/libcore.a)
78 0 0 78 4e WMath.o (ex _build/g103c/libcore.a)
1897 0 1 1898 76a WString.o (ex _build/g103c/libcore.a)
372 0 0 372 174 startup_stm32f103xb.o (ex _build/g103c/libcore.a)
184 4 0 188 bc system_stm32f1xx.o (ex _build/g103c/libcore.a)
342 0 4 346 15a stm32f1xx_hal.o (ex _build/g103c/libcore.a)
518 0 0 518 206 stm32f1xx_hal_cortex.o (ex _build/g103c/libcore.a)
1778 0 0 1778 6f2 stm32f1xx_hal_dma.o (ex _build/g103c/libcore.a)
826 0 0 826 33a stm32f1xx_hal_flash.o (ex _build/g103c/libcore.a)
1136 0 0 1136 470 stm32f1xx_hal_flash_ex.o (ex _build/g103c/libcore.a)
680 0 0 680 2a8 stm32f1xx_hal_gpio.o (ex _build/g103c/libcore.a)
7434 0 0 7434 1d0a stm32f1xx_hal_i2c.o (ex _build/g103c/libcore.a)
2146 0 0 2146 862 stm32f1xx_hal_pcd.o (ex _build/g103c/libcore.a)
50 0 0 50 32 stm32f1xx_hal_pcd_ex.o (ex _build/g103c/libcore.a)
524 0 0 524 20c stm32f1xx_hal_pwr.o (ex _build/g103c/libcore.a)
2716 0 0 2716 a9c stm32f1xx_hal_rcc.o (ex _build/g103c/libcore.a)
606 0 0 606 25e stm32f1xx_hal_rcc_ex.o (ex _build/g103c/libcore.a)
4440 0 0 4440 1158 stm32f1xx_hal_spi.o (ex _build/g103c/libcore.a)
128 0 1 129 81 stm32f1xx_hal_spi_ex.o (ex _build/g103c/libcore.a)
0 0 0 0 0 stm32f1xx_hal_tim.o (ex _build/g103c/libcore.a)
0 0 0 0 0 stm32f1xx_hal_tim_ex.o (ex _build/g103c/libcore.a)
2590 0 0 2590 a1e stm32f1xx_hal_uart.o (ex _build/g103c/libcore.a)
2054 0 0 2054 806 stm32f1xx_ll_usb.o (ex _build/g103c/libcore.a)
578 272 1 851 353 usbd_cdc.o (ex _build/g103c/libcore.a)
664 0 0 664 298 usbd_core.o (ex _build/g103c/libcore.a)
906 0 1 907 38b usbd_ctlreq.o (ex _build/g103c/libcore.a)
150 0 0 150 96 usbd_ioreq.o (ex _build/g103c/libcore.a)
396 0 0 396 18c _spi.o (ex _build/g103c/libcore.a)
128 0 0 128 80 gpio.o (ex _build/g103c/libcore.a)
184 0 0 184 b8 i2c.o (ex _build/g103c/libcore.a)
200 0 0 200 c8 main.o (ex _build/g103c/libcore.a)
116 0 0 116 74 stm32f1xx_hal_msp.o (ex _build/g103c/libcore.a)
98 0 0 98 62 stm32f1xx_it.o (ex _build/g103c/libcore.a)
360 0 0 360 168 usart.o (ex _build/g103c/libcore.a)
56 0 0 56 38 usb_device.o (ex _build/g103c/libcore.a)
124 16 0 140 8c usbd_cdc_if.o (ex _build/g103c/libcore.a)
588 0 544 1132 46c usbd_conf.o (ex _build/g103c/libcore.a)
243 52 0 295 127 usbd_desc.o (ex _build/g103c/libcore.a)
448 4 624 1076 434 variant.o (ex _build/g103c/libcore.a)
Perhaps there are some postings on STM’s own forums about the code size when using the Cube.
Its strange that compiler must be linking so much code that is never being used.
These are the extended HAL modules, they provide extended functionality on corresponding core modules. I am not sure if we need this functionality.
These are the extended HAL modules, they provide extended functionality on corresponding core modules. I am not sure if we need this functionality (for example fifo in i2c/spi etc….)
I think @sheepdoll has been trying to compile using Eclipse on OSX, but I’m not sure if she was using an Arduino plugin, or just the files from the Cube.
As I understand every source file inside cores/mapleMX directory is compiled and placed in the core.a static library, but every file in variants directory (for the selected board) is compiled and linked as object file. The linker is very capable to find the required functions from core.a rejecting all unneeded code but when tries to link objects that explicitly named, into binary is less sensitive, keeping much more functions (all objects from variant are explicitly named) .
I tried to put every source file from both cores/variants directories into core.a using makefile, and create the binary, linking the main source file (1 file sketch for simplicity) with core.a
The linker outputs some warnings about some libc functions, actually there are some problems with linking and some objects must be linked explicitly and not as part of core.a (I am still working on this, to figure out why this is happening and for which files).
Using makefile it is possible to compile and link the sketch successfully, and the size of executable binary is smaller! For example the blink sketch is about 11.5KB when using arduino build system and with makefile and big-core.a is about 8KB, keeping the CCFLAGS the same.
Maybe someone with deeper knowledge of linker internals can help to clarify these issues, if the MX sources must be included in core.a for effective linking we have to change the structure of files. It seems that variant directory is intended for some header files or small piece of code and not for frameworks.
I will make some more tests, keep this info as preliminary, I am still trying….
PS. Roger a small fix about naming of include<arduino.h> in variant.cpp file, Linux is case sensitive…. I send pull request…
The problem is the file with the interrupt vectors stm32f1xx_it.c. All interrupt vectors are weakly defined in startup.S to Default_Handler, if the stm32f1xx_it.c is included in a static library, the linker keeps the definitions of startup.S and all other definitions are discarded. The program is not running as the Default_Handler is while(1); loop. I tried to change the position of library in linker command line but the result was the same.
When the stm32f1xx_it is included in linker command line as object together with static library (with all other files) and sketch object the interrupt vectors are taking the correct values and the program executes normally. With this configuration there is no need to use the -whole-archive flag (which includes all library functions) and the linker resolves correctly the required symbols, discarding any no needed functions.
I did not find a working solution to use the stm32f1xx_it.c inside the static library…. maybe some modification in startup is needed, but this will brake the automatic generation of code from CubeMX.
We already need to make some changes to the auto generated code, so I don’t think it matters that the code needs to be changed.
I already had to change the file that hard codes the start offset vector to 0x00 as we need to move the start vector when using the bootloader, so I had to wrap the existing definition in an ifndef block, so that we can define it as a compiler command line argument.
Relocating the exception vectors table.. I do that at run time by writing a register in the STM32Fxxx. At compile time I have the linker config script file place the power-up default for the table at the usual place so that the auto-generated code will work.
My main reason for relocating the table is to have two versions of the app in flash, and use one as power-up default and then it decides whether to run the other version (moving the vector table pointer in hardware to the flash for that 2nd code), or to download and re-flash new version of 2nd copy of code.
This is a way to do two versions of code and in-place reflash, unattended, without needed an STM32 that has double flash size and the hardware remapping of two banks of flash. Saves cost of the double sized flash like the STM32F42x has, whereas the STM32F41x (or 40x) have half that much and no bank switching.
I had sent a PR from my windows Github but as it seems, you have never received it.
I think, I will do the PRs from the web based Github (for sure ).
I did not receive the other PR.
I have never tried to send a PR directly from Windows. Perhaps it doesn’t work.
// Adopted from libmaple with Hal
uint32_t micros(void)
{
uint32_t ms;
uint32_t cycle_cnt;
do {
ms = HAL_GetTick();
cycle_cnt = SysTick->VAL;
asm volatile("nop"); //allow interrupt to fire
asm volatile("nop");
} while (ms != HAL_GetTick());
return ( ms * 1000 + ( SysTick->LOAD + 1 - cycle_cnt ) / ( SystemCoreClock / 1000000 ) ) ;
}
// Adopted from libmaple with Hal
uint32_t micros(void)
{
uint32_t ms;
uint32_t cycle_cnt;
do {
ms = HAL_GetTick();
cycle_cnt = SysTick->VAL;
asm volatile("nop"); //allow interrupt to fire
asm volatile("nop");
} while (ms != HAL_GetTick());
return ( ms * 1000 + ( SysTick->LOAD + 1 - cycle_cnt ) / ( SystemCoreClock / 1000000 ) ) ;
}
The one that I’ve seen uses micros() which computes the inter-systick time using the real time counter value from the systick timer, and knows the systick timer clock speed.
But none the less, there’s always that pesky systick interrupt, usually every 1,000 microseconds.
The one that I’ve seen uses micros() which computes the inter-systick time using the real time counter value from the systick timer, and knows the systick timer clock speed.
.
GrumpyOldPizza, nice code. I included in my Big Book of snipplets….
while (ms != HAL_GetTick());
stephen
srp
while (ms != HAL_GetTick());
while (ms != HAL_GetTick());
I have one other PR https://github.com/rogerclarkmelbourne/ … M32/pull/7, but I’m waiting for a reply from @sheepdoll, as it may effect the Mac
We also have the code for micros() which needs to be manually merged as its not a PR
Thanks GrumpyOldPizza for clarify this…. yes, this value is changing very fast. I am not sure if the two nops are required…. No big difference anyway.
When I compared the build download output to the OS X 10.7.5 I found that the file startup_stm32f103xb.s was not being included. I noticed that on the 10.7.5 the suffix was uppercase ‘S’ changing this on the 10.10.5 machine the blink sketch ran.
I noticed that in the platforms.txt file the recipe for assembler is uppercase ‘S’ I also notice that on the F4 variant I had copied this file to the top of the variant tree and must have renamed it as there is both a file with a small ‘s’ in the drivers..gcc path and the one with the uppercase ‘S’ that is peer to variant.cpp and the .ioc file. So I must have run into this before and forgot about it.
I think @vassilis has a windows bat file which changes the case of assembler file extension (Or perhaps it was a script, I definitely remember seeing a script that changed it)
I sent a PR to Roger.
Normally the write function “pushes” a byte to the ring buffer and triggers manually the transmit interrupt if the transmission is inactive. A next call of write function simply pushes a new byte to ring buffer if the previous is not completed. The irq transmit function checks the ring buffer and if is not empty sends the next byte. With this way every write takes only the time of pushing the byte into the ring buffer ( less than usec in our case) and the transmission is actually a chain of transmits initiated by first write and controlled by irq function itself, of course, somewhere there is a check to avoid overflow of buffer (eg. the write checks if buffer is full and if it is, waits or discards the new byte).
PS. I didn’t check the new version yet…
(1) To program an F103 the Arduino IDE through maple_upload file, sends the DTR control signal and the character string “1EAF” via the CDC USB Serial port to the MCU. If that “Magic pack” is correct, the MCU restarts to the bootloader’s memory start address.
– The USB Serial port is appeared as “USB Serial device” in the device manager. I have not tested it on Linux or Mac but is expected to work out-of-the box.
– The USB re-enumerations works.
– The bootloader works and it is the stm32duino bootloader v2.0
There is an option in chip.c file that says:
#define USE_USBSerial
If I disconnect and then re-connect the usb cable to the STM32, the usb host sees the STM as “unknown device”.
I tried to reproduce the usb code to Atollic TrueSTUDIO and it has the same symptom.
When I use the Keil uVision 5 the code works correctly. Every time I disconnect / connect the STM to the usb host , the STM is appeared correctly in the device manager. I think that happens because the uVision uses its own ARM Compiler. The TrueSTUDIO uses the GNU gcc C/C++ compiler, the same as arduino uses
I did a debugging with TrueSTUDIO and I saw that it sticks in to the HardFault_Handler
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
}
/* USER CODE BEGIN HardFault_IRQn 1 */
/* USER CODE END HardFault_IRQn 1 */
}
There were issues in the libmaple core, with gcc 4.9 and I noticed that the bootloader will not run if compiled with 4.9
So perhaps its an optimisation setting issue.
Actually this sounds more like an issue about when PA12 is pulled low.
Perhaps it happens too late, and the USB is already code is already running
If I disconnect and then re-connect the usb cable to the STM32, the usb host sees the STM as “unknown device”.
I tried to reproduce the usb code to Atollic TrueSTUDIO and it has the same symptom.
When I use the Keil uVision 5 the code works correctly. Every time I disconnect / connect the STM to the usb host , the STM is appeared correctly in the device manager. I think that happens because the uVision uses its own ARM Compiler. The TrueSTUDIO uses the GNU gcc C/C++ compiler, the same as arduino uses
I did a debugging with TrueSTUDIO and I saw that it sticks in to the HardFault_Handler
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
}
/* USER CODE BEGIN HardFault_IRQn 1 */
/* USER CODE END HardFault_IRQn 1 */
}
Thanks! I will try that.
The strange thing is that I produced the same code with STM32CubeMX (identical) for uVision and TrueSTUDIO.
The first one works correctly, but the second one has the problem I mentioned earlier.
I used the debugger in TrueSTUDIO to find out where was the problem.
I found that the problem was at the pointer pDev in file usbd_cdc.c that seems to has invalid/wrong RAM address (?). I temporary put that line in comment and the USB worked as expected !
static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t ret = 0;
/* Open EP IN */
USBD_LL_CloseEP(pdev,
CDC_IN_EP);
/* Open EP OUT */
USBD_LL_CloseEP(pdev,
CDC_OUT_EP);
/* Open Command IN EP */
USBD_LL_CloseEP(pdev,
CDC_CMD_EP);
/* DeInit physical Interface components */
if(pdev->pClassData != NULL)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->DeInit();
//USBD_free(pdev->pClassData); //<========================== THIS LINE =============
USBD_free(NULL);
pdev->pClassData = NULL;
}
return ret;
}
I used the debugger in TrueSTUDIO to find out where was the problem.
I found that the problem was at the pointer pDev in file usbd_cdc.c that seems to has invalid/wrong RAM address (?). I temporary put that line in comment and the USB worked as expected !
static uint8_t USBD_CDC_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t ret = 0;
/* Open EP IN */
USBD_LL_CloseEP(pdev,
CDC_IN_EP);
/* Open EP OUT */
USBD_LL_CloseEP(pdev,
CDC_OUT_EP);
/* Open Command IN EP */
USBD_LL_CloseEP(pdev,
CDC_CMD_EP);
/* DeInit physical Interface components */
if(pdev->pClassData != NULL)
{
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->DeInit();
//USBD_free(pdev->pClassData); //<========================== THIS LINE =============
USBD_free(NULL);
pdev->pClassData = NULL;
}
return ret;
}
I’m trying to compile using 1.6.9 (which works fine with the libmaple repo – without any changes)
And I now get this error
arm-none-eabi-g++: error: unrecognized command line option '-CC -mcpu=cortex-m3'
@vassilis do a pull from my repo to get these fixes
The issue, believe it or not… appears to be the tab or spaces in front of the -mcpu !!!
I also changed the master compiler path to use the runtime.tools… variable rather than hard coded
compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/
I did the PR and I started using the Arduino 1.6.9. Everything works fine now.
I tested the 1.6.9 with HALMX some days ago and I got a mountain of errors/warnings
The only real error was the problem with the spaces in front of the -mcpu, everything else was just warnings
If you are switching to 1.6.9 (like I have), you can also change the build archive path in platform.txt, the warning tells you exactly what to change, its only on 2 lines in platform.txt so is easy change.
BTW. As the only board that currently works, you could comment you the other boards in boards.txt by putting a # in front of all their settings
I think this may save confusion until the other board variants are working, as there are multiple STM32F103C boards in boards.txt
(you don’t need to delete the variants folders)
I can do this is you want. But not until tuesday
Documents/Arduino/hardware/HALMX_Arduino_STM32/HALMX/variants/MXBluePillF103C8/variant.h:36:21: fatal error: Arduino.h: No such file or directoryextern const Pin2PortMapArray g_Pin2PortMapArray[]extern const Pin2PortMapArray g_Pin2PortMapArray[]I had to comment out these two lines due to conflict (itoa.h):
#if 0
extern void itoa( int n, char s[] ) ;
#else
extern char* itoa( int value, char *string, int radix ) ;
extern char* ltoa( long value, char *string, int radix ) ;
//extern char* utoa( unsigned long value, char *string, int radix ) ;
//extern char* ultoa( unsigned long value, char *string, int radix ) ;
#endif /* 0 */
The good thing is Vassilis made the changess to the global that I was planning and saves me a lot of time. Yay for collaboration.
Now I have to make these changes manually for the F103 Nucleo pins.
there was another thread here about itoa adding a lot of bloat to the code. Probably because most big iron implementations just call sprintf to do itoa. Not efficient, but effective.
Back when I was learning code 40 years ago you had to learn how to code itoa and ftoa from first principles. Hint it involves modulus and divide by 10. So good code needs to use a fpu if available. Ftoa is much more complex. The difference between Woznick and Gates as according to Issacson’s Biography this may be the one thing Gates did at MIT. On the other hand my example was from the HP2100 manual, so it was more of a case of knowing where to look.
Anyway, I tried to build again the code with gcc 4.8.3 and those commented lines are fine to be included. I guess with the latest compiler (or maybe the new library), we need to put #if #endif to exclude those lines.
…
I had to comment out these two lines due to conflict (itoa.h):
…
I have one situation where it’s needed, due to high frequency EXTI interrupts from an ASIC than needs a few tens of microseconds’ interrupt latency worst case. CubeMX lets me set that preemption priority.
For recurring timer interrupts, as I recall, the timer hardware (not the ISR) reloads the interval counter automatically if configured for such.

- nvic_.jpg (145.94 KiB) Viewed 1036 times
The new ring_buffer structure should look like this:
struct ring_buffer{
//uint8_t buffer[CDC_SERIAL_BUFFER_SIZE];
uint8_t *buffer;
volatile uint16_t iHead;
volatile uint16_t iTail;
};
https://github.com/ekawahyu/HALMX_Ardui … 3d850ba75d
Tested with fast auto-typing through AppleScript, everything seems fine. I also put a periodic CDC_Transmit for every 20 ms through SysTick callback.
So, it’s not important if the magic word is simple or not
Well, I have concern about ‘1EAF’ on STM32F072 Discovery because I am using the built-in system DFU and I wanted it to jump to system DFU by software instead of by pressing any button. No intervention whatsoever. So, it continuously listens to those USB Serial data stream for magic word. No DTR or any other reset mechanism available. The USB D+ even has built-in pull up resistor.
I am imagining that ‘1EAF’ would likely get captured from data stream than ‘@boot’. Maybe I am wrong, but it is at least 5 letters against 4, there is double characters in sequence, etc. I might probably need a magic sentence like “@aladin open sesame” instead of one word, just to be sure that is not part of data stream. ![]()
At least, it works for now. Look ma, no hands!
But I don’t see any way around getting the Serial code to listen for this sequence plus the DRT line
To change this code we’d need to rebuild all the upload tools. The main problem with this is the Windows “maple_upload” java, as we don’t have the original source for this utility, we only have a decompilation – and I’m not sure it recompiles
Considering no one has reported any issues with the existing 2 byte sequence, I don’t see a big problem with staying with it, and it pays homage to Leaflabs who kicked this all off in the first place ![]()
@RogerClark: could explain a bit how this maple_loader.jar works on Windows? I am having a hard time to understand what those %1 %2 … parameters I need to pass to. I can see that it uses jSSC. I might be able to rewrite the code for it.
Look in bottom of platform.txt as I think those values are just passed by the commands in the tools section of platform.txt
(note some params are probably redundant e.g. possibly the USB VID PID stuff )
I’m not sure the best way to do this and make it generic, but until someone can come up with a better idea ![]()
I’m going to define
USB_DISC_PORT
and
USB_DISC_PIN
Something like this
void USBSerial::init(void){
/* Re-enumerate the USB */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
#if defined(USB_DISC_PORT)
GPIO_InitStruct.Pin = USB_DISC_PIN;
HAL_GPIO_Init(USB_DISC_PORT, &GPIO_InitStruct);
HAL_GPIO_WritePin(USB_DISC_PORT, USB_DISC_PIN, GPIO_PIN_RESET);
#else
GPIO_InitStruct.Pin = GPIO_PIN_12;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
for(volatile unsigned int i=0;i<512;i++);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
#endif
MX_USB_DEVICE_Init();
}
I ran the Cube and it had updates, so I applied the updates, and the USB no longer compiles ![]()
HALMX_Arduino_STM32\HALMX\variants\MXBluePillF103C8\Src\usbd_cdc_if.c:143:24: error: 'hUsbDevice_0' undeclared (first use in this function)
For using the DISC pin on maple mini replace the init code into the USBSerial.cpp file
USBSerial.cppvoid USBSerial::init(void){
/* Re-enumerate the USB */
volatile unsigned int i;
#ifdef USB_DISC_PIN
pinMode(USB_DISC_PIN, OUTPUT);
digitalWrite(USB_DISC_PIN, HIGH);
for(i=0;i<512;i++);
digitalWrite(USB_DISC_PIN, LOW);
#else
pinMode(USBDP_PIN, OUTPUT);
digitalWrite(USBDP_PIN, LOW);
for(i=0;i<512;i++);
digitalWrite(USBDP_PIN, HIGH);
#endif
MX_USB_DEVICE_Init();
}
Thanks
I didnt realise that the pin was defined elsewhere as well as in USBSerial.cpp
Perhaps we can get USBserial.cpp to use the same #define , so it only needs to be changed in one place
I think I miss understood your posting.
I thought you were saying that it was already defined in chip.h, but I now realised this is new code.
I looked at the code in Libmaple, and it just seems to drive the USB DISC line LOW and holds it low.
But I see your code drives it LOW then back to HIGH. I’m not sure why there is a difference, but I suppose as long as it works (at the moment) it is better than it not working at all, as it will allow people with the Maple mini to use the core.
The only slight problem is that I need to completely duplicate all the Cube file for the MXBluePill to make make the Maple mini, but there are in reality very few differences. (just the flash size and the USB reset)
Thanks
Roger
The first code
#ifdef USB_DISC_PIN
pinMode(USB_DISC_PIN, OUTPUT);
digitalWrite(USB_DISC_PIN, HIGH);
for(i=0;i<512;i++);
digitalWrite(USB_DISC_PIN, LOW);
#else
I thought the sketch was being run by the bootloader after upload, but it looks like the bootloader has a problem with the sketch binary and it does not contain the correct code signature (or some problem like this)
I will need to revert the code in the repo, as I think something has gone badly wrong ;-(
/* USART1 init function */
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 38400;
huart1.Init.WordLength = UART_WORDLENGTH_7B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/* USART3 init function */
static void MX_USART3_Init(void)
{
husart3.Instance = USART3;
husart3.Init.BaudRate = 38400;
husart3.Init.WordLength = USART_WORDLENGTH_7B;
husart3.Init.StopBits = USART_STOPBITS_1;
husart3.Init.Parity = USART_PARITY_NONE;
husart3.Init.Mode = USART_MODE_TX_RX;
husart3.Init.CLKPolarity = USART_POLARITY_LOW;
husart3.Init.CLKPhase = USART_PHASE_1EDGE;
husart3.Init.CLKLastBit = USART_LASTBIT_DISABLE;
if (HAL_USART_Init(&husart3) != HAL_OK)
{
Error_Handler();
}
}
I think this is the other way around, isnt it?
I thought the first 3 were USARTS and 4 and 5 are UARTS
Anyway…
In libmaple, they were all initially called the same name even though some were USARTs and some UARTs
For basic functionality it doesn’t matter, as USARTs have UART functionality, but it is a problem for advanced functions.
In libmaple I think it just uses #ifdef’s to call the appropriate setup code, depending on the device number.
So perhaps we can do the same.
This may not be the ideal or final solution, but this is such a small detail in the overall scale of the core, that perhaps we can do it with #ifdef’s until we have a better picture potential problems on the other processor variants e.g the L versions and the F7 and F0 etc – which may be more different even than just USART vs UART
In ideal case, the F103 library would have support for RTS/CTS and related interrupts. Even when they are available only with the first three serial devices.
I thought the first 3 were USARTS and 4 and 5 are UARTS
I thought the first 3 were USARTS and 4 and 5 are UARTS
stephen
stephen
off to google on the topic
stm32 usart spi 9 data bits
The core for the Arduino STAR OTTO seems to have I2C (Wire) code built into the core (not as a library), which uses the HAL
I suspect that this is going to be the quickest way to add Wire to the HAL MX core.
There are some definition names in the STM32F469xx.h library that are used with different names in the F1 libraries such as HAL_I2C1 (F469) instead of I2C1 (F103) .
I hope the Wire library has not interfered with the studies for your exams.
I was going to look at the Wire library at the weekend, but I do not have much spare time at the moment.
Don’t worry. I need a break from studying.
I sent you with a PR with the Wire (I2C) core library. The core library has been tested only on DS1307 device by using the RTCx library. The RTCx library can be downloaded from the “Library manager” on Arduino IDE (Sketch -> Include library -> Manage libraries).
-= The wire library has not been tested 100%. I sent the Pull Request only for testing purpose. =-
No Worries….
I will accept the pull request and test on a BMP085 barometer module.
PS. I got an email from Francesco at Arduino.cc, and he has nearly finished the SDIO function.
So perhaps we can add this as a library.
Hopefully, he will email me when it is pushed to github.
We could actually provide the #ifdef in the core to remove the SPI by declaring a macro such as USE_SPI1, USE_SPI2, etc.

![[SOLVED] Discovery STM32F100RB — Trouble with timers and library structure](https://sparklogic.ru/wp-content/uploads/2019/11/st-stm32vl-discovery-90x90.jpg)
