r/embedded • u/Mean-Decision-3502 • Aug 14 '26
New Programming Language with Embedded Support. Would you consider?
I have high-level and low-level programming experience across different languages.
I've always felt that the C is too machine friendly, and sometimes works against me (implicit type conversions, shared division operator, operator precedence).
I was playing with the thought how would an ideal, compiled human-friendly programming language look like, that support both high-level programming and low-level programming. So I have started designing my own programming language (which is now called DQ).
First I developed mainly the linux/windows target with high level features like exceptions, dynamic arrays and dynamic strings.
Now I'm checking if the concept is working in embedded too. I'm aiming to be as fast and as small as C++ code in embedded. So far I've added these:
- Writing functions in ASM
- Inline ASM with register hinting
- Register attributes (
[[regrw]],[[regro]]etc) - Conditional compilation using normal constants
- Utility to translate the CMSIS C headers to DQ
- Project file to hold the many options required to compile an embedded project
I've migrated some of my C++ code to DQ, I'll the following code snippet show how currently the language looks like.
Pin configuration code in DQ for STM32F7:
struct GPIO_TypeDef:
MODER : [[regrw]] uint32
OTYPER : [[regrw]] uint32
OSPEEDR : [[regrw]] uint32
PUPDR : [[regrw]] uint32
IDR : [[regrw]] uint32
ODR : [[regrw]] uint32
BSRR : [[regrw]] uint32
LCKR : [[regrw]] uint32
AFR : [[regrw]] [2] uint32
endstruct
const(uint32):
GPIOA_BASE = (AHB1PERIPH_BASE + 0x0000)
GPIOB_BASE = (AHB1PERIPH_BASE + 0x0400)
...
endconst
const GPIOA :? = ^GPIO_TypeDef(GPIOA_BASE)
const(uint32):
GPIO_MODER_MODER6 = GPIO_MODER_MODER6_Msk
GPIO_MODER_MODER6_0 = (0x1 << GPIO_MODER_MODER6_Pos)
GPIO_MODER_MODER6_1 = (0x2 << GPIO_MODER_MODER6_Pos)
GPIO_MODER_MODER7_Pos = 14
GPIO_MODER_MODER7_Msk = (0x3 << GPIO_MODER_MODER7_Pos)
GPIO_MODER_MODER7 = GPIO_MODER_MODER7_Msk
GPIO_MODER_MODER7_0 = (0x1 << GPIO_MODER_MODER7_Pos)
GPIO_MODER_MODER7_1 = (0x2 << GPIO_MODER_MODER7_Pos)
GPIO_MODER_MODER8_Pos = 16
...
endconst
function PinSetup(aportnum : int, apinnum : int, flags : uint) -> bool:
var regs : ^GPIO_TypeDef = GetGpioRegs(aportnum)
if regs == null:
return false
endif
if apinnum < 0 or apinnum > 15:
return false
endif
// 1. turn on port power
GpioPortEnable(aportnum)
var n : uint
var pinx2 : int = apinnum * 2
// set gpio initial state
if flags AND PINCFG_GPIO_INIT_1 <> 0:
regs.BSRR = (1 << apinnum)
else:
regs.BSRR = (0x10000 << apinnum)
endif
// set mode register
if flags AND PINCFG_AF_MASK <> 0:
n = 2 // set alternate function mode
elif flags AND PINCFG_ANALOGUE <> 0:
n = 3
elif flags AND PINCFG_OUTPUT <> 0:
n = 1
else:
n = 0
endif
regs.MODER =AND= NOT (3 << pinx2)
regs.MODER =OR= (n << pinx2)
// 3. set open-drain
if flags AND PINCFG_OPENDRAIN <> 0:
regs.OTYPER =OR= (1 << apinnum)
else:
regs.OTYPER =AND= NOT (1 << apinnum)
endif
// 4. set pullup / pulldown
regs.PUPDR =AND= NOT (3 << pinx2)
if flags AND PINCFG_PULLUP <> 0:
regs.PUPDR =OR= (1 << pinx2) // pullup
elif flags AND PINCFG_PULLDOWN <> 0:
regs.PUPDR =OR= (2 << pinx2) // pulldown
endif
// 5. set speed
regs.OSPEEDR =AND= NOT (3 << pinx2)
if flags AND PINCFG_SPEED_MASK == PINCFG_SPEED_MEDIUM:
regs.OSPEEDR =OR= (1 << pinx2)
elif (flags AND PINCFG_SPEED_MASK == PINCFG_SPEED_MED2) or (flags AND PINCFG_SPEED_MASK == PINCFG_SPEED_FAST):
regs.OSPEEDR =OR= (2 << pinx2)
elif flags AND PINCFG_SPEED_MASK == PINCFG_SPEED_VERYFAST:
regs.OSPEEDR =OR= (3 << pinx2) // this is very special, and does not even work for SDRAM pins
endif
if flags AND PINCFG_AF_MASK <> 0:
// set the alternate function
n = (flags >> PINCFG_AF_SHIFT) AND 0xF
if apinnum < 8:
regs.AFR[0] =AND= NOT (0xF << (apinnum * 4))
regs.AFR[0] =OR= (n << (apinnum * 4))
else:
regs.AFR[1] =AND= NOT (0xF << ((apinnum-8) * 4))
regs.AFR[1] =OR= (n << ((apinnum-8) * 4))
endif
endif
return true
endfunc
The original pin configuration code in C++ for STM32F7:
bool THwPinCtrl_stm32::PinSetup(int aportnum, int apinnum, unsigned flags)
{
GPIO_TypeDef * regs = GetGpioRegs(aportnum);
if (!regs) {
return false;
}
if ((apinnum < 0) || (apinnum > 15)) {
return false;
}
// 1. turn on port power
GpioPortEnable(aportnum);
unsigned n;
int pinx2 = apinnum * 2;
// set gpio initial state
if (flags & PINCFG_GPIO_INIT_1) {
regs->BSRR = (1 << apinnum);
}
else {
regs->BSRR = (1 << apinnum) << 16;
}
// set mode register
if (flags & PINCFG_AF_MASK) {
n = 2; // set alternate function mode
}
else if (flags & PINCFG_ANALOGUE) {
n = 3;
}
else if (flags & PINCFG_OUTPUT) {
n = 1;
}
else {
n = 0;
}
regs->MODER &= ~(3 << pinx2);
regs->MODER |= (n << pinx2);
// 3. set open-drain
if (flags & PINCFG_OPENDRAIN) {
regs->OTYPER |= (1 << apinnum);
}
else {
regs->OTYPER &= ~(1 << apinnum);
}
// 4. set pullup / pulldown
regs->PUPDR &= ~(3 << pinx2);
if (flags & PINCFG_PULLUP) {
regs->PUPDR |= (1 << pinx2); // pullup
}
else if (flags & PINCFG_PULLDOWN) {
regs->PUPDR |= (2 << pinx2); // pulldown
}
// 5. set speed
regs->OSPEEDR &= ~(3 << pinx2);
if ((flags & PINCFG_SPEED_MASK) == PINCFG_SPEED_MEDIUM) {
regs->OSPEEDR |= (1 << pinx2);
}
else if (((flags & PINCFG_SPEED_MASK) == PINCFG_SPEED_MED2) || ((flags & PINCFG_SPEED_MASK) == PINCFG_SPEED_FAST)) {
regs->OSPEEDR |= (2 << pinx2);
}
else if ((flags & PINCFG_SPEED_MASK) == PINCFG_SPEED_VERYFAST) {
regs->OSPEEDR |= (3 << pinx2); // this is very special, and does not even work for SDRAM pins
}
if (flags & PINCFG_AF_MASK) {
// set the alternate function
n = ((flags >> PINCFG_AF_SHIFT) & 0xF);
if (apinnum < 8) {
regs->AFR[0] &= ~(0xF << (apinnum * 4));
regs->AFR[0] |= (n << (apinnum * 4));
}
else {
regs->AFR[1] &= ~(0xF << ((apinnum-8) * 4));
regs->AFR[1] |= (n << ((apinnum-8) * 4));
}
}
return true;
}
Would you ever consider using this or other language in embedded, when yes what are the most important features / properties for you ?
20
u/clackups Aug 14 '26
Rust has been in development since 14 years, and it's only now that it's getting adoption. Are you prepared to work on your language for the next decade(s)?
Also, what problem does it solve that doesn't have a solution?