Minimal Blinky in about 200 bytes

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Minimal Blinky in about 200 bytes

8,544 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Wed Apr 20 17:15:35 MST 2011
In the following post CodeRedSupport had said this:


Quote: CodeRedSupport

The example blinky application uses additional libraries such as CMSIS to demonstrate their use. If you use the libraries, this will obviously increase the code size.  A minimal blinky can be done in about 200 bytes.



http://knowledgebase.nxp.com/showpost.php?p=1212&postcount=2

Without resorting to assembly has anybody done this or does anybody have any suggestions on how to do this?

Thanks,
Larry

[COLOR=darkorange]Newbies take note[/COLOR]:  This thread contains advanced programming techniques that are not really suitable for those just starting out with LPCXpresso.  I want to leave this thread open for more experienced users to add ideas.  If you try the programs in this thread and they don't work for you and want to ask why please open a new thread and refer to this one.  In other words, please don't ask in this thread.  Thank You.
0 Kudos
Reply
81 Replies

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Sun Apr 24 13:12:04 MST 2011

Quote:
Should the parameters for the challenge be changed to require a valid C runtime environment?



I think so, yes. What has been proven so far is that the quotation you included in your first post is only possible if the validity of the C runtime environment is disregarded.

Tests show that it is possible to have a minimal program "doing something" (but not particularly useful) written in C, using only one assembler instruction to enable interrupts, in about 356 bytes.

You mentioned that you were stuck at around the 2k mark (which would be alarming when working with a device that had only 8k flash). I think that what you saw was caused by using the CMSIS library and a C standard library.

If you need portability and maintainability of your application, you tend to use the standard libraries while keeping an eye on memory consumption. I find more often that RAM is more of an issue than flash. The SNMP mib tree is interesting as it is a complex data structure using flash as much as possible for the constant nodes and ram for the leaf and table row nodes.

I'm not really sure what would make a good challenge that would get enough interest and be simple and quick to accomplish.:(
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sun Apr 24 11:45:35 MST 2011
Did I exceed the number of questions allowed on this weekend?:o

Oh Oh.  That was another question.:)
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sun Apr 24 10:09:04 MST 2011

Quote: jharwood
Technically, it's not a valid C runtime environment. The data section initialization has been removed, and the bss section has not been zeroed.



Details.  It still blinks.:)

So what do you think.

Should the parameters for the challenge be changed to require a valid C runtime environment?

Is one week pushing it for some of the others that might be interested in attempting this?

I haven't seen much other interest so far and I want this to be a fair challenge.  Should I start a new thread announcing a challenge and link to this thread?

LPC1114 or LPC12xx for the winner.  I forgot which LPC12xx board is available.

Other ideas?:confused:
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Sun Apr 24 09:11:34 MST 2011

Quote: larryvc
....and all while using C.



Technically, it's not a valid C runtime environment. The data section initialization has been removed, and the bss section has not been zeroed.

So while you could write
int foo[] = {1, 2, 3};
as a global variable, the results would not be what you expect. A global constant would be okay though.

You may notice that the very first half cycle (led off) after reset is of indeterminate length, but not more than 500 ms.
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sun Apr 24 01:09:36 MST 2011
jharwood,

I find the fact that you were able to get it down to 168 bytes, is extremely remarkable.:)  Using the reset ISR and omitting main is genius.

This shows that with the proper coding discipline we can cram a lot more into these devices than we previously thought and all while using C.

I'll let this challenge go on for another week.  I have my doubts that this can be beat.

Larry
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sat Apr 23 20:18:25 MST 2011

Quote: jharwood
Did some hacking^H^H^H^H^H^H^H code removal and ended up with this...
Thanks for the challenge Larry. I learned a lot :)



OK. I will allow one asm instruction, but if anyone can do this only in C great.

You're welcome, and you are still in the lead James.

Had to sneak out of a birthday party to send this.  Be back later.
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Sat Apr 23 17:10:34 MST 2011
Did some hacking^H^H^H^H^H^H^H code removal and ended up with this:

arm-none-eabi-size minblink.axf; arm-none-eabi-objcopy -O binary minblink.axf firmware.bin ; checksum -p LPC1769 -d firmware.bin;  cp firmware.bin c:/opt/tftp
   text       data        bss        dec        hex    filename
    164          0          4        168         a8    minblink.axf
Created checksum 0xc67dffef in firmware.bin at offset 0x1c
- Took out all the data and bss section initialization stuff from both the c source, and the linker script.
- Combined all the exception fault handlers into one

Thanks for the challenge Larry. I learned a lot
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Sat Apr 23 15:12:45 MST 2011
So far jharwood's implementation is still the most efficient.

I don't have enough knowledge yet to implement NXP_USAs suggestion but I'm working on it.

Anyone else up to the challenge?

I might have a spare board laying around for the individual that produces the smallest and most efficient working blinky.  It must be a perceptible blink to qualify.
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Apr 21 23:45:50 MST 2011
HAL yes. IBM, aren't we all a little bit.  We should get an opinion from an important mathematical place holder.:D
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Thu Apr 21 23:27:32 MST 2011

Quote: larryvc

HAL: I'm feeling much better now Dave..  Daisy Daisy...



I'm sure you already know this, but if not:

HAL == I(-1) B(-1) M (-1)

and

IBM == "I'm Bloody Mad"  :mad::)
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Apr 21 22:48:07 MST 2011

Quote: jharwood
HTH :)



Immensely.  I'm sane again.  Like Zero once said "[B][COLOR=#ffb210]Pointers[/COLOR][/B] and structures, [B][COLOR=#ffb210]a[/COLOR][/B] [B][COLOR=#ffb210]never[/COLOR][/B] [B][COLOR=#ffb210]ending[/COLOR][/B] [B][COLOR=#ffb210]story[/COLOR][/B]....:)".

HAL: I'm feeling much better now Dave..  Daisy Daisy...

Thanks,
Larry
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Thu Apr 21 22:24:48 MST 2011
Hi Larry

Perhaps this will help:
int main(void) {
    
    unsigned int *p = (unsigned int *)STCTRL;  // p is now set to the address of the STCTRL register
    //STCTRL = 7  enable timer and interrupt
    *p = 7;   // store 7 into the STCRL by de-referencing p
    p = (unsigned int *)RELOAD;  // p is now set to the address of the RELOAD register
    //RELOAD = (FIRC / 100) - 1 = 40,000 - 1 = 39,999 = 0x9C3F
    // 10 mSec
    *p = 0x9C3F;  // store 0x9C3F into the RELOAD by de-referencing p

    p = (unsigned int *)FIO0DIR;  // p is now set to the address of the FIO0DIR register
    *p = LEDPIN;  // store (1<<22) into FIO0DIR by de-referencing p

    msTicks = 0;
    // enable all interrupts
    __asm volatile ("cpsie i");

    // Enter an infinite loop
    while(1) {
    }
    return 0 ;
}

void SysTick_Handler(void)
{
    msTicks++;

    if(msTicks >= (50)) {
        msTicks = 0;
        unsigned int *p = (unsigned int *)FIO0PIN;  // p is now set to the address of the FIO0PIN register
        if(*p & LEDPIN) {  // de-reference p to obtain its value and mask it with (1<<22)
            p += 2;   // move p up by two words (8 bytes) (since p is an unsigned int ptr), so it now points to the FIO0CLR register
        } else {
            p++;    // move p up by one word (4 bytes) so it now points to the FIO0SET register
        }
        *p = LEDPIN;  // store (1<<22) into which ever register was selected above by de-referencing p
    }
}


HTH
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Apr 21 21:18:46 MST 2011

Quote: larryvc

Nice routine though, especially the use of the pointer.



@jharwood,

I thought I had a good understanding of what the pointer manipulation in the ISR was doing.  Today I have confused myself after working it out on paper.:o

Can you clear this up for me before I go further insane?:)

@everyone,

I'm also working on understanding the code that NXP_USA has provided.  I just need to figure out the code to put into the while loop. It shouldn't take too long to implement.

  I have Joseph Yui's book "The definitive guide to the ARM Cortex-M3 Second Edition" out and I am reading it again for more details.  Most of the time I use an LPCXpresso1769 for experimentation and learning, but I do have 3 LPCXpresso1114s just waiting to be tried.

I thought this was going to be an easy one to figure out though it seems I have opened up a can of worms.  All in all I'm glad I started this thread as it has provided me with an opportunity to explore the depths and I have already learned so much more.

Thanks,
Larry
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by NXP_USA on Thu Apr 21 14:00:20 MST 2011
The USB_HID_ROM_TINY example for LPC1343 can also be used as a starting point for making truly minimal applications.
[U]
Be aware that it can be dangerous to place application code into the vector table, so make sure you know what you are doing. [/U]

It should be entirely possible to make a minimal Blinky entirely in C.
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu Apr 21 10:32:30 MST 2011

Quote: larryvc
Actually I would like to challenge the CodeRedSupport person that posted this to buck up and show me how.;)



CodeRedSupport?
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Wed Apr 20 20:00:29 MST 2011

Quote: jharwood
Oh, and there's just one asm line - to turn on the global interrupts :o



That's cheating.:) But only a little bit.  ~100 bytes seems like a lot for just adding a small handler.

I gather that the if (*p... stuff in the Systick_Handler was in main in the version without interrupts that produced 268 bytes.

Need to, thoroughly, study your build options and maybe read a little more about the GCC parameters to get a better grasp on how to obtain the numbers you did.

Nice routine though, especially the use of the pointer.

Thanks again.
0 Kudos
Reply

2,294 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Wed Apr 20 19:52:03 MST 2011
To make it visualizable by normal people, I used the SysTick timer. Now it's a whopping 356 bytes :mad:

Anyway, this runs on a '1769 using the IRC @ 4Mhz. Oh, and there's just one asm line - to turn on the global interrupts :o
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Wed Apr 20 18:58:31 MST 2011

Quote: jharwood
Is it ok for LED to blink at 25Mhz? :D

I'm down to 268 bytes



Sure, I can accelerate, slow, and travel through time.  I am The Doctor.:rolleyes:

Care to share that?  The best I have done is 2K bytes, but I'm still a noob at all this amazing ARM stuff.

I would still like to see a blinky normal people could visualize.

EDIT:  Actually I would like to challenge the CodeRedSupport person that posted this to buck up and show me how.;)

Thanks James.

Larry
0 Kudos
Reply

2,293 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Wed Apr 20 17:32:53 MST 2011
Is it ok for LED to blink at 25Mhz? :D

I'm down to 268 bytes
0 Kudos
Reply