4

I'm trying the light an LED (on port c, pin 13) on STM32F103C8T6. I'm not using IDE. Code:

#include "include/stm32f10x.h"

int main()
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

    GPIOC->CRH  &= ~GPIO_CRH_CNF13;
    GPIOC->CRH  |=  GPIO_CRH_MODE13_0;

    GPIOC->BSRR  = GPIO_BSRR_BR13;

    while(1)
    {
        GPIOC->BSRR = GPIO_BSRR_BS13;
    }

    return 0;
}

Links to include files in include directory:

system_stm32f10x.h

core_cmInstr.h

core_cmFunc.h

core_cm3.h

stm32f10x.h part1

stm32f10x.h part2

That's how I compile it

arm-none-eabi-gcc --specs=nosys.specs -o output led.c

After uploading it to mc nothing happens.

Clifford
  • 88,407
  • 13
  • 85
  • 165
Олег
  • 67
  • 1
  • 5
  • Are you sure there is an LED connected to pin C13, and that it's configured as active-high? –  Jan 07 '18 at 01:25
  • To be sure, could you write a configuration that I need? Seems like right now I have output mode 10 MHz, general purpose output push-pull. Yes, it's in PC13. – Олег Jan 07 '18 at 02:02
  • The "configuration" of the LED that I'm referring to is hardware, not software. –  Jan 07 '18 at 03:13
  • 1
    _"STM32F103C8T6"_ specifies the microcontroller - there is no _"the LED"_. Any LED will be specific to your board; in which case you need to specify the board you are using or indicate how the LED is connected to the pin (a schematic image perhaps). However the obvious thing to try is set it low rather then high - the "on" state is dependent on how the LED is connected. – Clifford Jan 07 '18 at 17:17

1 Answers1

8

to light the led on a blue pill you need PC13 low (reset) so write with reset bit 13 set in the gpioc bsrr register, then end the program, making the gpio line go high turns off the led.

#include "include/stm32f10x.h"

int main()
{
    RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;

    GPIOC->CRH  &= ~GPIO_CRH_CNF13;
    GPIOC->CRH  |=  GPIO_CRH_MODE13_0;

    GPIOC->BSRR  = GPIO_BSRR_BR13;

    while(1)
    {
        continue;
    }

    return 0;
}

Just look at the schematic.

Understand this is not a universal truth that low is on. You have to look at the design of the board. Also not all stm32f103c8t6 chips have an led on that pin, but I assume this is an stm32 "blue pill" board.

EDIT

a complete working blinker example for that board

flash.ld

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

flash.s

.cpu cortex-m0
.thumb


.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang

.thumb_func
reset:
    bl notmain
    b hang
.thumb_func
hang:   b .

.align

.thumb_func
.globl PUT16
PUT16:
    strh r1,[r0]
    bx lr

.thumb_func
.globl PUT32
PUT32:
    str r1,[r0]
    bx lr

.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr

.thumb_func
.globl dummy
dummy:
    bx lr

.end

blinker01.c

void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );

#define GPIOCBASE 0x40011000
#define RCCBASE 0x40021000

int notmain ( void )
{
    unsigned int ra;
    unsigned int rx;

    ra=GET32(RCCBASE+0x18);
    ra|=1<<4; //enable port c
    PUT32(RCCBASE+0x18,ra);
    //config
    ra=GET32(GPIOCBASE+0x04);
    ra&=~(3<<20);   //PC13
    ra|=1<<20;      //PC13
    ra&=~(3<<22);   //PC13
    ra|=0<<22;      //PC13
    PUT32(GPIOCBASE+0x04,ra);

    for(rx=0;;rx++)
    {
        PUT32(GPIOCBASE+0x10,1<<(13+0));
        for(ra=0;ra<200000;ra++) dummy(ra);
        PUT32(GPIOCBASE+0x10,1<<(13+16));
        for(ra=0;ra<200000;ra++) dummy(ra);
    }
    return(0);
}

build

arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m3 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m0 -march=armv6-m -c blinker01.c -o blinker01.thumb.o
arm-none-eabi-ld -o blinker01.thumb.elf -T flash.ld flash.o blinker01.thumb.o
arm-none-eabi-objdump -D blinker01.thumb.elf > blinker01.thumb.list
arm-none-eabi-objcopy blinker01.thumb.elf blinker01.thumb.bin -O binary
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m3 -march=armv7-m -c blinker01.c -o blinker01.thumb2.o
arm-none-eabi-ld -o blinker01.thumb2.elf -T flash.ld flash.o blinker01.thumb2.o
arm-none-eabi-objdump -D blinker01.thumb2.elf > blinker01.thumb2.list
arm-none-eabi-objcopy blinker01.thumb2.elf blinker01.thumb2.bin -O binary

builds both with and without thumb2 extensions (flash.s doesnt have to be thumb only, just leftovers from prior examples).

now what file and how are you uploading it to the mcu? loading an elf does you no good there isnt an operating system but depending on the tool you are using it may read elf and download the loadable portions. I wrote my own tool since it is so simple to interface with the bootloader uart interface. I have also used openocd with various swd/jtag interfaces (stlink, j-link), to write these. They come from asia locked so the first time you have to unlock them, know you can do it from the uart interface, pretty sure I figured it out from openocd as well...

So either your binary build is bad/wont boot right, or the download is the issue (or both).

the flash in the stm32 maps at 0x08000000, they re-map it to 0x00000000 if/when booting from the application. Should be able to use 0x00000000 as well, but most I have seen use 0x08000000. As documented the first word is loaded into the stack pointer on reset, the second word is the thumb address to the reset vector (lsbit is set to indicate thumb so 0x41 below means the reset vector is at address 0x40 as shown)

08000000 <_start>:
 8000000:   20001000    andcs   r1, r0, r0
 8000004:   08000041    stmdaeq r0, {r0, r6}
 8000008:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 800000c:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000010:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000014:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000018:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 800001c:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000020:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000024:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000028:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 800002c:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000030:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000034:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 8000038:   08000047    stmdaeq r0, {r0, r1, r2, r6}
 800003c:   08000047    stmdaeq r0, {r0, r1, r2, r6}

08000040 <reset>:
 8000040:   f000 f80a   bl  8000058 <notmain>
 8000044:   e7ff        b.n 8000046 <hang>

08000046 <hang>:
 8000046:   e7fe        b.n 8000046 <hang>

You have to resolve this for starters, then once you have something with a chance of booting, then you can look at the code.

old_timer
  • 69,149
  • 8
  • 89
  • 168
  • Same result and yes, I'm using the blue pill. – Олег Jan 07 '18 at 03:38
  • you will have to show us a dump/disassembly of your binary starting with the vector table and go from there. – old_timer Jan 07 '18 at 12:56
  • I'm familiar with assembly just for a little bit, so I just did `arm-none-eabi-objdump -d output` [link to output](https://pastebin.com/rt0pqiS5). Is it enugh? – Олег Jan 07 '18 at 14:32
  • well there is your first problem it is built wrong, the linker script for starters is putting it in the wrong place, you are building for linux-ish essentially. no vector table – old_timer Jan 07 '18 at 14:48
  • 1
    While suggesting reversing the logic is reasonable - or even obvious (to someone with experience and basic knowledge of electronics), I am intrigued that you are able to assume the specific board used. Given that there are many STM32 COTS boards and a developer may be working on an in-house design, I am intrigued at how you came to that assumption with such apparent certainty. I've been working on STM32 for 9 years and had never heard of this board until you mentioned it here. – Clifford Jan 07 '18 at 17:09
  • I think I have answred my own quetion http://wiki.stm32duino.com/index.php?title=Blue_Pill states one user LED and explicitly states _"PC13 (lights when PC13 is LOW)"_. That would explain why he said _"the LED"_ rather than _"an LED"_; I shall roll back that change, but the OP should perhaps specify the board. – Clifford Jan 07 '18 at 17:14
  • @Clifford it was an educated guess (with an emphasis on guess, call it slightly better than dumb luck). PC13 seemed like an odd choice, but I have these boards and recognized the part number so like the nucleo and popular discovery boards this and the other blue one are going to show up here. They dont have a catchy name for the other blue board on ebay that is cortex-m0 based. – old_timer Jan 08 '18 at 18:42
  • I had not known about the boards either until someone else pointed me at them now ebay searches for stm32 put you in touch with them pretty quick. I dont know how that market works but these things seem to be cloned and or there is one vendor making gobzillions, but the schematic on the arduino or whatever site showed the way the led was tied, so assumed between the part number, the pin the led was connected on and cant get it to light, that it was this board and that off is on. but the problem was worse than that as the vector table was bad. – old_timer Jan 08 '18 at 18:44
  • FYI an stm32f030f4p6 based board is the other blue board coming out of asia similar in look to the "blue pill" but cortex-m0 based and has both an swd/jtag and a uart bootloader set of pins on the back/bottom end. – old_timer Jan 08 '18 at 18:48
  • the cortex-m0 one does not show up locked, the cortex-m3 blue pill one, in addition to the potential problems the OP had/has, it arrives with the flash locked, which is easy to unlock but if this is your first mcu or first stm32, that can trip you up. and was an additional potential candidate for the OP's problem assuming this was a blue pill which it ended up being. – old_timer Jan 08 '18 at 18:49
  • @Clifford if you dont already have one/some of these boards along with the one or few dollar "j-link" boards (usually are purple), you should grab some if for no other reason than they are disturbingly inexpensive. – old_timer Jan 08 '18 at 18:53
  • Could you elaborate on your choice of the `GPIOC_CRH` configuration bits? There seems to be a lot of decisions to make. For example, why is the output max speed set to 10MHz rather than 2MHz or 50MHz? In addition, is there any advantage of using push-pull over open-drain? It looks like the LED already serves as a pull-up resistor, so an open-drain output should suffice. – nalzok Feb 10 '20 at 00:23