Hi, Habr.
The traditional unique advantage of the Arduino platform was called (and even now it is called, although this is already wrong - and we will talk why) lowering the threshold for entering microcontroller development to the level of basic knowledge of C / C ++ and electronics on the scale of “connect an LED in the right polarity”.
Ask about any active supporter of Arduino - and they will quickly explain to you that you can, of course, write under STM32 or nRF52, but there is no real benefit, but sleepless nights over hundreds of pages of datasheets and endless sheets of functions with long obscure names are waiting for you.
')
The merits of Arduino in lowering the threshold of entry is really hard to overestimate - this platform came to light in the middle of the 2000s, and after 2010 it gained considerable popularity among fans. There were no special alternatives at that time - processors on Cortex-M cores only appeared, compared to AVR, they were quite complicated even for professional developers, and most vendors' debugging boards cost from hundreds of dollars and higher (and in general, the industry has a price tag for debugging on a $ 5 controller in $ 500, nobody surprised anyone very much).
However, the Arduino’s big problem is that its development over the past 10+ years most resembles some AvtoVAZ models:
Since I plan a long introduction further, now, so that you can imagine what the practical part will be, I will give the
full text of the program, including the initialization of the STM32 processor and the flashing of the LED. The program is written for ARM Mbed OS:
#include "mbed.h"
DigitalOut myled(LED1);
int main() {
while(1) {
myled = 1; // LED is ON
wait(0.2); // 200 ms
myled = 0; // LED is OFF
wait(1.0); // 1 sec
}
}
? ? ? ? , .
, 2010 … . AVR, 8- , — 2017 12 % ( Aspencore), : AVR, PIC STM8. , — , ..
ATMega 12 % — 32- Cortex-M / (STM32F030 16-64 4-8 30-50 ). , - .
64- — , , Cortex-A. , , Cortex-M ? ( , — ), . AVR , STM32F1 STM32L1 , - Infineon NXP…
, — , STMicro : SPL, HAL LL. , , , .
.
, . , — , , , . ,
(, , , loop(), , - — , - , - ).
— , « », :
- HAL — . . , -, (, , - STM32L072, STM32L151 STM32L451 — , ), -, ( , , , STM32, , ). — , RIOT API SAUL, ; , - .
- — , , - . , , .
- — , . , . , , , . , .
- IPC — . , , , , , , , , , - - (, , : , , , , ).
- — API , , . , , , , , , , API .
- — « » .
, — API POSIX.
, . , :
- FreeRTOS — , , . — . ( , )
- Contiki OS — , , , 6LoWPAN. , (, ). Contiki NG — , .
- RIOT OS — , Contiki. ( ATMega) . . C. , , . , , .
- ARM Mbed — ( , Apache 2.0) ARM Holdings. 2.0, 5.x. C++ API. , . , Mbed.
- TI-RTOS — Texas Instruments, , TI - , , . , API .
- , arm-none-eabi-gcc. , RIOT Makefile', Visual Studio, . ARM Mbed (
mbed-cli),
PlatformIO, mbed-cli Keil uVision Makefiles.
— , Arduino. , gdb JTAG/SWD-.
, ? , ?
. . ,
.
, RIOT OS « » :
- MinGW, arm-none-eabi-gcc GNU make ( Windows 10 , Ubuntu)
- RIOT
- cd RIOT/examples/hello-world
- make BOARD=nucleo-l152re
- HEX- Nucleo ( ST-Link )
, main.c, :
#include <stdio.h>
int main(void)
{
puts("Hello World!");
printf("You are running RIOT on a(n) %s board.\n", RIOT_BOARD);
printf("This board features a(n) %s MCU.\n", RIOT_MCU);
return 0;
}
? , ? SPL? , ?
.
,
. — ARM Mbed .
( , , b2b-, Nucleo-L152RE BME280 OPT3001)

1)
mbed.com.
2) «Compiler» - . , . , «Add board» Nucleo, ( L152RE, , Nucleo, ). , Nucleo .

3) New → New Program. Mbed - , Nucleo-L152 . , , 5.9.5, — «Empty program».
— -, mbed, -, - main.cpp. #include, mbed-os.
:
- «Import», «Click here to import from URL», ( , Mbed, )
- «Library»
- «Import»

→ «New file» → main.cpp. :
#include "mbed.h"
DigitalOut led(LED1);
int main()
{
printf("Hello World !\n");
while(1) {
wait(1); // 1 second
led = !led; // Toggle LED
}
}
(LED1 — Nucleo )
4) Ctrl-D ( «Compile»), -, . Nucleo USB- ( : Nucleo mini-USB, ), 540 «Node_L152RE». MBED.HTM, , .
, , BIN- HEX- , Mbed , .
. Nucleo , — LED1.
5) BME280, ?
, «Import Library» (, , , — ). , Library, («Target path»).

, , .
6) , :
#include "mbed.h"
#include "BME280.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
int main()
{
while(1) {
wait(1); // 1 second
led = !led; // Toggle LED
printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
}
}
, , , Nucleo I2C-. , .. SDA SCL ( STM32L1 I2C, ), , , I2C_SDA I2C_SCL . .
7) . — +3,3 , , SDA, SCL. STM32, 3,3-, .

8) «Compile», BIN- Nucleo.
8) ??????
( —
Termite, , Nucleo; COM-. 9600 /)
9) PROFIT!!!

. , , « , », , .
— , . -, , while(1) 1- — , 1 , 1 , .
-, 9600 / — - , 2018 , 115200.
: Serial, , .
Serial pc(SERIAL_TX, SERIAL_RX);
pc.baud(115200);
while(1) , , . Mbed , (
EventQueue), ( call) ( call_every), .
:
#include "mbed.h"
#include "BME280.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
void printTemperature(void)
{
printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
led = !led; // Toggle LED
}
int main()
{
eventQueue.call_every(1000, printTemperature); // run every 1000 ms
eventQueue.dispatch_forever();
return 0;
}
, . , ( ), — , - . eventQueue ( — , 50 ), , , , .
?
, while(1) , .
, OPT3001. , …
OPT3001 — ( , ), TSL2561 , Mbed . , ( ), —
https://github.com/ashok-rao/mbed-OPT3001.
Import, «Click here to import from URL», URL , «Library» — «Import».
. .
, . , « OPT3001.cpp, »,
( , OPT3001).
: Import → Click here to import from URL →
github.com/olegart/mbed_opt3001 → Library → Target Path = → Import.
:
#include "mbed.h"
#include "BME280.h"
#include "OPT3001.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
OPT3001 sensor_opt(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
Serial pc(SERIAL_TX, SERIAL_RX);
void printTemperature(void)
{
pc.printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
pc.printf("%ld lux\r\n", sensor_opt.readSensor());
led = !led; // Toggle LED
}
int main()
{
pc.baud(115200);
eventQueue.call_every(1000, printTemperature); // run every 1000 ms
eventQueue.dispatch_forever();
return 0;
}
Compile, , Nucleo, 115200…

PROFIT!!!
:
, , , — , .
, , , . , , .
Nucleo «IDD», , , ( , — , ).

L152 10 , - LED1, ( 2-3 ). - , , ?..
, . , , , — , , eventQueue.call_every , . STM32L151 , — ,
RTC ( L151CB-A , RTC_SSR), — .
, dispatch_forever(), — , , , , .
, ? , , — ?
LowPowerTicker, RTC, — . LowPowerTicker, sleep() — ( , , , — , , - , , ).
: , - — , ( OPT3001, , 100 ). printf — , . , , .
, while(1), — . , while(1) ?
, EventQueue, .
#include "mbed.h"
#include "BME280.h"
#include "OPT3001.h"
DigitalOut led(LED1);
BME280 sensor_bme(D14, D15);
OPT3001 sensor_opt(D14, D15);
EventQueue eventQueue(/* event count */ 50 * EVENTS_EVENT_SIZE);
Serial pc(SERIAL_TX, SERIAL_RX);
LowPowerTicker lpTicker;
void printTemperature(void)
{
pc.printf("%2.2f degC, %04.2f hPa, %2.2f %%\r\n", sensor_bme.getTemperature(), sensor_bme.getPressure(), sensor_bme.getHumidity());
pc.printf("%ld lux\r\n", sensor_opt.readSensor());
led = !led; // Toggle LED
}
void tickerIRQ (void)
{
eventQueue.call(printTemperature);
}
int main()
{
pc.baud(115200);
lpTicker.attach(tickerIRQ, 1); // every second
while(1)
{
eventQueue.dispatch(0);
sleep();
}
}
? : Low Power Ticker, . , eventQueue.call, ( , .. , — call ). .call , while(1), — dispatch , , sleep(), .
.
→ → → call → → dispatch → → sleep() .
PROFIT???

PROFIT!!!
( , 0,57 — , . Mbed, , STM32L1: Digital In , Analog In , - - . , Nucleo JTAG -)
- . , « RTOS» , , .
— 55,1 9,2 ( , «Build details» ), — , 2- STM32F103CB 128 20 . , , STM32F030F4P6 16 4 — RIOT OS .
, , float printf . —
, . malloc , malloc .
P.S. —
Mbed.
P.P.S. :
Nucleo-L152RE ( Nucleo / Discovery , ,
— , , ),
BME280 (: , , , BMP280, ). OPT3001 — , TI .
, RTOS , — Mbed , , - , RIOT 2018.07 ( ), .
, Arduino « », — , , , - ( , , ).
, , . , , , — , . , « », — , , , , 2018 , , , , - .
, — , . , , . .
, , . - , AVR.
…

?!
, 2018 ! ?