## Kategoriearchiv

Du betrachtest das Archiv der Kategorie Embedded.

• ## STM32F3-Discovery: no 72 MHz clock due to HSE never ready

Now what a fun: Unboxed my brand new STM32F3-Discovery, plugged it in – sweet blinking rapture. Compiled my first demo program, played around with the timers, all was so good. Until I had a closer look at the system clock speed: 8 MHz it said. So I dug into the unknown grounds of STM32F3 development, ended up in the generated firmware’s system initialization function in system_stm32f30x.c – which looks like this:

static void SetSysClock(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;

/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);

/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01; // all good
}
else
{
HSEStatus = (uint32_t)0x00; // nah.
}

/* ... */


I did so, only to find out that HSEStatus never switched to 0x01 because the RCC_CR_HSERDY flag was never asserted in the first place.

Obviously no one else in the whole wide web had trouble with this. Cold water? Let’s dive!
Some dude at the ST forums pointed me to the trick to output the RCC clock signal to the board’s PA8 pin, which I did like so:

void InitializeMCOGPIO() {
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);

/* Configure MCO (PA8) */
GPIO_InitTypeDef gpioStructure;
gpioStructure.GPIO_Pin = GPIO_Pin_8;
gpioStructure.GPIO_Speed = GPIO_Speed_50MHz;
gpioStructure.GPIO_Mode = GPIO_Mode_AF;
gpioStructure.GPIO_OType = GPIO_OType_PP;
gpioStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &gpioStructure);

/* Output HSE clock on MCO pin (PA8) */
RCC_MCOConfig(RCC_MCOSource_HSE);
}


Turned out … well, nothing. Flatline on that pin. So I took my multimeter and went upstream from the oscillator pins. Solder bridge SB12, of course bridged, working fine, SB17 open as requested, and then – silence on RB48. No beeps on my meter, no value, just plain high impedance.

To make a long story short: That 100 Ω resistor was borked, so I replaced it with some spare parts of an old scanner board I had floating around in the to-do stash. I’m not exactly known for massive soldering experience, but this video helped a lot here.

Final result:

Ugly but effective. Works like a charm now.

• ## Embedded CLion EAP: forcing arm-eabi-gcc onto cmake on Windows

While CLion may become a good IDE for embedded development, it really struggles with non conformant build scenarios at the time being. As far as building on Windows is concerned, you may either chose a MinGW- or cygwin-based toolchain and that’s it.

CMake, however, being the underlying build system, supports the notion of externally defined toolchains (-D CMAKE_TOOLCHAIN_FILE=...), which may be used to trick CLion into cross-compiling when it really doesn’t want to.

Note that this is merely a hack to get you starting and by no means a full-fledged solution. (Side note: Please share your insights.)

As for my system, I finally went with MinGW (mingw-base 2013072200) as this solution handles paths Windows-like, i.e. without cygwin’s /cygdrive/ mangling; I also installed arm-none-eabi-gcc 4.9.2. Note also that installing the arm-gcc toolchain within cygwin might be an easier solution in the long run.

First, we create a toolchain – in this case for a Cortex-M0+ – like follows:

include(CMakeForceCompiler)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus)

find_program(ARM_CC arm-eabi-gcc
${TOOLCHAIN_DIR}/bin ) find_program(ARM_CXX arm-eabi-g++${TOOLCHAIN_DIR}/bin
)
find_program(ARM_OBJCOPY arm-eabi-objcopy
${TOOLCHAIN_DIR}/bin ) find_program(ARM_SIZE_TOOL arm-eabi-size${TOOLCHAIN_DIR}/bin)

CMAKE_FORCE_C_COMPILER(${ARM_CC} GNU) CMAKE_FORCE_CXX_COMPILER(${ARM_CXX} GNU)

set(CMAKE_C_FLAGS
"${CMAKE_C_FLAGS}" "-fno-common -ffunction-sections -fdata-sections" ) if (CMAKE_SYSTEM_PROCESSOR STREQUAL "cortex-m0plus") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}"
"-mcpu=cortex-m0plus -mthumb"
)

else ()
message(WARNING
"Processor not recognised in toolchain file, "
"compiler flags not configured."
)
endif ()

# fix long strings (CMake appends semicolons)
string(REGEX REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")

set(BUILD_SHARED_LIBS OFF)


In CLion’s Build, Execution, Deployment > CMake settings we then set the CMake Generation options with

-DTOOLCHAIN_DIR:PATH=c:/path/to/arm-eabi/
-DCMAKE_TOOLCHAIN_FILE=toolchain-gcc-arm-eabi.cmake


as can be seen in the following image.

If we weren’t using MinGW but cygwin, CMake would be unable to find the executables given a MinGW-style path (e.g. c:/some/thing); a cygwin-style path (e.g. /cygdrive/c/some/thing) would then have to be used here. However, when the cygwin toolchain is selected in CLion, all source file paths are also presented cygwin-style, which obviously can’t be accessed from a non-cygwin application. Long story short: Know your tools, I didn’t.

Using Help > Show Generated CMake Files in Explorer you can see the generated project files.

Deleting this folder forces a full invalidation of CMake’s generated cache, which might otherwise not happen.

Afterwards you can trigger a regeneration of the cache by using the Reload CMake Project button in the CMake Problem pane.

Now the CMake Cache should show the correct paths.

If you then build your project, CMake will use the crosscompiler and place the binaries in the folder you deleted earlier.