惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
B
Blog RSS Feed
The GitHub Blog
The GitHub Blog
爱范儿
爱范儿
博客园 - 司徒正美
J
Java Code Geeks
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
D
Docker
Blog — PlanetScale
Blog — PlanetScale
Recent Announcements
Recent Announcements
罗磊的独立博客
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
腾讯CDC
T
The Blog of Author Tim Ferriss
小众软件
小众软件
U
Unit 42
T
Tailwind CSS Blog

Comments for LinuxJedi's /dev/null

Converting a PC Floppy Drive to Amiga Amiga 1000 Restoration: The Keyboard Amiga 1000 Restoration: Floppy Drive and WCS Failure? Amiga 4000 Repair: This one was just weird Socket SO_REUSEPORT and Kernel Implementations Coding an MSP430 From the Linux Command Line Upgrading the RAM Detective: A Firmware Adventure with RAMCHECK When an Amiga A570 Repair Took a Strange Turn AI Didn’t Destroy Your Company, Your Processes Did KDE Plasma Automatic Time Zone Raspberry Pi JTAG Programming - 2025 Edition Teletext on a BBC computer in 2024 Amiga RAMesses Trying Out Even More Amiga 500 Plus Upgrades Programming Xilinx JTAG from a Raspberry Pi
UART and Ethernet on the STM32 Nucleo-F756ZG
LinuxJedi · 2021-11-04 · via Comments for LinuxJedi's /dev/null

If, like me, you are new to developing for the STM32, there are not many tutorials out there on how to get started with certain things. Made worse by the fact that the defaults in ST’s software are not the same as the defaults in their hardware. So, I’ve put together this quick tutorial so I remember how to do this again next time.

First of all you need the STM32CubeIDE software and STM32CubeMX software. The former is a tailor-made IDE and the latter sets up the hardware configuration and initialisation code. You can just use the IDE as this can have CubeMX integrated inside it. But for now I’ve been keeping them separate. From there you can create a project for the STM32F756ZG MPU, unfortunately there is no software template for the board.

UART

The Nucleo boards include something called ST-LINK which is a USB programmer and debugger for the board. It also includes a couple of extra features such as a UART directly connected to it. In the case of this board, “USART3” is connected and in Linux this corresponds to /dev/ttyACM0 (or a higher number if you already have a ttyACM). There is a gotcha to this, the Nucleo boards do not use the default pins defined in MX for the UART. To get this running, first of all you need to enable it. You can do this by expanding “Connectivity”, clicking on the dropdown for “Mode” and selecting “Asynchronous”:

From here you’ll notice that the pins PB10 and PB11 have been selected, but these are the wrong ones. You actually need to use PD8 and PD9 (as can be seen in the screenshot above). You can change these by finding those pins on the image of the chip, clicking on them and selecting USART3_RX and USART3_TX:

Ethernet

As with the UART, whilst the MX software has everything needed to make the Ethernet work, a few of the defaults are incorrect. You can enable the Ethernet by selecting “ETH” in the “Connectivity” and setting the “Mode” to “RMII”:

The key things to change are the “PHY Address”, it defaults to “1” but for this board it should be “0”. In addition, the pin ETH_TXD0 defaults to PB12 when it should be PG13. This can be seen in the chip image in the UART section above, you can change this in the same way as the UART pins. You might also want to change the MAC address here, although the default will work.

Middleware

Next we need a mini operating system and network stack. For the OS it is easy to use FreeRTOS. Expand the “Middleware” section and change the “Interface” to “CMSIS_V2“. UPDATE 2021-11-08: CMSIS V2 appears to trigger a bug somewhere that causes memory corruption in the Ethernet code, particularly around the receive semaphore. The fix for this is to choose “CMSIS_V1” instead:

Then click on the “Advanced settings” tab and change “USE_NEWLIB_REENTERANT” to “Enabled”:

When using lwIP you’ll need a larger stack size, which in-turn requires more heap. If you don’t do this then DHCP will handling will blow the stack and crash really fast. I’ve increased the heap here to 128KB:

The stack is set for the individual task, here I’ve increased it to 8KB:

To enable the lwIP network stack simply select “LWIP” in the “Middleware” section and tick the “Enabled” box. For the purposes of this example the defaults are fine. If you want some debugging information then you can turn it on in the “Debug” tab with the “Show Advanced Parameters” checked:

Finishing Setup

A couple of extra changes that should be made before we hit the “GENERATE CODE” button. First, change the “Timebase Source” to “TIM1” in the “SYS” module. This stops a warning when generating FreeRTOS code:

Finally, in the Project Management tab, we need to set the output “Toolchain” to “STM32CubeIDE” (I also tick “Generate Under Root”). It should be noted that I have “Enable multi-threaded support” ticked here, do not do this. ST’s implementation of lwIP is not thread safe and will crash (typically around 10 minutes into running):

Source Modifications

Once you have generated the project and loaded it into the IDE you can make a few changes to main.c so that printf() will output on the UART. The first is intercepting the underlying functions and sending the buffers to the UART, to do this, add the following code between the USER CODE BEGIN PV comments. It is always good to add any additional code in the “USER CODE” sections because these won’t be erased if you make changes in MX later and regenerate the code:

/* Retargets the C library printf function to the USART. */
#include <stdio.h>
#ifdef __GNUC__
int __io_putchar(int ch)
#else
int fputc(int ch, FILE *f)
#endif
{
    HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);

    return ch;
}
#ifdef __GNUC__
int _write(int file,char *ptr, int len)
{
    int DataIdx;
    for (DataIdx= 0; DataIdx< len; DataIdx++) {
        __io_putchar(*ptr++);
    }
    return len;
}
#endif

Then in the main() function, in the USER CODE BEGIN Init section:

  /* Turn off buffers, so I/O occurs immediately */
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);

Finally we can test this by adding the following in StartDefaultTask() in the USER CODE BEGIN 5 section:

In my test I also turned on some lwIP debugging options so you can see the DHCP happening:

And that is it! You are now free to add more code to use your board on the network, with the ability to use a serial output to debug as needed.