Stm32f100 notes

From Wiki at Neela Nurseries
Revision as of 20:22, 2 January 2019 by Ted (talk | contribs) (^ SN 436315)
Jump to: navigation, search

LPCXpresso 1114/1314 notes here

Overview

This article to hold notes on early works with STMicro's STM32F100VL Discovery Board. We're using arm-none-eabi-gcc and assember versions:

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (4.8.4-1+11-1) 4.8.4 20141219 (release)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ arm-none-eabi-as --version
GNU assembler (2.25-5+5+b1) 2.25
Copyright (C) 2014 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.


^ To Do

Ted to review these early STM32F notes and incorporate any useful ones in this article . . .

STM32F early notes sections 3p1 through 3p4


^ st-flash utility to program STM32F dev board

In these notes Ted has not yet covered wiring and connections from PC to dev board, but here is how to flash

$ grep -nr st-flash ./*
./Source/stash/makefile--set-aside-2018-05-03:15:# Inform `make` where to find Texane's stlink tools such as st-flash:
./Source/stash/makefile--set-aside-2018-05-03:108:	$(STLINK)/st-flash write $(PROJ_NAME).bin 0x8000000
./Source/stash/z-example-makefile:61:$(STLINK)/st-flash write $(PROJ_NAME).bin 0x8000000


Wiring on the STM32F Discover Value Line dev board, defined in source file i2c_hal.c:

I2C serial clock . . . PB13
I2C serial data  . . . PB14

UART port pins, 2018-08-28 Tuesday Ted needs to confirm these:

./Projects/STM3210E_EVAL/Examples/UART/UART_Printf/Inc/main.h:60:/* Definition for USARTx Pins */
./Projects/STM3210E_EVAL/Examples/UART/UART_Printf/Inc/main.h:61:#define USARTx_TX_PIN                    GPIO_PIN_9
./Projects/STM3210E_EVAL/Examples/UART/UART_Printf/Inc/main.h:62:#define USARTx_TX_GPIO_PORT              GPIOA
./Projects/STM3210E_EVAL/Examples/UART/UART_Printf/Inc/main.h:63:#define USARTx_RX_PIN                    GPIO_PIN_10
./Projects/STM3210E_EVAL/Examples/UART/UART_Printf/Inc/main.h:64:#define USARTx_RX_GPIO_PORT              GPIOA



^ STM32F microcontroller and dev board

This section of this LPCXpresso article is not very related to LPCXpresso but here to describe tools for compiling for, programming and debugging ST32F type processors and development boards. As of 2018-04-23 have on hand STMicro's development board model number STM32F1, also known as STM32FVLDISCOVERY. Overview page for this board at STMicro is:

The processor used in this dev board is an STM32F100 family part, described in the following PDF, and interestingly there appears to be no mention of 'fuse' or 'fuse bits' in this document:


References for reading and writing flash memory and other memory types on this board include the following pages:


- 2018-04-26 Thursday -


- STEP - Searching for tool chain components which provide gcc-arm-none-eabi compiler and related linking and library tools:

$ dpkg -c /var/cache/apt/archives/gcc-arm-none-eabi_4.8.4-1+11-1_i386.deb | grep gcc$
-rwxr-xr-x root/root    711032 2015-03-14 10:50 ./usr/bin/arm-none-eabi-gcc
hrwxr-xr-x root/root         0 2015-03-14 10:50 ./usr/bin/arm-none-eabi-gcc-4.8 link to ./usr/bin/arm-none-eabi-gcc

$


- STEP - building Texane's stlink programming utility for ST32F and related target processors:

Looks like there are a couple of extra steps to take to build developer or dev team Texane's stlink project. These steps include installing `cmake`, and then on Debian and Ubuntu systems invoking stlink's makefile as follows:

$ make clean && make release


- STEP - Noting memory map of the ST32F100xB family microcontrollers


- STEP - JTAG versus SWD (Serial Wire Debug)


- ASIDE - RCC stands for . . .

RCC in ST32F micro context appears to stand for Reset and Clock Control. See https://www.slideshare.net/GauravVerma3/programming-the-arm-cortex


With STM_COMMON=/opt/lib/STM32F4-Discovery_FW_V1.1.0 we find the following STM32F10xxx related library files . . . but having trouble finding file stm32f10x.h:

$ ls $STM_COMMON/Utilities/STM32F4-Discovery
MCD-ST Image SW License Agreement 19Jul2011 v0.1.pdf  stm32f4_discovery.c              stm32f4_discovery_audio_codec.h
Release_Notes.html                                    stm32f4_discovery.h              stm32f4_discovery_lis302dl.c
pdm_filter.h                                          stm32f4_discovery_audio_codec.c  stm32f4_discovery_lis302dl.h

$ ls $STM_COMMON/Libraries/CMSIS/Include
arm_common_tables.h  arm_math.h  core_cm0.h  core_cm3.h  core_cm4.h  core_cm4_simd.h  core_cmFunc.h  core_cmInstr.h

$ ls $STM_COMMON/Libraries/CMSIS/ST/STM32F4xx/Include
stm32f4xx.h  system_stm32f4xx.h

$ ls $STM_COMMON/Libraries/STM32F4xx_StdPeriph_Driver/inc
misc.h           stm32f4xx_cryp.h    stm32f4xx_dma.h    stm32f4xx_gpio.h  stm32f4xx_pwr.h  stm32f4xx_sdio.h    stm32f4xx_usart.h
stm32f4xx_adc.h  stm32f4xx_dac.h     stm32f4xx_exti.h   stm32f4xx_hash.h  stm32f4xx_rcc.h  stm32f4xx_spi.h     stm32f4xx_wwdg.h
stm32f4xx_can.h  stm32f4xx_dbgmcu.h  stm32f4xx_flash.h  stm32f4xx_i2c.h   stm32f4xx_rng.h  stm32f4xx_syscfg.h
stm32f4xx_crc.h  stm32f4xx_dcmi.h    stm32f4xx_fsmc.h   stm32f4xx_iwdg.h  stm32f4xx_rtc.h  stm32f4xx_tim.h

$


^ Demo Firmwares from AN3268 Standard Peripherals Library

- 2018-05-03 Thursday -

Ted working to compile, program part and run STMicro's RCC example firmware project, targeted to the STM32F100 Discovery Value Line board. Working on a Linux platform with GCC toolchain. Using professor Geoffry Brown's STM32 project template as for the project makefile or project recipe basis.

Today's goal is to build and run STM32 library example named 'RCC', locally installed in /opt/lib/an3268/stm32vldiscovery_package/Project/Examples/RCC. Having trouble with the linker not finding where built library files, likely archive or shared object files are located . . .

main.o: In function `main':
  .
  .
  .
/home/${USER}/projects/stm32f/RCC/main.c:72: undefined reference to `RCC_GetClocksFreq'
/home/${USER}/projects/stm32f/RCC/main.c:75: undefined reference to `STM32vldiscovery_LEDInit'
/home/${USER}/projects/stm32f/RCC/main.c:76: undefined reference to `STM32vldiscovery_LEDInit'
/home/${USER}/projects/stm32f/RCC/main.c:79: undefined reference to `RCC_APB2PeriphClockCmd'
/home/${USER}/projects/stm32f/RCC/main.c:84: undefined reference to `GPIO_Init'
/home/${USER}/projects/stm32f/RCC/main.c:85: undefined reference to `RCC_MCOConfig'
/home/${USER}/projects/stm32f/RCC/main.c:90: undefined reference to `STM32vldiscovery_LEDToggle'
/home/${USER}/projects/stm32f/RCC/main.c:95: undefined reference to `STM32vldiscovery_LEDToggle'
stm32f10x_it.o: In function `RCC_IRQHandler':
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:155: undefined reference to `RCC_GetITStatus'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:158: undefined reference to `RCC_ClearITPendingBit'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:161: undefined reference to `RCC_GetFlagStatus'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:169: undefined reference to `RCC_PLLCmd'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:175: undefined reference to `RCC_GetITStatus'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:178: undefined reference to `RCC_ClearITPendingBit'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:181: undefined reference to `RCC_GetFlagStatus'
/home/${USER}/projects/stm32f/RCC/stm32f10x_it.c:184: undefined reference to `RCC_SYSCLKConfig'
collect2: error: ld returned 1 exit status
../Makefile.common:70: recipe for target 'RCC.elf' failed
make: *** [RCC.elf] Error 1

$


LED toggling code is located in an AN3268 source file, full local path /opt/lib/an3268/stm32vldiscovery_package/Utilities/STM32vldiscovery.c . . .

$ grep -n -r STM32vldiscovery_LEDToggle ./*
         
./Project/Examples/STANDBY Mode/stm32f10x_it.c:139:  STM32vldiscovery_LEDToggle(LED3);
./Project/Examples/IWDG/stm32f10x_it.c:141:  STM32vldiscovery_LEDToggle(LED4);
./Project/Examples/WWDG/stm32f10x_it.c:153:  STM32vldiscovery_LEDToggle(LED4);
./Project/Examples/EXTI/stm32f10x_it.c:157:     STM32vldiscovery_LEDToggle(LED3);
./Project/Examples/RCC/main.c:90:    STM32vldiscovery_LEDToggle(LED3);
./Project/Examples/RCC/main.c:95:    STM32vldiscovery_LEDToggle(LED4);
./Project/Examples/SysTick/main.c:71:    STM32vldiscovery_LEDToggle(LED3);
./Project/Examples/SysTick/main.c:77:   STM32vldiscovery_LEDToggle(LED4);
./Utilities/STM32vldiscovery.c:142:void STM32vldiscovery_LEDToggle(Led_TypeDef Led)
./Utilities/STM32vldiscovery.h:119:void STM32vldiscovery_LEDToggle(Led_TypeDef Led);


On the Discovery board LED3 is defined as pin . . .

/opt/lib/an3268/stm32vldiscovery_package$ grep -n -r LED3 ./*

./Utilities/STM32vldiscovery.h:53:  LED3 = 0,
./Utilities/STM32vldiscovery.h:82:#define LED3_PIN                         GPIO_Pin_9  
./Utilities/STM32vldiscovery.h:83:#define LED3_GPIO_PORT                   GPIOC
./Utilities/STM32vldiscovery.h:84:#define LED3_GPIO_CLK                    RCC_APB2Periph_GPIOC



^ STM32F10x device types LD, MD, HD and Value Line

In the file /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h there is a good explanation of the abbreviations LD, MD, HD attached to some STM32F10x microcontroller names:

  57 /*  Tip: To avoid modifying this file each time you need to switch between these
  58         devices, you can define the device in your toolchain compiler preprocessor.
  59 
  60  - Low density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers
  61    where the Flash memory density ranges between 16 and 32 Kbytes.
  62  - Low-density value line devices are STM32F100xx microcontrollers where the Flash
  63    memory density ranges between 16 and 32 Kbytes.
  64  - Medium density devices are STM32F101xx, STM32F102xx and STM32F103xx microcontrollers
  65    where the Flash memory density ranges between 64 and 128 Kbytes.
  66  - Medium-density value line devices are STM32F100xx microcontrollers where the
  67    Flash memory density ranges between 64 and 128 Kbytes.
  68  - High density devices are STM32F101xx and STM32F103xx microcontrollers where
  69    the Flash memory density ranges between 256 and 512 Kbytes.
  70  - XL-density devices are STM32F101xx and STM32F103xx microcontrollers where
  71    the Flash memory density ranges between 512 and 1024 Kbytes.
  72  - Connectivity line devices are STM32F105xx and STM32F107xx microcontrollers.
  73   */

This same header file has some pound includes which may be worth noting, about four hundred lines into this file:

 412 #include "core_cm3.h"
 413 #include "system_stm32f10x.h"
 414 #include <stdint.h>

Even with the value line controller there are just over nine hundred register definitions in STM's standard peripherals library main header file for the STM32F100RB part:

   $ /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x$ grep -n 'Bit definition for' ./*.h | grep register | wc
    902    6320   91086


Looks like there are fourteen GPIO registers defined . . .

$ grep -n 'Bit definition for' ./*.h | grep GPIO     
./STM32f10x.h:2209:/*******************  Bit definition for GPIO_CRL register  *******************/
./STM32f10x.h:2278:/*******************  Bit definition for GPIO_CRH register  *******************/
./STM32f10x.h:2347:/*!<******************  Bit definition for GPIO_IDR register  *******************/
./STM32f10x.h:2365:/*******************  Bit definition for GPIO_ODR register  *******************/
./STM32f10x.h:2383:/******************  Bit definition for GPIO_BSRR register  *******************/
./STM32f10x.h:2418:/*******************  Bit definition for GPIO_BRR register  *******************/
./STM32f10x.h:2436:/******************  Bit definition for GPIO_LCKR register  *******************/
./stm32f10x.h:2209:/*******************  Bit definition for GPIO_CRL register  *******************/
./stm32f10x.h:2278:/*******************  Bit definition for GPIO_CRH register  *******************/
./stm32f10x.h:2347:/*!<******************  Bit definition for GPIO_IDR register  *******************/
./stm32f10x.h:2365:/*******************  Bit definition for GPIO_ODR register  *******************/
./stm32f10x.h:2383:/******************  Bit definition for GPIO_BSRR register  *******************/
./stm32f10x.h:2418:/*******************  Bit definition for GPIO_BRR register  *******************/
./stm32f10x.h:2436:/******************  Bit definition for GPIO_LCKR register  *******************/


As we saw in compiler directive error messages a few days ago, a particular STM32F microcontroller part number needs be called out in order for conditional stuff in header files, including System Core Clock variable to be declared at compile time. Here are references to variable SystemCoreClock:

./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h:52:extern uint32_t SystemCoreClock;          /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h:79:extern void SystemCoreClockUpdate(void);
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:112:  uint32_t SystemCoreClock         = SYSCLK_FREQ_HSE;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:114:  uint32_t SystemCoreClock         = SYSCLK_FREQ_24MHz;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:116:  uint32_t SystemCoreClock         = SYSCLK_FREQ_36MHz;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:118:  uint32_t SystemCoreClock         = SYSCLK_FREQ_48MHz;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:120:  uint32_t SystemCoreClock         = SYSCLK_FREQ_56MHz;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:122:  uint32_t SystemCoreClock         = SYSCLK_FREQ_72MHz;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:124:  uint32_t SystemCoreClock         = HSI_Value;        /*!< System Clock Frequency (Core Clock) */
./CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c:167:  *         SystemCoreClock variable.



^ The dot S File

Somehow we need to include the 'dot s' file /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/arm/startup_stm32f10x_md_vl.s in our instance of STMicro's SysTick demo project. This file calls some processor-initializing code before routine int main() starts. This fact per comments in SysTick demo source file main.c . . .

int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */

Our challenge seems to be to direct gcc and related tools to bring together C sources and pre-existing assembly or 'dot s' files. Here is a reference which talks about coding syntax in C and assembly but is missing details of makefile syntax for GCC:

More a reference on crafting makefile to handle assembled files along with source files:

An article on bare metal programming of an ARM Cortex-M9 which gets closer to what we need, though assembly file is purely assembly here:

How to preprocess assembly files with C'ism:


2018-05-09 Searching via Google with phrase "STM32f compile demo project Linux .s file":

Searching with phrase "arm-none-eabi-gcc assembly .s file":

Shukra site, golden . . .


Our invocations of arm-none-eabi-gcc and arm-none-eabi-as so far, where .s files seem to not work at all and .S files trigger some processing:

  983  /usr/bin/arm-none-eabi-as -g -mcpu=cortex-m3 -mthumb startup_stm32f10x_md_vl.s -o startup_stm32f10x_md_vl.o
  987  /usr/bin/arm-none-eabi-as -g -mcpu=cortex-m3 -mthumb startup_stm32f10x_md_vl.S -o startup_stm32f10x_md_vl.o
  988  /usr/bin/arm-none-eabi-gcc -g -mcpu=cortex-m3 -mthumb startup_stm32f10x_md_vl.S -o startup_stm32f10x_md_vl.o
  989  /usr/bin/arm-none-eabi-gcc -x startup_stm32f10x_md_vl.S
  990  /usr/bin/arm-none-eabi-gcc -x assembler-with-cpp startup_stm32f10x_md_vl.S


^ edit point

On writing ARM assembly - looking for examples of assembly files with different comment styles:



^ GCC manual page

From gcc's manual page:

       Preprocessor Options
           -Aquestion=answer -A-question[=answer] -C  -dD  -dI  -dM  -dN -Dmacro[=defn]  -E  -H -idirafter dir -include file
           -imacros file -iprefix file  -iwithprefix dir -iwithprefixbefore dir  -isystem dir -imultilib dir -isysroot dir -M  -MM
           -MF  -MG  -MP  -MQ  -MT  -nostdinc -P  -fdebug-cpp -ftrack-macro-expansion -fworking-directory -remap -trigraphs  -undef
           -Umacro -Wp,option -Xpreprocessor option

       Assembler Option
           -Wa,option  -Xassembler option

-E tells gcc to stop after preprocessing. Says nothing about how default preprocessing of gcc handles given input files.



^ GNU assembler versus ARM assembler

Assembly files written in ARM assembler syntax won't assemble using GNU `as`, per Stack Overflow forum post 20301140:

Here is some work compiling an3268 SysTick demo source file main.c to the assembly stage, using GNU arm-none-eabi-gcc:

Systick main dot c to assembly Systick main dot c to assembly


Search for ARM assembler which is not GNU based, and available on Debian-like systems (also why QEMU needs code which ends which an infinite loop):



^ Startup and linker files in STCube1 libraries

About to examine following start-up assembly files for STM32F100xb type microcontrollers . . .

user@localhost:~/Downloads/stm/STM32Cube_FW_F1_V1.6.0$ find . -name 'startup_stm32f100*'

./Projects/STM32VL-Discovery/Templates/TrueSTUDIO/startup_stm32f100xb.s
./Projects/STM32VL-Discovery/Templates/EWARM/startup_stm32f100xb.s
./Projects/STM32VL-Discovery/Templates/MDK-ARM/startup_stm32f100xb.s
./Projects/STM32VL-Discovery/Templates_LL/EWARM/startup_stm32f100xb.s
./Projects/STM32VL-Discovery/Templates_LL/MDK-ARM/startup_stm32f100xb.s

Ah sure enough! Some of these start-up assembly files are written in GNU gcc syntax, just what we need! TrueSTUDIO instance of file startup_stm32f100xb.s is written and assembles properly via arm-none-eabi-as.

So we've been trying to build and run an AN3268 demo firmware, using a makefile template of two makefiles from Indiana State Geoffy Brown, which should be ok as `make` is a tool and not a mix of two different libraries. There is however also a matter of a linker script which sets out things like where object file code gets put into memory. We were referencing a GNU assember incompatible start-up file and changed that. May we also be referencing an incompatible linker script in our instance / copy of AN3268 SysTick demo firmwares? Here are the first linker scripts found, working up dir by dir from the location of the start-up file:

/opt/lib/an3268/stm32vldiscovery_package$ find . -name '*.ld'
./Project/Master Workspace/TrueSTUDIO/stm32_flash.ld
./Project/Demo/TrueSTUDIO/DISCOVER/STM32F100RB_FLASH.ld
./Project/Examples/STANDBY Mode/TrueSTUDIO/stm32_flash.ld
./Project/Examples/IWDG/TrueSTUDIO/stm32_flash.ld
./Project/Examples/Sleep Mode/TrueSTUDIO/stm32_flash.ld
./Project/Examples/JTAG Remap/TrueSTUDIO/stm32_flash.ld
./Project/Examples/WWDG/TrueSTUDIO/stm32_flash.ld
./Project/Examples/DMA/TrueSTUDIO/stm32_flash.ld
./Project/Examples/EXTI/TrueSTUDIO/stm32_flash.ld
./Project/Examples/GPIOToggle/TrueSTUDIO/stm32_flash.ld
./Project/Examples/Flash Program/TrueSTUDIO/stm32_flash.ld
./Project/Examples/STOP Mode/TrueSTUDIO/stm32_flash.ld
./Project/Examples/RCC/TrueSTUDIO/stm32_flash.ld
./Project/Examples/SysTick/TrueSTUDIO/stm32_flash.ld


^ Linker script syntax

Keywords: linker scripts, multiple linker scripts to ld
linker scripts Ok now that we can compile assembly files, those ending in .s which are written in GNU toolchain syntax we have a binary we've flashed to the dev board. But no action! Debugging is different and more constrained in a development board than in a PC with operating system environment. Could there be something wrong with our linker script?

Golden . . .

From Sourceware reference we learn that GNU linker `ld` can accept at least two linker files. We just wrote one and passed it to linker in an amendment in our local project makefile. Here is the linker script which defines a symbol that is in Geoffry's template linker script but not in STM AN3268 TrueSTUDIO template linker script. We named this linker file 'extra-linker-directives.ld' . . .

/* comment */

SECTIONS
{
     PROVIDE ( _exit = _ebss );
}

Here are the changes we made to makefiles to reference this new linker file:

$ grep -nr EXTRA_LINKER_SCRIPT ./*
./Makefile.common:81:LDFLAGS+= -T$(LDSCRIPT) $(EXTRA_LINKER_SCRIPT) -mthumb -mcpu=cortex-m3 
./SysTick/Makefile:54:EXTRA_LINKER_SCRIPT=extra-linker-directives.ld
./UART_Printf/Makefile.common:91:LDFLAGS+= -T$(LDSCRIPT) $(EXTRA_LINKER_SCRIPT) -mthumb -mcpu=cortex-m3 
./makefile--geoffry-brown-stm32f-master-template.common:81:LDFLAGS+= -T$(LDSCRIPT) $(EXTRA_LINKER_SCRIPT) -mthumb -mcpu=cortex-m3

$

The gcc -T option is mentioned on [... GNU's gcc page on link options], and includes this comment which we seem to be running into as an issue on an NXP1114 embedded demo project,


    "-T script
      Use script as the linker script. This option is supported by most systems using the GNU linker. On some targets, such as bare-board targets without an operating system, the -T option may be required when linking to avoid references to undefined symbols."


So we've modified out project to use a new linker script, and this second linker script which provides one additional variable assignment to `ld`. Still no visible working of SysTick AN3268 demo . . . tried some other things. Strangely calls to STMDiscovery.c routine ...LEDOff() seem to turn one or the other of LED3 (GPIOC_9) and LED4 (GPIOC_8) on rather than off. Now looking for beginner blink-LED programs for the STM32F100 Discovery board . . .


^ First Steps To GPIO 'Hello World'

The following article shows a couple things, a project which seems to omit any .s type start-up file. Also there's comment in the main.c file above a while(1) construct, that this infinite loop is important to keep the micro from running unintended code should some code be loaded beyond the end of the intended firmware:

In AN3268 SysTick demo in source file main.c it's not obvious where or whether GPIOC clock settings are taking place. Again there is mention in main.c of a call to SystemInit(), which doesn't appear as a function in the SysTick project directory, and doesn't appear to be a fully defined function in startup_stm32f10x_md_vl.s. In yesterday's May 10 tests to compile to the point of a .s file the source file main.c we had to include several other .h files which probably correspond at least some of them to .c files, one of which may hold the function SystemInit(). The files we needed to symbolically link to in that small work are:

~/projects/stm32f/assembly-tests$ ls -l
total 104
-rw-r--r-- 1 user user  1787 May  9 14:54 Makefile.common
lrwxrwxrwx 1 user user    99 May 10 11:04 STM32f10x.h -> /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h
lrwxrwxrwx 1 user user    69 May 10 11:03 STM32vldiscovery.h -> /opt/lib/an3268/stm32vldiscovery_package/Utilities/STM32vldiscovery.h
lrwxrwxrwx 1 user user    83 May 10 11:02 core_cm3.h -> /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/CoreSupport/core_cm3.h
-rw-r--r-- 1 user user 11834 May 10 11:48 main-dot-c-to-assembly.tar.bz2
-rw-r--r-- 1 user user  3810 May  8 08:11 main.c
-rw-r--r-- 1 user user  1695 May  8 11:05 main.h
-rw-r--r-- 1 user user 30218 May 10 11:04 main.s
-rw-r--r-- 1 user user  1768 May 10 11:47 notes.txt
-rw-r--r-- 1 user user  5204 May 10 14:12 startup_stm32f100xb.o
-rw-r--r-- 1 user user 11927 May 10 14:11 startup_stm32f100xb.s
lrwxrwxrwx 1 user user    99 May 10 11:01 stm32f10x.h -> /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/stm32f10x.h
lrwxrwxrwx 1 user user   106 May 10 11:03 system_stm32f10x.h -> /opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.h
drwxr-xr-x 3 user user  4096 May  9 14:55 test-1

Yes, found it! . . .

/opt/lib/an3268/stm32vldiscovery_package/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x$ !grep    ( $ grep -n SystemInit ./* )
grep -n SystemInit ./*
grep: ./startup: Is a directory
./system_stm32f10x.c:153:  static void SystemInit_ExtMemCtl(void); 
./system_stm32f10x.c:172:void SystemInit (void)
./system_stm32f10x.c:216:    SystemInit_ExtMemCtl(); 
./system_stm32f10x.c:380:void SystemInit_ExtMemCtl(void) 
./system_stm32f10x.h:78:extern void SystemInit(void);

Looks like everything gets reset in this function, and there's a lot of registers and bit flags getting reset:

 172 void SystemInit (void)
 173 {
 174   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
 175   /* Set HSION bit */
 176   RCC->CR |= (uint32_t)0x00000001;
 177 
 178   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
 179 #ifndef STM32F10X_CL
 180   RCC->CFGR &= (uint32_t)0xF8FF0000;
 181 #else
 182   RCC->CFGR &= (uint32_t)0xF0FF0000;
 183 #endif /* STM32F10X_CL */
 184 
 185   /* Reset HSEON, CSSON and PLLON bits */
 186   RCC->CR &= (uint32_t)0xFEF6FFFF;
 187 
 188   /* Reset HSEBYP bit */
 189   RCC->CR &= (uint32_t)0xFFFBFFFF;
 190 
 191   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
 192   RCC->CFGR &= (uint32_t)0xFF80FFFF;
 193  172 void SystemInit (void)
 173 {
 174   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
 175   /* Set HSION bit */
 176   RCC->CR |= (uint32_t)0x00000001;
 177 
 178   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
 179 #ifndef STM32F10X_CL
 180   RCC->CFGR &= (uint32_t)0xF8FF0000;
 181 #else
 182   RCC->CFGR &= (uint32_t)0xF0FF0000;
 194 #ifdef STM32F10X_CL 172 void SystemInit (void)
 173 {
 174   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
 175   /* Set HSION bit */
 176   RCC->CR |= (uint32_t)0x00000001;
 177 
 178   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
 179 #ifndef STM32F10X_CL
 180   RCC->CFGR &= (uint32_t)0xF8FF0000;
 181 #else
 182   RCC->CFGR &= (uint32_t)0xF0FF0000;
 195   /* Reset PLL2ON and PLL3ON bits */
 196   RCC->CR &= (uint32_t)0xEBFFFFFF;
 197 
 198   /* Disable all interrupts and clear pending bits  */
 199   RCC->CIR = 0x00FF0000;
 200 
 201   /* Reset CFGR2 register */
 202   RCC->CFGR2 = 0x00000000;
 203 #elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL)
 204   /* Disable all interrupts and clear pending bits  */
 205   RCC->CIR = 0x009F0000;
 206 
 207   /* Reset CFGR2 register */
 208   RCC->CFGR2 = 0x00000000;
 209 #else
 210   /* Disable all interrupts and clear pending bits  */
 211   RCC->CIR = 0x009F0000;
 212 #endif /* STM32F10X_CL */
 213 
 214 #if defined (STM32F10X_HD) || (defined STM32F10X_XL)
 215   #ifdef DATA_IN_ExtSRAM
 216     SystemInit_ExtMemCtl();
 217   #endif /* DATA_IN_ExtSRAM */
 218 #endif
 219 
 220   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
 221   /* Configure the Flash Latency cycles and enable prefetch buffer */
 222   SetSysClock();
 223 }

Function SetSystemClock() is defined:

 339 /**
 340   * @brief  Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
 341   * @param  None
 342   * @retval None
 343   */
 344 static void SetSysClock(void)
 345 {
 346 #ifdef SYSCLK_FREQ_HSE
 347   SetSysClockToHSE();
 348 #elif defined SYSCLK_FREQ_24MHz
 349   SetSysClockTo24();
 350 #elif defined SYSCLK_FREQ_36MHz
 351   SetSysClockTo36();
 352 #elif defined SYSCLK_FREQ_48MHz
 353   SetSysClockTo48();
 354 #elif defined SYSCLK_FREQ_56MHz
 355   SetSysClockTo56();
 356 #elif defined SYSCLK_FREQ_72MHz
 357   SetSysClockTo72();
 358 #endif


^ STM32F10x Demo Projects and Exercises



^ USART work in STM32F10x context

Looking for USART project or demonstration firmware for the STM32F10x Discovery board . . .

~/Downloads/stm/STM32Cube_FW_F1_V1.6.0/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:298:__weak void HAL_IncTick(void)

In the newer STCube peripherals library there is a group of UART demo firmwares, the most simple of which appears to be in directory:

~/Downloads/stm/STM32Cube_FW_F1_V1.6.0/Projects/STM32VL-Discovery/Examples/UART/UART_Printf

So we're running into a link time problem, where the GNU linker doesn't know where to find definitions of certain STM32F library functions. In the STM32Cube Drivers subdirectory, there's no makefile nor any instructions for building a shared object or similar type of library file. I seem to recall reading that the STM32F libraries are configured and used in a way different and non-standard with respect to libc6 and most C libraries. Here's the complaint from the linker when we try to build UART_Printf with a makefile we're building from the ground up:

~/projects/stm32f/UART_Printf$ make

- SCD30 demo mafile - including common makefile after all var' assignments and recipe declarations . . .
- Makefile.common - setting variable ELF to 'uart-printf.elf'
- Makefile.common - variable TEMPLATEROOT holds '..',
- Makefile.common - just set vpath to '',
- Makefile.common - trying to print vpath value by double dollar sign syntax . . . '',
- Makefile.common - declaring recipes to convert, compile, clean and debug demo project . . .
- Makefile.common - SKIPPING pulling in dependencies of .o files . . .
- Makefile.common - done.

/usr/bin/arm-none-eabi-gcc -T./TrueSTUDIO/STM32VL-Discovery/STM32F100VB_FLASH.ld  -mthumb -mcpu=cortex-m3  -o uart-printf.elf main.o stm32f1xx_hal_msp.o stm32f1xx_it.o system_stm32f1xx.o 
/home/${USER}/projects/stm32f/UART_Printf/TrueSTUDIO/syscalls.o /home/${USER}/projects/stm32f/UART_Printf/TrueSTUDIO/startup_stm32f100xb.o
main.o: In function `__io_putchar':
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:138: undefined reference to `HAL_UART_Transmit'
main.o: In function `SystemClock_Config':
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:171: undefined reference to `HAL_RCC_OscConfig'
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:184: undefined reference to `HAL_RCC_ClockConfig'
main.o: In function `main':
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:88: undefined reference to `HAL_Init'
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:94: undefined reference to `BSP_LED_Init'
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:113: undefined reference to `HAL_UART_Init'
main.o: In function `Error_Handler':
/home/${USER}/projects/stm32f/UART_Printf/./Src/main.c:200: undefined reference to `BSP_LED_On'
stm32f1xx_hal_msp.o: In function `HAL_UART_MspInit':
/home/${USER}/projects/stm32f/UART_Printf/./Src/stm32f1xx_hal_msp.c:90: undefined reference to `HAL_GPIO_Init'
/home/${USER}/projects/stm32f/UART_Printf/./Src/stm32f1xx_hal_msp.c:95: undefined reference to `HAL_GPIO_Init'
stm32f1xx_hal_msp.o: In function `HAL_UART_MspDeInit':
/home/${USER}/projects/stm32f/UART_Printf/./Src/stm32f1xx_hal_msp.c:114: undefined reference to `HAL_GPIO_DeInit'
/home/${USER}/projects/stm32f/UART_Printf/./Src/stm32f1xx_hal_msp.c:116: undefined reference to `HAL_GPIO_DeInit'
stm32f1xx_it.o: In function `SysTick_Handler':
/home/${USER}/projects/stm32f/UART_Printf/./Src/stm32f1xx_it.c:158: undefined reference to `HAL_IncTick'
collect2: error: ld returned 1 exit status
../Makefile.common:97: recipe for target 'uart-printf.elf' failed
make: *** [uart-printf.elf] Error 1

~/projects/stm32f/UART_Printf$

^ edit point - undefined references fixed by including STM32Cube library sources

So we see an undefined referernce to HAL_UART_Transmit and perform a search for this pattern at the top level of our unzipped STM32Cube library download. There are many references to the first function GNU ld cannot find, but just one definition in file stm32f1xx_hal_uart.c on line 645:

~/Downloads/stm/STM32Cube_FW_F1_V1.6.0$ grep -nr HAL_UART_Transmit ./*
   .
   .
   .
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c:645:HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c:815:HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c:904:HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
./Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h:637:HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
./Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h:639:HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
./Drivers/STM32F1xx_HAL_Driver/Inc/stm32f1xx_hal_uart.h:641:HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
   .
   .

^ edit point - STM32Cube UART_Printf library source file dependencies

Will it be enough then to include this source file among our list of sources, expressed in our makefile? Let's try . . . ok we're getting somewhere. Looks like we need to refactor some of the vpath %.c clauses in the common makefile taken as a template and starting point from Professor Geoffry Brown's work. Here noting some of the Hardware Abstraction Layer set-up routines from STM, and which source files in which they're defined . . . full path to 'Drivers' directory is /home/user/Downloads/stm/STM32Cube_FW_F1_V1.6.0:

./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c:263      . . . provides HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef  *RCC_OscInitStruct)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c:645     . . . provides HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c:158          . . . provides HAL_StatusTypeDef HAL_Init(void)
./Drivers/BSP/STM32VL-Discovery/stm32vl_discovery.c:110         . . . provides void BSP_LED_Init(Led_TypeDef Led)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c:196     . . . provides void HAL_GPIO_Init(GPIO_TypeDef  *GPIOx, GPIO_InitTypeDef *GPIO_Init)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c:381      . . . provides HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c:247   . . . provides uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)



Figure x - first captures of UART_Printf demo firmware output using minicom:

Welcome to minicom 2.7

OPTIONS: I18n 
Compiled on Apr 25 2017, 21:26:52.
Port /dev/ttyUSB0, 12:47:52

Press CTRL-A Z for help on special keys


vib.a.y..7~in#f 3us?zon.F?.Hth+ +/x)TS.e. #->nt 3inKsC+.6.s+|es_7vlys2e* S~
vib.ary..7~in#f 3us?zon #o #h+ +/x)TS.e* #->nt 3inKsC+.6.s+|es_7vlys2e* S~
vibra.y..7~in#f 3us?zon.F?.Hth+ UAR#MqC*S.2Ues# 3inKsC+.6.s+|es_7vlys2e* S~
vib.a.y...in#f 3us?zon.F?.Hth+ +/x)TS.e* #->nt 3inKsC+.6.s+|es_7vlys2e* S~
library printf function to the UART                <-- this line copied and pasted from project main.c - TMH






CTRL-A Z for help | 9600 7N1 | NOR | Minicom 2.7 | VT102 | Offline | ttyUSB0

Looks like there's a timing issue. Project readme.txt file mentions the project as is being based on a 24MHz system clock, but our board has just 8Mhz crystal driving the microcontroller.

^ edit point - STM32Cube printf() and f_printf() functions

Searching for STM32Cube printf() function . . .

./Middlewares/Third_Party/FatFs/src/ff.c:4654:int f_printf (


^ edit point - adjusting baud rate on the fly

Trying to change baud rate on the fly to diagnose the severely garbled message strings coming from our instance of UART_Printf project . . . but where is UART_HandleTypeDef defined among all the STM32Cube v1.6.0 files? This is some kind of structure, with data members being set once at the top of routine int main() in main.c of UART_Printf project as follows:

  /*##-1- Configure the UART peripheral ######################################*/
  /* Put the USART peripheral in the Asynchronous mode (UART Mode) */
  /* UART configured as follows:
      - Word Length = 8 Bits (7 data bit + 1 parity bit) : BE CAREFUL : Program 7 data bits + 1 parity bit in PC HyperTerminal
      - Stop Bit    = One Stop bit 
      - Parity      = ODD parity
      - BaudRate    = 9600 baud
      - Hardware flow control disabled (RTS and CTS signals) */
  UartHandle.Instance        = USARTx;

  UartHandle.Init.BaudRate   = 2400;                 // 2018-05-23 - was 9600
  UartHandle.Init.WordLength = UART_WORDLENGTH_8B;   // 2018-05-23 - could be UART_WORDLENGTH_9B, see header file named stm32f1xx_hal_uart.h - TMH
  UartHandle.Init.StopBits   = UART_STOPBITS_1;
  UartHandle.Init.Parity     = UART_PARITY_ODD;
  UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
  UartHandle.Init.Mode       = UART_MODE_TX_RX;

  if (HAL_UART_Init(&UartHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }

Ah but hey, look at that last IF statement which calls a routine HAL_UART_Init(...), which we missed earlier today. Most likely we need to call that in order to change baud rate while a program is running in our development board, and after it has already been set to a value. Will be interesting however to see how that routine works, and whether we can call something smaller or perform a local assignment in a routine of our immediate project, rather than calling a library routine to adjust one integer type parameter . . .

The data structure UART_HandleTypeDef is defined in ~/Downloads/stm/STM32Cube_FW_F1_V1.6.0/Drivers/STM32F1xx_HAL_Driver/Inc/./stm32f1xx_hal_uart.h as follows:

156 /**
157   * @brief  UART handle Structure definition
158   */
159 typedef struct
160 { 
161   USART_TypeDef                 *Instance;        /*!< UART registers base address        */
162   
163   UART_InitTypeDef              Init;             /*!< UART communication parameters      */
164   
165   uint8_t                       *pTxBuffPtr;      /*!< Pointer to UART Tx transfer Buffer */
166   
167   uint16_t                      TxXferSize;       /*!< UART Tx Transfer size              */
168   
169   __IO uint16_t                 TxXferCount;      /*!< UART Tx Transfer Counter           */
170   
171   uint8_t                       *pRxBuffPtr;      /*!< Pointer to UART Rx transfer Buffer */
172   
173   uint16_t                      RxXferSize;       /*!< UART Rx Transfer size              */
174   
175   __IO uint16_t                 RxXferCount;      /*!< UART Rx Transfer Counter           */
176   
177   DMA_HandleTypeDef             *hdmatx;          /*!< UART Tx DMA Handle parameters      */
178   
179   DMA_HandleTypeDef             *hdmarx;          /*!< UART Rx DMA Handle parameters      */
180   
181   HAL_LockTypeDef               Lock;             /*!< Locking object                     */
182   
183   __IO HAL_UART_StateTypeDef    gState;           /*!< UART state information related to global Handle management
184                                                        and also related to Tx operations.
185                                                        This parameter can be a value of @ref HAL_UART_StateTypeDef */
186   
187   __IO HAL_UART_StateTypeDef    RxState;          /*!< UART state information related to Rx operations.
188                                                        This parameter can be a value of @ref HAL_UART_StateTypeDef */
189   
190   __IO uint32_t                 ErrorCode;        /*!< UART Error code                    */
191 }UART_HandleTypeDef;

This data structure references another data structure which entails lower level details, including baud rate:

 62 /**
 63   * @brief UART Init Structure definition
 64   */
 65 typedef struct
 66 { 
 67   uint32_t BaudRate;                  /*!< This member configures the UART communication baud rate.
 68                                            The baud rate is computed using the following formula:
 69                                            - IntegerDivider = ((PCLKx) / (16 * (huart->Init.BaudRate)))
 70                                            - FractionalDivider = ((IntegerDivider - ((uint32_t) IntegerDivider)) * 16) + 0.5 */
 71   
 72   uint32_t WordLength;                /*!< Specifies the number of data bits transmitted or received in a frame.
 73                                            This parameter can be a value of @ref UART_Word_Length */
 74   
 75   uint32_t StopBits;                  /*!< Specifies the number of stop bits transmitted.
 76                                            This parameter can be a value of @ref UART_Stop_Bits */
 77   
 78   uint32_t Parity;                    /*!< Specifies the parity mode.
 79                                            This parameter can be a value of @ref UART_Parity 
 80                                            @note When parity is enabled, the computed parity is inserted
 81                                                  at the MSB position of the transmitted data (9th bit when
 82                                                  the word length is set to 9 data bits; 8th bit when the
 83                                                  word length is set to 8 data bits). */
 84   
 85   uint32_t Mode;                      /*!< Specifies whether the Receive or Transmit mode is enabled or disabled.
 86                                            This parameter can be a value of @ref UART_Mode */
 87   
 88   uint32_t HwFlowCtl;                 /*!< Specifies whether the hardware flow control mode is enabled or disabled.
 89                                            This parameter can be a value of @ref UART_Hardware_Flow_Control */
 90   
 91   uint32_t OverSampling;              /*!< Specifies whether the Over sampling 8 is enabled or disabled, to achieve higher speed (up to fPCLK/8).
 92                                            This parameter can be a value of @ref UART_Over_Sampling. This feature is only available
 93                                            on STM32F100xx family, so OverSampling parameter should always be set to 16. */
 94 }UART_InitTypeDef;

^ To Activate Floating Point, and Integer Alternative

Notes on floating point encoding: looks like there are some significant memory footprint savings in microcontroller projects, by turning off or not including floating point support in the sprintf family functions. There's mention on an STMicro forum that working integer-wise with exponent and mantissa of a floating point formatted datum, by printing those two parts of the datum in integer format, saves about 6Kb of memory. Forum post is "44899 how to activate floating point for sprintf . . .", see references section for link to this post.

The manual page for gcc says that -u is used to force linking of library modules, by directing gcc to pretend that one or another symbol is not defined:

-u symbol
     Pretend the symbol symbol is undefined, to force linking of library modules to define it.  You can use -u multiple times
     with different symbols to force loading of additional library modules.

Interesting comment on this related post, user says that newlib-nano C library doesn't have floating point support:

If this is the case then for now we'll assume we're using a C library which doesn't implement floating point in its sprintf functions. Let's see how four-byte, also known as single-precision floating point numbers are structured, so that we may correctly parse and format the bits of each measurement value of the SCD30 sensor,


^ Subversion troubles . . .

svn: E175002: Unexpected HTTP status 405 'Method Not Allowed' on '/Alta/air_quality'

svn: E175002: Additional errors:
svn: E175002: PROPFIND request on '/Alta/air_quality' failed: 405 Method Not Allowed
svn: E175002: Your commit message was left in a temporary file:
svn: E175002:    'svn-commit.tmp'

$ # svn mkdir https://...



^ Some SCD30 feedback, full SN partial readings

The following is output from an STM32F100x Value Line Discovery board attached via wires and breadboard to a Sensirion SCD30 carbon dioxide sensor using the sensor's I2C communication facility. Serial number reads out fully, relative humidity and temperature readings appear well within the ballpark for office setting. Carbon dioxide level reading always appears zero. The sensor lamp is flashing, at a rate of 1/3 Hz or 1/4 Hz, tried both these rates via STM32F firmware. This output noted here reflects sensor response to having single-shot measurement commands sent to it . . .


^ SN 436315 gives always zero readings

Top of loop 5
sensor serial number returned is:  436315-434905-73363610


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  0  0,  0 PPM CO2,   humidity 25 %RH   temperature 22 C

Note - any dots in ellipses pattern represent readings coming back all zero:


^ SN 244586

An older fully working sensor returns:

Entering primary loop . . .
Block 5:  starting,
Block 5:  sending sensor command to stop measurement . . .
Block 5:  command routine returns error = 0,
Block 5:  sending sensor command to start single measurement . . .
Block 5:  command routine returns error = 0,
asking sensor whether readings ready . . .
Top of loop 5
sensor serial number returned is:  244586-244594-22606045
CO2 measurement as four bytes and decimal value:   0  0  1 92,  402 PPM CO2,   humidity 27 %RH   temperature 22 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  244586-244594-22606045


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  0 de,  222 PPM CO2,   humidity 27 %RH   temperature 22 C


^ SN 435148

Ok really wierd, we are now getting a new sensor to return non-zero carbon dioxide readings:

while trying i2c address 96 got an 'ACK_ERROR',
changing i2c address to 97 . . .
querying sensor for its serial number to see whether we get an 'ACK' . . .
querying sensor for its serial number . . . 
sensor serial number is 435148-436657-73370497,
reading SCD30 sensor article code . . .
setting SCD30 CO2 measurement interval to 5 seconds . . .
starting periodic CO2 measurements . . .

Entering primary loop . . .
Block 5:  starting,
Block 5:  sending sensor command to stop measurement . . .
Block 5:  command routine returns error = 0,
Block 5:  sending sensor command to start single measurement . . .
Block 5:  command routine returns error = 0,
asking sensor whether readings ready . . .
Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  a 7e,  2686 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  5 91,  1425 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  5 4d,  1357 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  5 26,  1318 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  4 fc,  1276 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  435148-436657-73370497


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  5 27,  1319 PPM CO2,   humidity 25 %RH   temperature 23 C

Note - any dots in ellipses pattern represent readings coming back all zero:


^ SN 434757

 UART Printf Example: retarget the C library printf function to the UART
** Test finished successfully. ** 
Beginning tests with i2c address set to 94 . . .
pausing a bit, about 3 seconds . . . 
*** routine SCD30_ReadSerialNumber() returns error value of 1,
while trying i2c address 94 got an 'ACK_ERROR',
changing i2c address to 95 . . .
querying sensor for its serial number to see whether we get an 'ACK' . . .
while trying i2c address 95 got an 'ACK_ERROR',
changing i2c address to 96 . . .
querying sensor for its serial number to see whether we get an 'ACK' . . .
while trying i2c address 96 got an 'ACK_ERROR',
changing i2c address to 97 . . .
querying sensor for its serial number to see whether we get an 'ACK' . . .
querying sensor for its serial number . . . 
sensor serial number is 434757-436167-73372247,
reading SCD30 sensor article code . . .
setting SCD30 CO2 measurement interval to 5 seconds . . .
starting periodic CO2 measurements . . .

Entering primary loop . . .
Block 5:  starting,
Block 5:  sending sensor command to stop measurement . . .
Block 5:  command routine returns error = 0,
Block 5:  sending sensor command to start single measurement . . .
Block 5:  command routine returns error = 0,
asking sensor whether readings ready . . .
Top of loop 5
sensor serial number returned is:  434757-436167-73372247


Block 5:  sensor says readings not ready,
. PFR routine ReadMeasurementBuffer() returns non-zero error 2,
tart meas
'start meas' returns 0,
asking sensor if data ready . . .


Top of loop 5
sensor serial number returned is:  434757-436167-73372247


Block 5:  sensor says readings not ready,
CO2 measurement as four bytes and decimal value:   0  0  0  0,  0 PPM CO2,   humidity 24 %RH   temperature 24 C

Note - any dots in ellipses pattern represent readings coming back all zero:
start meas
'start meas' returns 0,
asking sensor if data ready . . .


^ References


- - - top of page - - -