Bare metal from scratch, help? :)

@drummyfish on the LPC11U68 (and I suspect other ARM cortex as well) you cant write to EEPROM or rewrite/delete flash memory areas without hard coded ROM api calls. I don’t see how it would even be possible. The sysclock drops to internal clock and interrupts are disabled etc during those procedures. The application is not executing when those things are happening.

1 Like

Hmm so that LED that’s inside Pokitto isn’t part of the MCU board, right? I can’t find it the user manual :mag: I also can’t find in the code where in the memory it is mapped, anyone knows please?

Pokitto board has only two leds, one for power on and other for charging. They are not controllable by the user in any way

1 Like

Ooooh, okay. What would be the easiest way to get a basic output then? IS DAC easier to init than display so that I can get some beep? Or maybe the rumble motor in JoyHat?

An LED or voltmeter in the PEX is probably the simplest thing.

Led in PEX is by far the easiest output

Okay okay, extremely lame question now. CAN I just stick an LED to the PEX without buying that plastic matrix thing? :laughing:

1 Like

ARMv6 Architecture Technical Manual, p. 221 (about vector table):

The entry at offset 0 is used to initialize the value for SP_main, see The SP registers on page B1-211. All other entries must have bit [0] set to 1, because the bit defines the EPSR T-bit on exception entry, … f bit [0] of the associated vector table entry is 0, execution of the first instruction causes a HardFault

What? :open_mouth: Why? Do they literally want the function pointers in the table to have LSB 1? I want to believe I’m wrong. This I’d have to do in the linker script? This is weird and complicated. (hmm or maybe it’s the highest bit?)

It’s the lowest bit. Pointers to functions using the Thumb2 IS must be odd. Not just for interrupts, this applies for all functions despite the fact that instructions always start on an even address. That means they point one byte past the beginning of the function itself. This is something the compiler usually takes care of automatically, but you’ll have to keep it in mind because it can be an issue occasionally (such as when calculating the checksum).

2 Likes

Not a lame question. Yes you can. Set ext0 & ext1 to output via registers, stick a led in between. Use one output low ans the other high and you’ll have the led on.

Not officially recommended (because no resistor) but I am yet to see any problems

2 Likes

Thank you so so much my friends and sorry for bothering again:

@FManga in your PokittoMini startup.cpp you simply set the checksum to 0 in the table. How come it works? In PokittoLib it is computed in the linker script and exported as__valid_user_code_checksum and placed in the table in the init code, which BTW doesn’t work for me in C as it says it’s not knowable at compile time. As I’m thinking about it, how the heck can that even work in PokittoLib, the compiler can’t know the checksum before linker assigns a specific address. I’m a noob.

MiniLib does it the old-fashioned way: as an extra build step. Before I added the checksum to PokittoLib’s linker script, the checksum was written into the bin by the mbed IDE. FemtoIDE also adds this checksum, so the code in the linker script is only used by people using C++ with Makefiles.

            function calculateChecksum( binBytes ){
                    let acc = 0;
                    let u32 = new Uint32Array( binBytes );
                    for( let i=0; i<4; ++i )
                        acc -= u32[i];
                    u32[7] = acc;
            }

The compiler doesn’t need to know. In C++ the linker can put the right value where it needs to be.

2 Likes

Amazing :slight_smile: I’ll force feed the checksum to the generated bin then lol.

Project now lives here: https://gitlab.com/drummyfish/pot.

2 Likes

OK so I’ve bought a multimeter, can confirm PEX works, I measure 3,3 volts on the pin I set with PokittoLib! However the interface is pretty cryptic and bloated, having a class and multiple layers over a literal write to a memory address, so I now have to figure out where exactly the pin address is plus set the pin to the output mode, then I can make a basic hello multimeter.

Question: do all pins behave the same or do the analog/PWM/etc do something special? I.e. can I just pick any pin for my experiments?

EDIT: Writing to pins from my program seems to work!

I refer you to this image:

And its accompanying article:

Though that only half answers the question because it’s not obvious what all of those markings mean and that doesn’t tell you how to make use of those features.

I believe EXT 0 through EXT 17 ought to be able to be used as both digital inputs and digital outputs, so that’s probably a good place to start, particularly if your goal at the moment is just to light up an LED.

You may also want to read the tutorial I wrote eons ago that shows how to set up an LED on a breadboard and provides some code demonstrating how to use DigitalIn which you could use as a baseline to compare your own library variant with.


int value = pin; might be a tad cryptic, but I don’t see how pin.read() is any more cryptic than read(pin) or how pin.is_connected() is any more cryptic than is_connected(pin).

As for ‘bloated’, it’s not likely to be that more expensive than maintaining a pin variable and having a set of functions for interacting with pins.

There’s no virtuality or weird indirection going on here, the DigitalIn/DigitalOut classes are just zero-cost wrappers around a C-like API.
Assuming ARM doesn’t do something weird with thiscalls, the end result should be as if the C-like API had been used directly.

I.e. the compiler will end up translating this:

DigitalIn pin(LED1);

if(pin.is_connected())
{
	std::printf("Value: %d", pin.read());
}

To the equivalent of:

gpio_t gpio = gpio_t();
gpio_init_in(&gpio, LED1);

if(gpio_is_connected(&gpio))
{
	std::printf("Value: %d", gpio_read(&gpio));
}

If those functions are small enough they’ll be inlined.
If they aren’t small enough to be inlined by the compiler, you probably don’t want them to be inlined anyway.

(Though in fairness I haven’t seen how those gpio functions are implemented so I can’t vouch that they’re as simple as they could be.)

1 Like

Thanks!

Now I have a periodically blinking pin and also the screen is blinking along as I’m setting all GPIO pins, awesome! So the next step now could be reading the buttons and output their value. The buttons also live on some GPIO address, ok?

In the assembly init function they do this:

// init buttons
SET 0x40044084,0x88
SET 0x40044070,0x88
SET 0x40044088,0x88
SET 0x40044094,0x88
SET 0x4004406c,0x88
SET 0x400440c4,0x88
SET 0x4004407c,0x88

I wonder what that means.

EDIT: Hmm it seems to be in some “APB peripherals” area.

EDIT: Ok it’s IOCON, not GPIO. I wonder what the difference between “normal” and general purpose IO is.

I think “normal” is the same as “general purpose”; a digital input or output that you can read or set “high” or “low”. This is opposed to assigning a pin to do a special function, such as the Tx line of a UART or an analogue input.

From the doc it seems like the “not GPIO” IO has some extra functions like hysteresis or glitch filters.

No, hysteresis or a glitch filter would be something that could be configured for a GPIO input pin.

1 Like