Skip to main content

Posts

Zephyr Example 1: Blinky

Setting up Zephyr Environment Detailed description about Zephyr environment can be found here . Since most of the prerequisites are common to other development, chances are you already have most of them installed on your computer. Ubuntu and its derivative users may need to uninstall outdated device-tree-compiler package and install new one by building from the source Running a Sample Code Grab one of the board listed as supported , clone the Zephyr source tree , go to one of the sample code directory and run: Default CMake generator is "Unix Makefile". However ninja is way more faster. You can override it by creating a file named PreLoad.cmake with following content: and put it in the same directory as CMakeLists.txt. Additionally you can set the board in the CMakeLists.txt so you don't have to specify in the command line. Note that this line comes before including the boilerplate setting. Blinky We are going to use ST Disco L475 IoT01 board in this ex...

Fixing B-L475E-IOT01A board for reset.

There are at least two revisions of the B-L475E-IOT0A board. Earlier boards (version C) have rather critical bug in the hardware, so the STLink-V2 does not work. This is because the NRST net between STLink and the main MCU is missing in the version C board. For more information, check the manual . Unfortunately the manual didn't describe how to fix it, although it is rather straightforward. Grab a soldering tools and connect two points shown below. On the schematic these two points correspond to and Now, you should be able to run the hello_world example without problem.

STM32 USB MSD with SD Card

Build a low level driver for SD card, then the glue logic for FatFs and USB MSD is pretty much the same as Flash memory case posed before. In case of SD card, sector size is 512 in most of the cases. Thus the memory requirement is much relaxed. You can even allocate a file buffer that is bigger than the sector size. FatFs site has a  dedicated page for MMC/SDC, on which you can find fairly detailed explanation about how to interface MMC/SDC via SPI bus. Implementation should be straightforward until you encounter with cheap SD cards that do not behave very well. In such cases, you either have to protect your code with redundancy or just stick with quality devices. If you choose SanDisk or Kingston brand, you will be safe. ADATA on the other hand, frequently generates timeout error at first try. Most of the SD card sockets have a pin to detect the presence of the card. This pin is usually connected to GND pin or some other pin. You can use this to generate interrupt whenever ...

Repurposing STLink of Nucleo64 boards

Most of the development kits from ST are equipped with on-board STLink-V2 debugger / programmers, use of which is not very convenient in Linux environment. Instead, Segger kindly provides a tool that allows you to reflash on-board STLink into JLink . Process takes only seconds. And you can enjoy most of the great features of JLink with no cost at least for STM32 devices. It keeps the UART port function, so you can use it as a serial monitor in addition to the JLink. If you have a Nucleo-64 board handy, you can make a nice stand-alone JLink debugger by reflashing the on-board STLink and snap it off. Note that the original pin headers are removed and some of them are replaced with right-angle type for the convenience. Two of the pins of ST-Link jumper are used to provide 3.3V power. And TX and RX pins of UART are soldered at the back not to interfere with the debug pins. Note the small changes in the solder bridges SB3 through SB10. Basically this allows the 3V3 line to b...

FatFs with FLASH memory

STM32Cube framework provides very similar interface for FatFS as USB MSC we have seen before. Again the same argument applies to this case about the basic unit of read/write operation on a flash memory. In this case, the sector size and the cluster size should be equal to the sector size of flash memory, namely 4KB. This can be set in the file ffconf.h , in which a lot of customization can be done by changing the definitions. In particular, following definitions should be set. In the file user_diskio.c, USER_read and USER_write functions can be implemented as the same way as before. Here we assume that the count is always one for the simplicity. In reality this can be bigger than one if you call f_read() with the buffer size larger than the sector size (4096). However given the limited memory capacity, that is not realistic. By similar token, pdrv variable can be ignored. If ioctl is to be used, then  FatFs allows users to not only read and write files but also to ...

STM32 USB MSC Device with FLASH memory

USB Mass Storage Class framework implements bulk-only-transfer (BOT) with SCSI protocol. USB packets from the host eventually converted SCSI transport commands by the middleware, in which data is exchanged (read / write) in the unit of logical block, typically 512 bytes. This SCSI commands works well with SD card system where a dedicated controller does the job of managing the actual memory elements. If you want to use a FLASH chip as a memory unit instead, you need to handle read / write operation directly. Fortunately, most of flash memory support 4KB block erase. This makes the 4096 bytes as a natural choice for the size of the logical block in the file usbd_storage_if.c. In this case, 8Mbit Flash memory was used. During initial enumeration, this information is registered to the host. The middleware maintains one logical block size of buffer and handles USB transaction where each payload is only 64 bytes. It then calls SCSI requests to store / retrieve data to / from physical...

STM32L052 Touch Sensing Controller

Some of STM32 MCUs are equipped with TSC (Touch Sensing Controller), whose hardware performance is not bad compared to ASIC solutions. It is a self-sufficient module supporting multi-touch. And you can lower the power consumption down to few tens of micro amps. Setting up the TSC requires to select one port for sampling for each group. One group consists of one sampling channel, where a sampling capacitor is connected, with one or more measurement channel, where a sensor pad is connected. Charge transfer happens from a measurement channel to the sampling channel. This is done independently from other groups. Thus channels belongs to each group are measured at the same time. In the same group, however measurement should be done sequentially among channels. A PCB touch panel (on the right) is connected to a STM32L052 MCU. The MCU is programmed to measure the touch sensor value at every 100 msec. It transfers the measurement to a PC via UART connection. On the PC side, a py...

A Simple wxPython Stopwatch

This is a very short wxPython script that helps to measure time interval during various testing. Initial screen shows a stock wxPython clock control. When clicked on the clock face, a list appears on the right, on which time stamp, lap time, and cumulative time are displayed. This list disappears when clicked on it. And all data is cleared. Finally, the transparency of the program can be adjusted with the mouse wheel button. <<source code>>

WS2812B (SK6812) Control with SPI and DMA

There are a couple of ways to control WS2812B and its clones. Among them, the method that uses SPI bus via DMA would be the easiest choice for the following reasons; Firstly SPI bus is ubiquitous. It is not easy to find a MCU that is not equipped with one. Secondly DMA minimizes the burden of the processor and handles timing with hardware. No code is involved in transferring data. Thus once proper SPI clock is chosen, operation is quite reliable as well. Only downside is that you have to dedicate one SPI port for the control of the LED, since you cannot share this line with any other SPI devices. The timing of SK6812 is shown below. There are slight variations in the actual timing between devices. But basically all use the same high/low ratio, namely 1:3 for logic zero and 2:2 for logic one. Thus set the SPI clock frequency to somewhere between 2.8hMHz and 4MHz, and use nibble (0x8) for logic zero, (0xc) for logic one. Then all should be good. Actually there are a few things t...

UART Data Communication in STM32Cube Framework

Sometimes implementation of UART communication is asymmetric. In general, Rx tasks are time critical and total size of the data is unknown, thus it is best to handle the task in an interrupt service routine where individual incoming bytes are checked without delay. While Tx tasks can be implemented rather relaxed manner. For example, you can use a blocking call inside the main loop. In this sense, UART HAL functions provided by STM32Cube framework is useful for Tx but not very much so for Rx task. Thus you may have to write your own UART interrupt handler using LL drivers while still using HAL UART Tx functions in Tx task. Use STM32Cube to generate all the chores of setting the UART module except the interrupt part. LL interrupt is activated after the UART port is initialized using LL functions: Source file 414 void SerialComm_Init () 415 { 416 LL_USART_EnableIT_RXNE ( huart1 . Instance ); 417 } Then write the interrupt handler to call Rx routine: ...

STM32 Pushbutton Example: Part 3. Pushbutton State Check

In this post, actual pushbutton checking algorithm is explained. As discussed previously, it utilizes the software timer (UsrTimer) to address the chattering issue and to implement a multi-function input button. The main timer routine is registered by calling: Source file 103 // initialize the pushbutton handler with mask byte. 104 PushButton_Init ( 0x01 ); where the mask byte (0x01) indicates the location of the state bits of active buttons in the 8bit button state byte. Here we have only one button that is located at the first bit location. This call starts a timer routine that runs indefinitely at a predefined interval, PUSHBTN_TMR_PERIOD whose value is set to 80 msec at the moment. This period can be tuned to serve particular hardware better. However you have to remember that other parameters such as the duration values that determine short click and long click have reference to this value. For example PUSHBTN_TO_SHORT value is set to 3, which means tha...

STM32 Pushbutton Example: Part 2. Event Queue

The Event Queue is a simple ring buffer, whose element is a byte array of fixed size. You can use it any purpose as long as it fits. When it is used as an event queue, the meaning of each byte is supposed to be defined by the user. In this example, we define the first byte as the event id followed by event data as below: Source file 73 /** Pushbutton input event 74 * 75 * Event Data: (PBTN_ID)(EVT_TYPE) 76 * 77 * * PBTN_ID: id of the pushbutton that generated the event 78 * * EVT_TYPE: type of the event such as single click, double click, 79 */ 80 #define EVT_PBTN_INPUT 0x10 ///< event code for pushbutton input 81 #define PBTN_SCLK 0x01 ///< single click 82 #define PBTN_LCLK 0x02 ///< long click 83 #define PBTN_DCLK 0x03 ///< double click 84 #define PBTN_TCLK 0x04 ///< triple click Posting an event is...

STM32 Pushbutton Example: Part 1. Software Timer

Project Design Pushbuttons, or tactile switches are convenient way of interacting with the firmware, whether the final product retains them as its UI components or not. There are a couple of things to consider to implement the pushbutton handling features. Debouncing and Software Timer First you have to deal with the contact bouncing effect of the switch.  Following snapshot of  an oscilloscope from Wikipedia page illustrates one situation. However it can be radically different from one case to another. There are numerous ways of addressing the issue, each of which has its own pros and cons. So one method works better in one situation but not necessarily in other cases primarily depending on the chattering characteristics but also depending on other situations. Here we are going to use software timer, in which a timer routine checks (samples) the state of the switch with a regular interval. Short Click vs. Long Click, Single Click vs. Multiple Click Another consi...

A Simple STM32 Example Project

Most of the embedded projects share certain initial steps. You need to confirm the clock settings before doing anything, then you want to have debug connection via a UART channel since it is cheap  but still it can provide useful information for debugging. Let us start with CubeMX. You select a device/board of your choice, set up the pinouts for one GPIO output and one UART port. Configure the clock if necessary then create a project. Clock Checking using SysTick The sanity of the clock setting can be done by checking the SysTick interval. All Cortex-M series core have SysTick timer by default, which should fire at 1msec interval while the MCU is active. In the STM32Cube, the SysTick is initialized by HAL_Init() call, which in turn calls SysTick_Config() in CMSIS. Once the SysTick is initialized, it generates 1 msec interrupt and this interrupt is handled by SysTick_Handler() according to the Cube framework. Source file 1 /** 2 * @brief This function han...