Is the old method of configuring the pullups and pulldowns still useable on the RPi4? I had a quick look at your LED code and it configures them using GPPUD, GPPUDCLK0 & GPPUDCLK1 for all models but the RPi4 has four new registers GPIO_PUP_PDN_CNTRL_REGn (where n is 0..3) for setting them. I was under the impression that the three registers which the earlier RPis use aren't on the RPi4, they aren't listed in the BCM2711 doc.sean.lawless wrote: ↑Wed Aug 05, 2020 3:58 amMy Github baremetal project, and the associated books, have been updated for RPi 4. See the following link for more information:
https://sean-lawless.github.io/computersystems/
The biggest change for RPi 4 is the change in the peripheral base to 0xFE000000. Older baremetal RPi code will often work for RPi 4 if you change this base address of the peripherals.
Cheers,
Sean
I think the GPIO base in the doc is a typo and should be 0x200000 just like the other models, 0x215000 is the AUX base (page 12 of the 2711 doc). It's just the pull-updown registers that changed.sean.lawless wrote: ↑Mon Aug 10, 2020 5:42 am@Paeryn Thank you for your comment. The bcm2711 document references a new GPIO base interface (0x215000 instead of 0x200000). While the old GPIO interface (on 0x200000) still works on RPI4 for set/clear (and is used in the code), as you pointed out the PU/PD on this interface is not plumbed into the hardware on RPI4. To be fair to RPI4 readers who may need this feature on a different GPIO, the code will be updated to use the new GPIO interface (0x215000).
Hello, thank you for your feedback and the circumstances you are going through.sean.lawless wrote: ↑Mon Aug 10, 2020 4:15 am@satyria - A lot can go wrong. Did you follow all the instructions from both main and lab books? If so, please also try turning off optimizations (change -O2 to -O0 in build.sh). I noticed this is -O0 in build.bat, but not build.sh... the for() loop may be optimized away so no blinking can be detected.
If *still* not working, please post the result of command 'arm-none-eabi-gcc -v' as well as 'arm-none-eabi-objdump led.elf' and I will do the best to assist debugging remotely.
@Paeryn, I suspect you are correct and will investigate further. However for compatibility I believe the old registers still exist on the RPI4 ; they just don't anything and the code works because the GPIO defaults for this pin (LED) match.
Code: Select all
_kernel.img
_kernel7.img
_kernel7l.img
bcm2708-rpi-b.dtb
bcm2708-rpi-b-plus.dtb
bcm2708-rpi-cm.dtb
bcm2708-rpi-zero.dtb
bcm2708-rpi-zero-w.dtb
bcm2709-rpi-2-b.dtb
bcm2710-rpi-3-b.dtb
bcm2710-rpi-3-b-plus.dtb
bcm2710-rpi-cm3.dtb
bcm2711-rpi-4-b.dtb
bootcode.bin
cmdline.txt
config.txt
COPYING.linux
fixup.dat
fixup_cd.dat
fixup_db.dat
fixup_x.dat
fixup4.dat
fixup4cd.dat
fixup4db.dat
fixup4x.dat
issue.txt
kernel.list
kernel.map
kernel7l.img
LICENCE.broadcom
overlays
start.elf
start_cd.elf
start_db.elf
start_x.elf
start4.elf
start4cd.elf
start4db.elf
start4x.elf
System Volume InformationCode: Select all
Using built-in specs.
COLLECT_GCC=C:\msys64\usr\bin\arm-none-eabi-gcc.exe
COLLECT_LTO_WRAPPER=c:/msys64/usr/bin/../libexec/gcc/arm-none-eabi/9.2.1/lto-wrapper.exe
Target: arm-none-eabi
Configured with: /tmp/lto_build/src/gcc/configure --target=arm-none-eabi --prefix=/tmp/lto_build/build-mingw-arm-none-eabi/install// --with-gmp=/tmp/lto_build/build-mingw-arm-none-eabi/host-tools --with-mpfr=/tmp/lto_build/build-mingw-arm-none-eabi/host-tools --with-mpc=/tmp/lto_build/build-mingw-arm-none-eabi/host-tools --with-isl=/tmp/lto_build/build-mingw-arm-none-eabi/host-tools --disable-shared --disable-nls --disable-threads --disable-tls --enable-checking=release --enable-languages=c,c++,fortran --with-newlib --with-libiconv-prefix=/tmp/lto_build/build-mingw-arm-none-eabi/host-tools --host=i686-w64-mingw32 --with-pkgversion='GNU Toolchain for the A-profile Architecture 9.2-2020.02 (arm-9.10)' --with-bugurl=https://bugs.linaro.org/
Thread model: single
gcc version 9.2.1 20191025 (GNU Toolchain for the A-profile Architecture 9.2-2020.02 (arm-9.10))
Code: Select all
led.elf: file format elf32-littlearm
Disassembly of section .text:
00008000 <main>:
/* main: Application Entry Point */
/* */
/* Returns: Exit error */
/*...................................................................*/
int main(void)
{
8000: e52db004 push {fp} ; (str fp, [sp, #-4]!)
8004: e28db000 add fp, sp, #0
8008: e24dd00c sub sp, sp, #12
unsigned int i, select;
#if RPI == 4
/* GPIO 42 is 2nd register in GPFSEL4, so 2 * 3 bits or bit 6. */
/* Clear the 3 bit range (7) starting at bit 6 */
select = REG32(GPFSEL4);
800c: e59f3244 ldr r3, [pc, #580] ; 8258 <main+0x258>
8010: e5933000 ldr r3, [r3]
8014: e50b300c str r3, [fp, #-12]
select &= ~(7 << 6);
8018: e51b300c ldr r3, [fp, #-12]
801c: e3c33d07 bic r3, r3, #448 ; 0x1c0
8020: e50b300c str r3, [fp, #-12]
/* Configure the LED (GPIO 42) starting at bit 6, as output (1). */
select |= (GPIO_OUTPUT << 6);
8024: e51b300c ldr r3, [fp, #-12]
8028: e3833040 orr r3, r3, #64 ; 0x40
802c: e50b300c str r3, [fp, #-12]
REG32(GPFSEL4) = select;
8030: e59f2220 ldr r2, [pc, #544] ; 8258 <main+0x258>
8034: e51b300c ldr r3, [fp, #-12]
8038: e5823000 str r3, [r2]
/* (0) disable pull up and pull down to float the GPIO */
/* (1 << 0) enable pull down (low) */
/* (1 << 1) enable pull up (high) */
/* Always pull up (high) for LEDs as they require voltage. */
REG32(GPPUD) = GPPUD_PULL_UP;
803c: e59f3218 ldr r3, [pc, #536] ; 825c <main+0x25c>
8040: e3a02002 mov r2, #2
8044: e5832000 str r2, [r3]
/* Loop to wait until GPPUD assignment persists. */
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
8048: e3a03000 mov r3, #0
804c: e50b3008 str r3, [fp, #-8]
8050: ea000005 b 806c <main+0x6c>
select = REG32(GPFSEL4);
8054: e59f31fc ldr r3, [pc, #508] ; 8258 <main+0x258>
8058: e5933000 ldr r3, [r3]
805c: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
8060: e51b3008 ldr r3, [fp, #-8]
8064: e2833001 add r3, r3, #1
8068: e50b3008 str r3, [fp, #-8]
806c: e51b3008 ldr r3, [fp, #-8]
8070: e3530e7d cmp r3, #2000 ; 0x7d0
8074: 3afffff6 bcc 8054 <main+0x54>
#if RPI == 4
/* Push GPPUD settings to GPPUDCLK1 GPIO 42. */
REG32(GPPUDCLK1) = (1 << (42 - 32)); /* GPIO 42 */
8078: e59f31e0 ldr r3, [pc, #480] ; 8260 <main+0x260>
807c: e3a02b01 mov r2, #1024 ; 0x400
8080: e5832000 str r2, [r3]
/* Push GPPUD settings to GPPUDCLK1 GPIO 47. */
REG32(GPPUDCLK1) = (1 << (47 - 32)); /* GPIO 47 */
#endif
/* Loop to wait until GPPUD clock assignment persists. */
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
8084: e3a03000 mov r3, #0
8088: e50b3008 str r3, [fp, #-8]
808c: ea000005 b 80a8 <main+0xa8>
select = REG32(GPFSEL4);
8090: e59f31c0 ldr r3, [pc, #448] ; 8258 <main+0x258>
8094: e5933000 ldr r3, [r3]
8098: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
809c: e51b3008 ldr r3, [fp, #-8]
80a0: e2833001 add r3, r3, #1
80a4: e50b3008 str r3, [fp, #-8]
80a8: e51b3008 ldr r3, [fp, #-8]
80ac: e3530e7d cmp r3, #2000 ; 0x7d0
80b0: 3afffff6 bcc 8090 <main+0x90>
/*
* Enable the JTAG GPIOs
*/
/* Disable pull up/down for the next configured GPIO. */
REG32(GPPUD) = GPPUD_OFF;
80b4: e59f31a0 ldr r3, [pc, #416] ; 825c <main+0x25c>
80b8: e3a02000 mov r2, #0
80bc: e5832000 str r2, [r3]
/* Loop to wait until GPPUD assignment persists. */
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
80c0: e3a03000 mov r3, #0
80c4: e50b3008 str r3, [fp, #-8]
80c8: ea000005 b 80e4 <main+0xe4>
select = REG32(GPFSEL4);
80cc: e59f3184 ldr r3, [pc, #388] ; 8258 <main+0x258>
80d0: e5933000 ldr r3, [r3]
80d4: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
80d8: e51b3008 ldr r3, [fp, #-8]
80dc: e2833001 add r3, r3, #1
80e0: e50b3008 str r3, [fp, #-8]
80e4: e51b3008 ldr r3, [fp, #-8]
80e8: e3530e7d cmp r3, #2000 ; 0x7d0
80ec: 3afffff6 bcc 80cc <main+0xcc>
// Apply to all the JTAG GPIO pins
REG32(GPPUDCLK0) = (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) |
80f0: e59f316c ldr r3, [pc, #364] ; 8264 <main+0x264>
80f4: e3a0253f mov r2, #264241152 ; 0xfc00000
80f8: e5832000 str r2, [r3]
(1 << 26) | (1 << 27);
/* Loop to wait until GPPUD clock assignment persists. */
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
80fc: e3a03000 mov r3, #0
8100: e50b3008 str r3, [fp, #-8]
8104: ea000005 b 8120 <main+0x120>
select = REG32(GPFSEL4);
8108: e59f3148 ldr r3, [pc, #328] ; 8258 <main+0x258>
810c: e5933000 ldr r3, [r3]
8110: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT / 1000; ++i)
8114: e51b3008 ldr r3, [fp, #-8]
8118: e2833001 add r3, r3, #1
811c: e50b3008 str r3, [fp, #-8]
8120: e51b3008 ldr r3, [fp, #-8]
8124: e3530e7d cmp r3, #2000 ; 0x7d0
8128: 3afffff6 bcc 8108 <main+0x108>
// Select level alternate 4 to enable JTAG
select = REG32(GPFSEL2);
812c: e59f3134 ldr r3, [pc, #308] ; 8268 <main+0x268>
8130: e5933000 ldr r3, [r3]
8134: e50b300c str r3, [fp, #-12]
select &= ~(7 << 6); //gpio22
8138: e51b300c ldr r3, [fp, #-12]
813c: e3c33d07 bic r3, r3, #448 ; 0x1c0
8140: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 6; //alt4 ARM_TRST
8144: e51b300c ldr r3, [fp, #-12]
8148: e38330c0 orr r3, r3, #192 ; 0xc0
814c: e50b300c str r3, [fp, #-12]
select &= ~(7 << 9); //gpio23
8150: e51b300c ldr r3, [fp, #-12]
8154: e3c33c0e bic r3, r3, #3584 ; 0xe00
8158: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 9; //alt4 ARM_RTCK
815c: e51b300c ldr r3, [fp, #-12]
8160: e3833c06 orr r3, r3, #1536 ; 0x600
8164: e50b300c str r3, [fp, #-12]
select &= ~(7 << 12); //gpio24
8168: e51b300c ldr r3, [fp, #-12]
816c: e3c33a07 bic r3, r3, #28672 ; 0x7000
8170: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 12; //alt4 ARM_TDO
8174: e51b300c ldr r3, [fp, #-12]
8178: e3833a03 orr r3, r3, #12288 ; 0x3000
817c: e50b300c str r3, [fp, #-12]
select &= ~(7 << 15); //gpio25
8180: e51b300c ldr r3, [fp, #-12]
8184: e3c3390e bic r3, r3, #229376 ; 0x38000
8188: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 15; //alt4 ARM_TCK
818c: e51b300c ldr r3, [fp, #-12]
8190: e3833906 orr r3, r3, #98304 ; 0x18000
8194: e50b300c str r3, [fp, #-12]
select &= ~(7 << 18); //gpio26
8198: e51b300c ldr r3, [fp, #-12]
819c: e3c33707 bic r3, r3, #1835008 ; 0x1c0000
81a0: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 18; //alt4 ARM_TDI
81a4: e51b300c ldr r3, [fp, #-12]
81a8: e3833703 orr r3, r3, #786432 ; 0xc0000
81ac: e50b300c str r3, [fp, #-12]
select &= ~(7 << 21); //gpio27
81b0: e51b300c ldr r3, [fp, #-12]
81b4: e3c3360e bic r3, r3, #14680064 ; 0xe00000
81b8: e50b300c str r3, [fp, #-12]
select |= GPIO_ALT4 << 21; //alt4 ARM_TMS
81bc: e51b300c ldr r3, [fp, #-12]
81c0: e3833606 orr r3, r3, #6291456 ; 0x600000
81c4: e50b300c str r3, [fp, #-12]
REG32(GPFSEL2) = select;
81c8: e59f2098 ldr r2, [pc, #152] ; 8268 <main+0x268>
81cc: e51b300c ldr r3, [fp, #-12]
81d0: e5823000 str r3, [r2]
for (;;)
{
/* Turn on the activity LED. */
#if RPI == 4
/* RPI 4 has LED at GPIO 42, so set GPIO 42. */
REG32(GPSET1) = 1 << (42 - 32);
81d4: e59f3090 ldr r3, [pc, #144] ; 826c <main+0x26c>
81d8: e3a02b01 mov r2, #1024 ; 0x400
81dc: e5832000 str r2, [r3]
/* Other RPIs have LED at GPIO 47, so set GPIO 47. */
REG32(GPSET1) = 1 << (47 - 32);
#endif
// Loop to wait a bit
for (i = 0; i < TOGGLE_LOOP_CNT; ++i) /* loop to pause LED on */
81e0: e3a03000 mov r3, #0
81e4: e50b3008 str r3, [fp, #-8]
81e8: ea000005 b 8204 <main+0x204>
select = REG32(GPFSEL4);
81ec: e59f3064 ldr r3, [pc, #100] ; 8258 <main+0x258>
81f0: e5933000 ldr r3, [r3]
81f4: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT; ++i) /* loop to pause LED on */
81f8: e51b3008 ldr r3, [fp, #-8]
81fc: e2833001 add r3, r3, #1
8200: e50b3008 str r3, [fp, #-8]
8204: e51b3008 ldr r3, [fp, #-8]
8208: e59f2060 ldr r2, [pc, #96] ; 8270 <main+0x270>
820c: e1530002 cmp r3, r2
8210: 3afffff5 bcc 81ec <main+0x1ec>
/* Turn off the activity LED. */
#if RPI == 4
/* RPI 4 has LED at GPIO 42, so clear GPIO 42. */
REG32(GPCLR1) = 1 << (42 - 32);
8214: e59f3058 ldr r3, [pc, #88] ; 8274 <main+0x274>
8218: e3a02b01 mov r2, #1024 ; 0x400
821c: e5832000 str r2, [r3]
/* Other RPIs have LED at GPIO 47, so clear GPIO 47. */
REG32(GPCLR1) = 1 << (47 - 32);
#endif
// Loop to wait a bit
for (i = 0; i < TOGGLE_LOOP_CNT; ++i) /* loop to pause LED off */
8220: e3a03000 mov r3, #0
8224: e50b3008 str r3, [fp, #-8]
8228: ea000005 b 8244 <main+0x244>
select = REG32(GPFSEL4);
822c: e59f3024 ldr r3, [pc, #36] ; 8258 <main+0x258>
8230: e5933000 ldr r3, [r3]
8234: e50b300c str r3, [fp, #-12]
for (i = 0; i < TOGGLE_LOOP_CNT; ++i) /* loop to pause LED off */
8238: e51b3008 ldr r3, [fp, #-8]
823c: e2833001 add r3, r3, #1
8240: e50b3008 str r3, [fp, #-8]
8244: e51b3008 ldr r3, [fp, #-8]
8248: e59f2020 ldr r2, [pc, #32] ; 8270 <main+0x270>
824c: e1530002 cmp r3, r2
8250: 3afffff5 bcc 822c <main+0x22c>
REG32(GPSET1) = 1 << (42 - 32);
8254: eaffffde b 81d4 <main+0x1d4>
8258: fe200010 .word 0xfe200010
825c: fe200094 .word 0xfe200094
8260: fe20009c .word 0xfe20009c
8264: fe200098 .word 0xfe200098
8268: fe200008 .word 0xfe200008
826c: fe200020 .word 0xfe200020
8270: 001e8480 .word 0x001e8480
8274: fe20002c .word 0xfe20002c
Code: Select all
mov sp,#0x8000Code: Select all
__attribute__((naked)) void main (void)
{
__asm volatile("mov sp,#0x8000");
// Rest of C code here
}
Code: Select all
kernel.elf: file format elf32-littlearm
Disassembly of section .init:
00008000 <main>:
8000: e3a0d902 mov sp, #32768 ; 0x8000
Hm, I stuck to the documentation from Post 2 here. The corresponding source is also offered here to compile the examples. Since this is a kind of commercial offer, I assume that it will also work.LdB wrote: ↑Mon Aug 10, 2020 12:17 pmYour code will crash from the first assembler code ... you obviously didn't read any of the stickies
You haven't set the stack pointer (SP) how the hell do you expect to push onto the stack "push {fp}" or you are using only C with no assembler boot?????
How about you try something really basic like we all started set the SP at the top of the start address so it can work down towards 0x0 if needCode: Select all
mov sp,#0x8000
If you are trying to write only in C you will need to make main naked attribute it can't carry prolog or epilog
https://www.keil.com/support/man/docs/a ... 564298.htm
The first line in the main code is then inline assembler for the SP aboveThe output of that is thisCode: Select all
__attribute__((naked)) void main (void) { __asm volatile("mov sp,#0x8000"); // Rest of C code here }Code: Select all
kernel.elf: file format elf32-littlearm Disassembly of section .init: 00008000 <main>: 8000: e3a0d902 mov sp, #32768 ; 0x8000
Code: Select all
8000: e52db004 push {fp} ; (str fp, [sp, #-4]!)
8004: e28db000 add fp, sp, #0
8008: e24dd00c sub sp, sp, #12Code: Select all
__attribute__((naked)) void main(void)
{
__asm volatile("mov sp,#0x8000");
// Rest of C code is the same
unsigned int i, select;
naked
This attribute allows the compiler to construct the requisite function declaration, while allowing the body of the function to be assembly code. The specified function will not have prologue/epilogue sequences generated by the compiler. Only basic asm statements can safely be included in naked functions. While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported.
Thanks for pointing this out, after a small change it has now worked.sean.lawless wrote: ↑Mon Aug 10, 2020 7:00 pmCode: Select all
__attribute__((naked)) void main(void) { __asm volatile("mov sp,#0x8000"); // Rest of C code is the same unsigned int i, select;
Code: Select all
__attribute__((naked)) void main(void)Code: Select all
__attribute__((naked)) int main(void)For me this was a basic thing. Before I go deeper into the matter, I wanted to at least clarify the basics. In this regard, I only had setbacks with RPI2 when it came to USB support. At the time, the RPI2 was new to the market and information was few. Here were my experiments in pure "assembler" and I did not have this problem. For me this is the first time that I have tried something like this with "C" ... Now I want to try again with the RPI4 and possibly again in pure assembler. But even like back then, the information is still very few and I was overjoyed to find this guide. But if you try that and then it doesn't work, it's very depressing.LdB wrote: How about you try something really basic like we all started set the SP at the top of the start address so it can work down towards 0x0 if need
Got a new problem with the documentation.
Code: Select all
arm-none-eabi-gcc -c -DRPI=1 -O2 -ffreestanding -I. -o main.o main.cCode: Select all
arm-none-eabi-gcc -c -DRPI=1 -O0 -ffreestanding -I. -o main.o main.cCode: Select all
#else
/* Other RPIs have LED at GPIO 47, so set GPIO 47. */
/* old: REG32(GPSET1) = 1 << (47 - 32);*/
/* new:*/
REG32(GPSET0) = 1 << (16);
#endifThat is not correct. With an RPI1 is the address GPIO 16.Other RPIs have LED at GPIO 47, so set GPIO 47.
For the RPI 1B+ the LED GPIO is 47. I suspect you have an RPI 1A? Hardware I have and test with are RPI 1B+, RPI 2, RPI 3B+ and RPI 4B.