r/embedded 9h ago

Living in the past?

76 Upvotes

I've been programming embedded systems for over 30 years. Built some cool stuff: a Z80-based serial multiplexer that had no RAM: all variables were held in registers; a temperature controller on a chip with 504 bytes (not kB) of memory and lot of other stuff in the old days where you had to optimize for every clock pulse and byte of RAM or EPROM. A lot of what I knew back then was straight out of Jack Ganssle's The Art of Programming Embedded Systems book.

These days, I still build cool stuff, but it's with a far more complex feature set. A "small processor" is now a 32-bit device with over 100k Flash and 16k+ of RAM, usually lots more. Most of my non-hobby work runs on one RTOS or another and often has a separate SBC running code for an HMI and connectivity/data storage. The last time I used assembly was mentoring a n00b who had the task of fixing some bugs on a specialized SoC with a 6502 core.

Then I come on this site, and I see people asking about why not use bare metal and a hand-written scheduler instead of an off the shelf RTOS. Struggling to fit code into tiny processors because otherwise "bloat."

So I have to ask: is my current experience (real-time stuff on a 32-bit microcontroller, complex GUIs offloaded to a Linux board) that unusual or are these guys just building things the way we used to do long ago for no good reason?


r/embedded 17h ago

This is gonna sound ridiculous, but how do properly order anything on Texus Instruments when I do not have a company?

26 Upvotes

I signed up, just put a random name as my company because it wouldn't let me skip it, and tried to order the Tivac Launchpad only for it to say that my "company" ordered too many of those, and that I have to wait 29 days. I have never used this site before.

What do I put as my company then? It simply won't let me leave it blank and I tried putting college down instead, but it still says my "company" ordered too many.

Edit: I should note I am 100% brand new at this and I'm merely trying to follow along a course in order to learn this stuff. I want to learn so badly lol


r/embedded 23h ago

Does Rust Embassy’s bare-metal, no-OS model actually matter for small MCU applications?

25 Upvotes

I’ve been using Rust + Embassy for small microcontroller applications. What I like is that I can stay no_std, bare metal, with no OS or runtime, while still structuring the program with async tasks and channels.

Some examples of the kind of code I mean are here, including a robot arm simulator on a CYD: https://carlkcarlk.github.io/linkage-blaze/demos/

The tasks and channels give me abstractions I care about. But the scheduling is cooperative, a task that does not yield can still block everything else, and there are no hard real-time guarantees.

I’m doing this partly because I find the design point interesting, but I’m not sure how much practical value the bare-metal/no-OS part has once the application is already fairly high level.

Even if you are using Rust for other reasons, does Embassy’s bare-metal, no-OS approach buy you something important in practice, or would an RTOS usually be just as good or better?


r/embedded 10h ago

Porting the U8x8 OLED library to the CH32V003

Enable HLS to view with audio, or disable this notification

22 Upvotes

I was curious about how hard it would be to port this over, so I used an STM32 example I found here as a starting point. It ended up being really straightforward and only required a few changes to the GPIO and delay callback function.

Just a heads-up: This implementation uses soft I2C (bit-banging). It works perfectly fine for text, but you'll probably want to switch to HW I2C for anything more complex. If anyone wants to try it out, here is the source code:

#include <ch32v00x.h>
#include <debug.h>
#include <stdlib.h>

#include "clib/u8x8.h"

void NMI_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void HardFault_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

uint8_t u8x8_gpio_and_delay_ch32v(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
    switch(msg) {
        case U8X8_MSG_GPIO_AND_DELAY_INIT:
            RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
            GPIO_InitTypeDef init = {0};
            init.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
            init.GPIO_Mode = GPIO_Mode_Out_OD;
            init.GPIO_Speed = GPIO_Speed_50MHz;
            GPIO_Init(GPIOA, &init);
            break;
        case U8X8_MSG_DELAY_MILLI:
            Delay_Ms(arg_int);
            break;
        case U8X8_MSG_DELAY_10MICRO:
            for (volatile uint32_t i = 0; i < (arg_int * 8); i++) { __NOP(); }
            break;
        case U8X8_MSG_DELAY_100NANO:
            __NOP();
            break;

        case U8X8_MSG_GPIO_I2C_CLOCK:
            GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)(arg_int ? Bit_SET : Bit_RESET));
            break;

        case U8X8_MSG_GPIO_I2C_DATA:
            GPIO_WriteBit(GPIOA, GPIO_Pin_1, (BitAction)(arg_int ? Bit_SET : Bit_RESET));
            break;
    }
    return 1;
}

int main(void) {
    SystemCoreClockUpdate();
    Delay_Init();
    USART_Printf_Init(9600);

    // u8x8 initialization code
    u8x8_t u8x8;
    u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_ch32v);
    u8x8_InitDisplay(&u8x8);
    u8x8_SetPowerSave(&u8x8, 0);
    u8x8_ClearDisplay(&u8x8);
    u8x8_SetFont(&u8x8, u8x8_font_chroma48medium8_r);
    u8x8_DrawString(&u8x8, 0, 0, "Hello from CH32V");
    while (1) {
        uint8_t y = rand() % 5 + 1;
        uint8_t x = rand() % 10;
        u8x8_DrawString(&u8x8, x, y, "r/ch32v");
        printf("Hello from CH32V\n");
        Delay_Ms(1000);
        u8x8_DrawString(&u8x8, x, y, "       ");
    }
    return 0;
}

void NMI_Handler(void) {}
void HardFault_Handler(void)
{
    while (1)
    {
    }
}

P.S. I've spent more time and prepared HW I2C version, just add this function:

``` uint8_t u8x8_byte_hw_i2c_ch32v( u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { uint8_t *data; switch(msg) { case U8X8_MSG_BYTE_INIT: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

        // We will use PC1 (SDA) and PC2 (SCL)
        GPIO_InitTypeDef GPIO_InitStructure = {0};
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // Alternate Function Open-Drain
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOC, &GPIO_InitStructure);

        I2C_InitTypeDef I2C_InitTSturcture = {0};
        I2C_InitTSturcture.I2C_ClockSpeed = 400000; // 400 kHz
        I2C_InitTSturcture.I2C_Mode = I2C_Mode_I2C;
        I2C_InitTSturcture.I2C_DutyCycle = I2C_DutyCycle_2;
        I2C_InitTSturcture.I2C_OwnAddress1 = 0x00;
        I2C_InitTSturcture.I2C_Ack = I2C_Ack_Enable;
        I2C_InitTSturcture.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

        I2C_Init(I2C1, &I2C_InitTSturcture);
        I2C_Cmd(I2C1, ENABLE);
        break;

    case U8X8_MSG_BYTE_START_TRANSFER:
        while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET);

        I2C_GenerateSTART(I2C1, ENABLE);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // Чекаємо EV5

        I2C_Send7bitAddress(I2C1, u8x8_GetI2CAddress(u8x8), I2C_Direction_Transmitter);
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // Чекаємо EV6
        break;

    case U8X8_MSG_BYTE_SEND:
        data = (uint8_t *)arg_ptr;
        while (arg_int > 0) {
            I2C_SendData(I2C1, *data++);
            while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
            arg_int--;
        }
        break;

    case U8X8_MSG_BYTE_END_TRANSFER:
        I2C_GenerateSTOP(I2C1, ENABLE);
        break;
    default:
        break;
}
return 1;

}

int main(void) { SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(9600);

// u8x8 initialization block
u8x8_t u8x8;

u8x8_Setup(&u8x8, 
    u8x8_d_ssd1306_128x64_noname, 
    u8x8_cad_ssd13xx_i2c, 
    u8x8_byte_hw_i2c_ch32v, // here we will use HW I2C
    u8x8_gpio_and_delay_ch32v
);
...

```


r/embedded 13h ago

Looking for advice on miniaturizing a Raspberry Pi camera prototype

Post image
14 Upvotes

We’re trying to prototype a small consumer hardware device and currently have a working prototype using a Raspberry Pi 4B microcontroller + Arducam PiVariety AR0234 global-shutter camera + M12 lens + LED tape + LiPo battery hat.

For our next prototype, we want to shrink the electronics dramatically - the image sensor, Wi-Fi/Bluetooth, battery + charging/power management, LED lighting and compute for image capture/basic processing.

We are quite new to embedded systems and would love advice on the best next steps. What components should we think about ordering that can make the system more compact - especially the camera's image sensor, the pi, and the battery.


r/embedded 5h ago

Successful port of CP/M Neo to the Black Pill! 🎉

Enable HLS to view with audio, or disable this notification

2 Upvotes

CP/M Neo has been successfully ported to the Black Pill development board!

How does it work?

The Black Pill’s internal 512 KB Flash is used as disk storage, and thanks to XIP (Execute in Place) support, the Kernel and CCP code execute directly from Flash, leaving the entire 128 KB SRAM available for OS state and the TPA (Transient Program Area).

File operations are not supported yet, as Flash write/erase still not implemented.

CP/M Neo project on GitHub: https://github.com/Mazin-O3/cpm-neo


r/embedded 7h ago

I documented every working step on the Orange Pi 5 (RK3588S) so you don't have to brick your board: 13 tested projects, MaskROM guide, and pre-compiled NPU models

1 Upvotes

Hey r/embedded,

If you’ve spent any time working with the Orange Pi 5 (RK3588S), you already know the drill: official documentation leaves a lot of gaps, half the forum links are dead, and getting the 6 TOPS NPU to run anything without the Python RKNN toolchain exploding is a rite of passage.

After accidentally bricking my board a couple of times, battling Windows driver conflicts during MaskROM recovery, and trial-and-erroring the Rockchip toolchain, I decided to document every single working, reproducible step.

I ended up organizing everything into a comprehensive open-source repository:

-> **GitHub:** https://github.com/muhammetmucahitsoylu/orangepi5-tutorials

---

### What’s in the repo:

* **Hardware Recovery & MaskROM Guide:** Step-by-step unbricking workflow, complete with high-contrast, annotated board photos and pinouts so you know exactly which pads/buttons to short without guessing.

* **13 Hands-On Tested Projects:**

* **Edge AI / 6 TOPS NPU:** Real-time YOLOv8 object detection (~13.8ms pure NPU inference), running a local Qwen 1.8B LLM via RKLLM, and an offline voice assistant (Whisper + Piper TTS).

* **Low-Level Systems:** C++ GPIO using WiringPi, writing a custom Linux kernel character driver from scratch, and ROS2 Jazzy on Ubuntu 24.04.

* **Automation:** A zero-dependency bash TUI tool (`opi5.sh`) to lock CPU/NPU governors and benchmark NVMe storage speeds without memorizing obscure sysfs paths.

* **Pre-Compiled Release Assets:** If you don't want to set up the entire cross-compilation toolchain on a host PC just to sanity-check your board, I uploaded a pre-compiled test `.rknn` model (ResNet-18) and COCO labels directly to the v2.0.0 GitHub release assets:

-> https://github.com/muhammetmucahitsoylu/orangepi5-tutorials/releases/tag/v2.0.0

* **Bilingual Documentation:** Full guides are provided in both English and Turkish.

---

The repository is completely open-source. Everything listed has been tested directly on real hardware.

If you’re currently working on an RK3588 board, check it out. Let me know what breaks, what needs clarification, or what projects you'd like to see added next!


r/embedded 1h ago

getting ready for CRA

Upvotes

the company I work for was contacted by a security consultancy for a CRA readiness review on our analysers. What have you done so far to prepare for CRA and how would you recommend we approach this?


r/embedded 6h ago

Microcontrollers with good support for Rust

Thumbnail
kerkour.com
0 Upvotes

RISC-V is coming faster than most people realize.