esp32-c6 blink led baremetal riscv not run
Posted: Fri Jun 26, 2026 2:33 pm
Hello.
I wrote a RISC-V assembly program for the ESP32-C6 to blink an external LED connected to pin 5.
I compiled this program using the IDF SDK with the command:
idf.py -p com14 flash monitor
and
idf.py set-target esp32-c6
The LED blinks 5 times as expected. So far, so good.
CMakeLists.txt :
Program debledsdk.s:
Now, I add a few instructions at the beginning of the program (magic word, initializing the stack and some PCR registers) and compile it without the SDK, using the `riscv32-esp-elf-as.exe` compiler found in the IDF tools. I then flash it to the chip using this command:
C:\Espressif\tools\python\v6.0.1\venv\Scripts\esptool --chip esp32c6 -p com14 -b 460800 write-flash --flash-mode dio --flash-freq 80m --flash-size 2MB 0x0 deblederr3.bin
Upon execution, the LED turns on but either fails to blink or blinks continuously, depending on the specific instructions I add while trying to find a solution.
I must be missing an initialization step, but I haven't found it in the documentation yet: reset? vector table? GPIO register init? clock?
Does anyone have a solution?
makefile :
program deblederr3:
memmap.ld :
I wrote a RISC-V assembly program for the ESP32-C6 to blink an external LED connected to pin 5.
I compiled this program using the IDF SDK with the command:
idf.py -p com14 flash monitor
and
idf.py set-target esp32-c6
The LED blinks 5 times as expected. So far, so good.
CMakeLists.txt :
Code: Select all
idf_component_register(SRCS "debledsdk.s"
INCLUDE_DIRS ".")
Code: Select all
/*******************************************/
/* CONSTANTES */
/*******************************************/
.equ LED_PIN, 5
.equ GPIO_MATRIX, 0x60091000
.equ GPIO_OUT_REG, 0x4
.equ GPIO_OUT_W1TS_REG, 0x8
.equ GPIO_OUT_W1TC_REG, 0xC
.equ GPIO_ENABLE_REG, 0x20
.equ GPIO_ENABLE_W1TS_REG,0x24
.equ GPIO_ENABLE_W1TC_REG,0x28
.equ GPIO_PIN_REG, 0x74 + (4*LED_PIN)
.equ GPIO_FUNCPIN_OUT_SEL_CFG_REG, 0x554 + (4*LED_PIN)
.equ GPIO_STATUS_REG, 0x44
.equ GPIO_CLOCK_GATE_REG ,0x062C
.equ IO_MUX, 0x60090000
.equ IO_MUX_GPIOPIN_REG, 0x0004 + (4 * LED_PIN)
.equ PCR, 0x60096000 # clock, reset
.equ PCR_SYSCLK_CONF_REG, 0x0110
.equ PCR_IOMUX_CLK_CONF_REG, 0x00EC
.equ PCR_IOMUX_CONF_REG, 0x00E8
/*******************************************/
/* DONNEES INITIALISEES */
/*******************************************/
.data
/***********************************************/
/* Données non initialisées */
/***********************************************/
.bss
/*******************************************/
/* CODE PROGRAMME */
/*******************************************/
.text
.global app_main
/************************************/
/* Main */
/***********************************/
app_main: # INFO: main
li a0,LED_PIN
call initGpioLed
li s0,GPIO_MATRIX
li t0,1
slli s1,t0,LED_PIN
li s2,5
1:
sw s1,GPIO_OUT_W1TS_REG(s0) # allumage led pin 20
li a0,100
call attendre
sw s1,GPIO_OUT_W1TC_REG(s0) # extinction led pin 20
li a0,100
call attendre
sw s1,GPIO_OUT_W1TS_REG(s0) # allumage led pin 20
li a0,100
call attendre
addi s2,s2,-1
bgtz s2,1b
2: j 2b # end loop
/************************************/
/* init gpio */
/***********************************/
/* a0 pin led */
initGpioLed: # INFO: initGpioLed
addi sp, sp, -8
sw ra, 0(sp)
li t4,GPIO_MATRIX
li t0,1
sll t2,t0,a0 # bit pin 8
sw t2,GPIO_ENABLE_W1TC_REG(t4)
li t0,0x280 #
sw t0,GPIO_FUNCPIN_OUT_SEL_CFG_REG(t4)
#li t0,0x1 # not effect
#sw t0,GPIO_CLOCK_GATE_REG(t4)
li t4,IO_MUX
li t0,0x1902
sw t0,IO_MUX_GPIOPIN_REG(t4)
li t4,GPIO_MATRIX
sw t2,GPIO_ENABLE_W1TS_REG(t4)
100:
lw ra, 0(sp)
addi sp, sp, 8
ret
/************************************/
/* boucle attente */
/***********************************/
/* a0 valeur en milliseconde */
attendre: # INFO: attendre
addi sp, sp, -8 # save des registres
sw t0, 0(sp)
sw t1, 4(sp)
li t0,19 # approximatif
sll t1,a0,t0
li t0,16
sll a0,a0,t0
add a0,a0,t1
1: # loop
addi a0,a0, -1 # decrement indice
bne a0,x0,1b
lw t0, 0(sp)
lw t1, 4(sp)
addi sp, sp, 8 # restaur registres
ret
C:\Espressif\tools\python\v6.0.1\venv\Scripts\esptool --chip esp32c6 -p com14 -b 460800 write-flash --flash-mode dio --flash-freq 80m --flash-size 2MB 0x0 deblederr3.bin
Upon execution, the LED turns on but either fails to blink or blinks continuously, depending on the specific instructions I add while trying to find a solution.
I must be missing an initialization step, but I haven't found it in the documentation yet: reset? vector table? GPIO register init? clock?
Does anyone have a solution?
makefile :
Code: Select all
ARMGNU ?= C:/Espressif/tools/riscv32-esp-elf/esp-15.2.0_20251204/riscv32-esp-elf/bin
ARMGNU1 ?= C:\PrincipalA\Outils\tools\arm-gnu-toolchain-13.3.rel1-mingw-w64-i686-arm-none-eabi\arm-none-eabi\bin
#AOPS = -mabi=ilp32 -march=rv32i_m_zbs_zicsr_f_zba
AOPS = -march=rv32imac_zicsr_zifencei_zaamo_zalrsc
all : deblederr3.flash
deblederr3.o : deblederr3.s
$(ARMGNU)/riscv32-esp-elf-as.exe $(AOPS) deblederr3.s -o deblederr3.o
deblederr3.bin : deblederr3.o
$(ARMGNU)/riscv32-esp-elf-ld.exe -T memmap.ld deblederr3.o -o deblederr3.elf -M >deblederr3_map.txt
$(ARMGNU)/riscv32-esp-elf-objcopy -O binary deblederr3.elf deblederr3.bin
deblederr3.elf : deblederr3.bin
$(ARMGNU)/riscv32-esp-elf-objdump.exe -D deblederr3.elf > deblederr3_list.txt
deblederr3.flash : deblederr3.elf
C:\Espressif\tools\python\v6.0.1\venv\Scripts\esptool --chip esp32c6 -p com14 -b 460800 write-flash --flash-mode dio --flash-freq 80m --flash-size 2MB 0x0 deblederr3.bin
Code: Select all
/*******************************************/
/* CONSTANTES */
/*******************************************/
.equ LED_PIN, 5
.equ GPIO_MATRIX, 0x60091000
.equ GPIO_OUT_REG, 0x4
.equ GPIO_OUT_W1TS_REG, 0x8
.equ GPIO_OUT_W1TC_REG, 0xC
.equ GPIO_ENABLE_REG, 0x20
.equ GPIO_ENABLE_W1TS_REG,0x24
.equ GPIO_ENABLE_W1TC_REG,0x28
.equ GPIO_PIN_REG, 0x74 + (4*LED_PIN)
.equ GPIO_FUNCPIN_OUT_SEL_CFG_REG, 0x554 + (4*LED_PIN)
.equ GPIO_STATUS_REG, 0x44
.equ GPIO_CLOCK_GATE_REG ,0x062C
.equ IO_MUX, 0x60090000
.equ IO_MUX_GPIOPIN_REG, 0x0004 + (4 * LED_PIN)
.equ PCR, 0x60096000 # clock, reset
.equ PCR_SYSCLK_CONF_REG, 0x0110
.equ PCR_IOMUX_CLK_CONF_REG, 0x00EC
.equ PCR_IOMUX_CONF_REG, 0x00E8
.equ RTC_WDT, 0x600B1C00 # RTC Watch Dog Timer
.equ RTC_WDT_CONFIG0_REG, 0x0
.equ RTC_WDT_CONFIG1_REG, 0x4
.equ RTC_WDT_FEED_REG, 0x0014
.equ RTC_WDT_WPROTECT_REG, 0x0018
.equ RTC_WDT_SWD_WPROTECT_REG, 0x0020
.equ RTC_WDT_SWD_CONFIG_REG, 0x001C
/*******************************************/
/* DONNEES INITIALISEES */
/*******************************************/
.data
/***********************************************/
/* Données non initialisées */
/***********************************************/
.bss
/*******************************************/
/* CODE PROGRAMME */
/*******************************************/
.text
.global main
/************************************/
/* Main */
/***********************************/
main: # INFO: main
.int 0xAEDB041D, 0xAEDB041D
li t1,1
li t1,0
li sp,0x4080cc00 # stack address
li t1,PCR
li t0,0x28010200
sw t0,PCR_SYSCLK_CONF_REG(t1)
li t0,0x00700000
sw t0,PCR_IOMUX_CLK_CONF_REG(t1)
li t0,1
sw t0,PCR_IOMUX_CONF_REG(t1)
/*
li t1,RTC_WDT
li t0,0x50D83AA1
sw t0,RTC_WDT_WPROTECT_REG(t1)
li t0,0x50D83AA1
sw t0,RTC_WDT_SWD_WPROTECT_REG(t1)
li t0,0x40000000
sw t0,RTC_WDT_SWD_CONFIG_REG(t1)
sw x0,RTC_WDT_CONFIG0_REG(t1)
sw x0,RTC_WDT_CONFIG1_REG(t1)
*/
li a0,LED_PIN
call initGpioLed
# j 2f # TODO: a supprimer
li s0,GPIO_MATRIX
li t0,1
slli s1,t0,LED_PIN
li s2,5
1:
sw s1,GPIO_OUT_W1TC_REG(s0) # allumage led pin 20
li a0,100
call attendre
sw s1,GPIO_OUT_W1TS_REG(s0) # extinction led pin 20
li a0,100
call attendre
sw s1,GPIO_OUT_W1TC_REG(s0) # allumage led pin 20
li a0,100
call attendre
addi s2,s2,-1
bgtz s2,1b
2: j 2b # end loop
/************************************/
/* init gpio */
/***********************************/
/* a0 pin led */
initGpioLed: # INFO: initGpioLed
addi sp, sp, -8
sw ra, 0(sp)
li t4,GPIO_MATRIX
li t0,1
sll t2,t0,a0 # bit pin 8
sw t2,GPIO_ENABLE_W1TC_REG(t4)
li t0,0x280 #
sw t0,GPIO_FUNCPIN_OUT_SEL_CFG_REG(t4)
#li t0,0x1 # not effect
#sw t0,GPIO_CLOCK_GATE_REG(t4)
li t4,IO_MUX
li t0,0x1902
sw t0,IO_MUX_GPIOPIN_REG(t4)
li t4,GPIO_MATRIX
sw t2,GPIO_ENABLE_W1TS_REG(t4)
100:
lw ra, 0(sp)
addi sp, sp, 8
ret
/************************************/
/* boucle attente */
/***********************************/
/* a0 valeur en milliseconde */
attendre: # INFO: attendre
addi sp, sp, -8 # save des registres
sw t0, 0(sp)
sw t1, 4(sp)
li t0,19 # approximatif
sll t1,a0,t0
li t0,16
sll a0,a0,t0
add a0,a0,t1
1: # loop
addi a0,a0, -1 # decrement indice
bne a0,x0,1b
lw t0, 0(sp)
lw t1, 4(sp)
addi sp, sp, 8 # restaur registres
ret
Code: Select all
MEMORY
{
flash (rx) : ORIGIN = 0x42000000, LENGTH = 2048k
ram (rwx) : ORIGIN = 0x40800000, LENGTH = 0x80000
}
STACK_SIZE = 0x4000;
RAM_SIZE = 0x80000;
/* Section Definitions */
SECTIONS
{
.flash_header : {
KEEP(*(flash_headerH))
}> FLASH
.text ORIGIN(flash) + 8 :
{
/* KEEP(*(.vectors .vectors.*)) */
*(.text*)
*(.rodata*)
} > flash
. = ALIGN(4);
_debutFlashData = . ;
.data :
{
. = ALIGN(2);
_debutRamData = . ;
. = ALIGN(2);
*(.data*);
} > ram AT > flash
/* .bss section which is used for uninitialized data */
. = ALIGN(4); /* aligne bss pour initialisation dans pgm */
_debutRamBss = . ;
.bss (NOLOAD) :
{
*(.bss*)
*(COMMON)
} > ram
_finRamBss = . ;
.SC1 (NOLOAD):
{
. = ALIGN(8);
_debutTas = . ;
. = _debutRamData - . + RAM_SIZE - (STACK_SIZE) ;
} > ram
_finTas = . ;
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
. = . + STACK_SIZE;
_stack = .;
. = ALIGN(8);
} > ram
_end = . ;
}