ARM37: the hare and the little turtle.

It sounds like a reference to the classic fable of the tortoise and the hare! Do you mean it in that sense, or is it something technical related to ARM processors? 🙂

If you’re not interested in microcontroller programming, you might as well skip this. It won’t be very exciting… 🙂
A classic issue—two processes running at very different speeds. In this case: USB and UART. How do you synchronize their operation? You find some source code from an online tutorial, and everything seems to work fine as long as you’re manually typing data. But if you try copy-pasting, suddenly the text stops transferring properly, characters disappear, and the processor hangs. Why? Because processes that operate at different speeds and principles need synchronization:
The first process, USB, transmits data in packets, allowing for pauses and even retransmissions. It operates quite fast.
The second process, UART, transmits data sequentially and slowly, with timing dependency. If control lines aren’t used, the process cannot be paused. When there’s too much data, it’s lost.
From a human perspective, this looks like two processes. From a microcontroller’s view, there are actually four: USB TX, USB RX, UART TX, UART RX.
To manage this chaos, processes should run independently using interrupts. Alternatively, the main loop can be paused while sending data (at least in this experiment). The setup works like this:

  • UART RX: Received via interrupt, sometimes with DMA, but since we don’t know how many bytes will arrive, the DMA/IRQ handles one byte at a time.
  • UART TX: Blocks CPU execution while sending data (since the program isn’t doing anything complex, this is acceptable).
  • USB RX: Probably interrupt-driven, using the HAL library.
  • USB TX: Either blocked or IRQ-driven, using the HAL library.1
    Each process does just one job during an interrupt—when data is received, it is stored in a buffer (if there’s space). This buffer is called a “circle” buffer because it’s like a circular buffer2, though here, overflow results in lost data instead of overwriting.
    And the real fun happens in the main loop:
while(1)
	{
	HAL_IWDG_Refresh(&hiwdg); //watchdogas

	while(circle_available(&cc)>0) //ar yra duomenu gautu is UART?
		{
		i=circle_available(&cc);
		for(j=0;j<i;j++)
			{
			tmp[j]=circle_pull(&cc); //viska persikopijuojam ir issiunciam
			}
		CDC_Transmit_FS(tmp, i); //siuntimas per USB (blocking?. gal ne)
		}

	while(circle_available(&cu)>0) //ar yra duomenu gautu is USB?
		{
		i=circle_available(&cu);
		for(j=0;j<i;j++)
			{
			tmp[j]=circle_pull(&cu); //viska persikopijuojam ir issiunciam
			}
		send_uart((char *) tmp,i); //siunciam per UART (blocking)
		}
	}
}

WordPress probably didn’t corrupt the program text.
Basically, the program works like this: is there data to transmit? Send it! And repeat.
To complicate things further, TX can be handled with separate buffers and an asynchronous transmission process, freeing up some CPU resources for other tasks.
Another issue—an unexpected case where, in short moments while fetching data to the buffer, new data is written. The circular buffer theoretically prevents these issues… but practically, it works fine for everyday use.
This article is mainly for my own reference—I needed it but didn’t remember everything, so I had to write it down.

P.S. The source code isn’t optimized for clarity.

  1. The HAL USB library doesn’t check whether data has actually been sent. If precise control is needed, USB status should be verified. The Atari disk emulator code might be a better reference (I think I did everything there). ↩︎
  2. A circular buffer allows continuous reading and writing, like the mythical ouroboros serpent—new data is added to the head while old data exits at the tail. Everything works fine unless the head catches the tail, causing data loss. ↩︎

About Administrator

I am owner of this site.
This entry was posted in AI translated, Anything, MCU and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *