rust-embedded / cortex-m-quickstart

Template to develop bare metal applications for Cortex-M microcontrollers
782 stars 164 forks source link

stm32l432kc flash problem with quickstart template #77

Closed lucazulian closed 4 years ago

lucazulian commented 4 years ago

I have a stm32l432kc and I started a new project with cortex-m-quickstart template. I can build and the with openocd but I have a problem to flash (or load) the binary into the nucleo.

//! Blinks an LED
#![no_std]
#![no_main]

use core::panic::PanicInfo;

extern crate cortex_m;
#[macro_use]
extern crate cortex_m_rt as rt;
extern crate cortex_m_semihosting as sh;
extern crate stm32l4xx_hal as hal;

use crate::hal::prelude::*;
use crate::hal::delay::Delay;
use crate::rt::ExceptionFrame;
use crate::rt::entry;

use core::fmt::Write;
use crate::sh::hio;

#[inline(never)]
#[entry]
fn main() -> ! {

    let mut hstdout = hio::hstdout().unwrap();

    writeln!(hstdout, "Hello, world!").unwrap();

    let cp = cortex_m::Peripherals::take().unwrap();
    let dp = hal::stm32::Peripherals::take().unwrap();

    let mut flash = dp.FLASH.constrain(); // .constrain();
    let mut rcc = dp.RCC.constrain();

    // Try a different clock configuration
    let clocks = rcc.cfgr.hclk(8.mhz()).freeze(&mut flash.acr);

    let mut gpiob = dp.GPIOA.split(&mut rcc.ahb2);
    let mut led = gpiob.pa1.into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper);

    let mut gpiof = dp.GPIOB.split(&mut rcc.ahb2);
    let mut leda = gpiof.pb3.into_push_pull_output(&mut gpiof.moder, &mut gpiof.otyper);

    let mut timer = Delay::new(cp.SYST, clocks);
    loop {
        timer.delay_ms(100 as u32);

        led.set_high();
        leda.set_high();

        timer.delay_ms(100 as u32);

        led.set_low();
        leda.set_low();

        writeln!(hstdout, "ciao").unwrap();
    }
}

#[panic_handler]
#[no_mangle]
pub fn panic(_info: &PanicInfo) -> ! {
    loop{}
}
[package]
authors = ["luca"]
edition = "2018"
readme = "README.md"
name = "app"
version = "0.1.0"

[dependencies]
cortex-m = "0.6.1"
cortex-m-rt = "0.6.10"
cortex-m-semihosting = "0.3.3"
panic-halt = "0.2.0"
alloc-cortex-m = "0.3.5"
embedded-hal = "0.2.1"
generic-array = "0.12.0"
nb = "0.1.0"

[dependencies.stm32l4xx-hal]
version = "0.5.0"
features = ["stm32l4x2"]

[dependencies.stm32l4]
version = "0.8.0"
features = ["stm32l4x2", "rt"]

[dependencies.cast]
default-features = false
version = "0.2.2"

# this lets you use `cargo fix`!
[[bin]]
name = "app"
test = false
bench = false

[profile.release]
codegen-units = 1 # better optimizations
debug = false # symbols are nice and they don't increase the size on Flash
lto = true # better optimizations
panic = "abort"
opt-level = 's'

#[profile.dev]
#panic = "abort"

The memory.x is

MEMORY
{
  /* NOTE K = KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 40K
}

/* This is where the call stack will be allocated. */
/* The stack is of the full descending type. */
/* You may want to use this variable to locate the call stack and static
   variables in different memory regions. Below is shown the default value */
/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */

/* You can use this symbol to customize the location of the .text section */
/* If omitted the .text section will be placed right after the .vector_table
   section */
/* This is required only on microcontrollers that store some configuration right
   after the vector table */
/* _stext = ORIGIN(FLASH) + 0x400; */

/* Example of putting non-initialized variables into custom RAM locations. */
/* This assumes you have defined a region RAM2 above, and in the Rust
   sources added the attribute `#[link_section = ".ram2bss"]` to the data
   you want to place there. */
/* Note that the section will not be zero-initialized by the runtime! */
/* SECTIONS {
     .ram2bss (NOLOAD) : ALIGN(4) {
       *(.ram2bss);
       . = ALIGN(4);
     } > RAM2
   } INSERT AFTER .bss;
*/

If I inspect app I can see

arm-none-eabi-readelf -h app

ELF Header:                                                                     
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00                      
  Class:                             ELF32                                      
  Data:                              2's complement, little endian              
  Version:                           1 (current)                                
  OS/ABI:                            UNIX - System V                            
  ABI Version:                       0                                          
  Type:                              EXEC (Executable file)                     
  Machine:                           ARM                                        
  Version:                           0x1                                        
  Entry point address:               0x80004a3                                  
  Start of program headers:          52 (bytes into file)                       
  Start of section headers:          49632 (bytes into file)                    
  Flags:                             0x5000400, Version5 EABI, hard-float ABI   
  Size of this header:               52 (bytes)                                 
  Size of program headers:           32 (bytes)                                 
  Number of program headers:         3                                          
  Size of section headers:           40 (bytes)                                 
  Number of section headers:         21                                         
  Section header string table index: 19                                         

But the "same" functionality produces in Arduino something like this:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x80002ad
  Start of program headers:          52 (bytes into file)
  Start of section headers:          149912 (bytes into file)
  Flags:                             0x5000400, Version5 EABI, hard-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         3
  Size of section headers:           40 (bytes)
  Number of section headers:         18

The difference here is the Entry point address. If I try to copy

arm-none-eabi-objcopy -O binary app app.bin
cp app.bin /run/media/luca/NODE_L432KC

The binary produced by rust does not start.

therealprof commented 4 years ago

Most likely the problem is the use of semihosting in the code. semihosting requires that the board is hooked up to a debug probe, a debugger is running on the host system and properly set up. Otherwise it will just crash the application and nothing happens.

lucazulian commented 4 years ago

@therealprof now it works! Thanke for helping me!