Minimal Blinky in about 200 bytes

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

Minimal Blinky in about 200 bytes

2,438 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
81 Replies

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by riscy00 on Tue Jan 28 21:54:24 MST 2014
If anyone managed down to 10 byte, I would be in heaven!!!!
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Mon Jan 27 22:35:05 MST 2014
@gbm,

I got you beat, well sort of. Slight modification of your code gets it down to 28 bytes.

The only reason that this occurred is because the LPCXpresso flash programmer now seems to work correctly and does not balk at the checksum being removed.  Re your:

Quote: gbm
I noticed that if I remove the checksum placeholder, the code is not downloaded correctly - maybe the flash programming routine does not compute the checksum if flash image is too short. I don't think it was written for such rotten programs as nanoblink.



I deleted
KEEP(*(.data_at_1c))

from NanoBlink_17.ld and the corresponding
__attribute__ ((section(".data_at_1c")))
uint32_t checksum_placeholder = 0;
in NanoBlink.c

Here is the Sequel
//*****************************************************************************
// NanoBlinkySequel.c
// A newly created adaptation of
//
//*****************************************************************************
//  The tiniest C blink program for LPC17xx - 28 bytes + vec. checksum = 32 B
//  Copyright (c) 2011 gbm
//*****************************************************************************
//
// By larryvc
// Now the tiniest C blink program for LPC17xx - 28 bytes total
// Real men don't need the checksum vector allocated if the code is short enough
//
//*****************************************************************************

#include "LPC17xx.h"

#define LED_PORT LPC_GPIO0
#define LED_MASK (1 << 22)

// set shift (left or right) so that LED state is controlled by bit 19..21
// of free-running counter variable
#define SHIFT(a)    (a << 5)

int main(void);
//*****************************************************************************
// External declaration for the pointer to the stack top from the Linker Script
//*****************************************************************************
extern void _vStackTop(void);

//*****************************************************************************
// The vector table.
// This relies on the linker script to place at correct location in memory.
//*****************************************************************************
extern void (* const g_pfnVectors[])(void);
__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
&_vStackTop,// The initial stack pointer
(const void *)main, // Replaced ResetISR() with main() - allows debugging and disassembly listing to be displayed

};

__attribute__ ((section(".code_at_8")))
int main(void) {

    uint32_t i;// real men don't need to initialize variables

    LED_PORT->FIODIR = LED_MASK;
    while (1)
    {
        LED_PORT->FIOPIN = SHIFT(i++);
    }
}


Quote: gbm
Unfortunately the code generated for Cortex M0 is bigger than the one for M3, so it doesn't fit below 0x1c.



Do you still have the Cortex M0 project?


0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 12:48:35 MST 2011
Thanks a lot jharwood.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Fri May 13 10:46:40 MST 2011

Quote: akhilpo
If you could explain whats that quoted portion of the code does, .



Take a look at post #9 of this thread, I added comments to the code.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 05:01:08 MST 2011
And I do use CMSIS while coding. But in this case I am not the actual coder. I just tried to edit it and run on my LPC1114. Jharwood is the original coder. He posted it in this thread here: [HTML]http://knowledgebase.nxp.com/showpost.php?p=7667&postcount=4[/HTML]
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 04:56:01 MST 2011
I didnt understand that handler, thats why I tried to run it. Not to see a blinking LED. I thought M3 is a little similar to M0. I assumed he (original coder) was accessing the data register of the PORT0. I think thats where I went completely wrong. My whole theory was to just remap the mem address to corresponding one in M0 and make it work. I referred to a M3 architecture reference. It says the portion including 0x2009C014 is a part of some bitbanding stuff. Actually I didnt understand that. If you could explain whats that quoted portion of the code does, I will be very grateful.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Fri May 13 03:26:11 MST 2011

Quote: akhilpo
Zero, I do agree I am a  novice at this. I am really trying to get more understanding about how these works. If you guys can be more explanatory about our mistakes, we can learn much faster. Hope you will understand.



I'm not getting paid for teaching you. Thats good luck for you. I've explained your mistakes already:

1. Use CMSIS, this will protect you as a newbee.

2. Don't mix M0 with M3 and don't mix M0 registers with M3 registers. The result is confusion.

3. Learn C. If you understand C basics, you are able to understand pointers.

4. Learn programming instead of copying. Start with proven samples.

5. Read manuals.

6. Answer question. So why don't you use CMSIS as suggested. Is that something religious?

Are that enough mistakes? How many hours did you spent for a simple LED blinking example? That's not very successful. A proven and reliable way to learn is to use samples.

You want to find the problem in your copied code?

What do you think is this?

unsigned int *p = (unsigned int *)FIO0PIN;
if(*p & LEDPIN)
{
  p += 2;
 }
 else
{
  p++;
 }
 *p = LEDPIN;
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 03:09:20 MST 2011
I dont find anything specific to 17xx except those addresses. And I did compile it for 11xx configuration. If I map it to corresponding addresses for 11xx and compile it as a 11xx project, is it supposed to work?

Zero, I do agree I am a  novice at this. I am really trying to get more understanding about how these works. If you guys can be more explanatory about our mistakes, we can learn much faster. Hope you will understand.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Ex-Zero on Fri May 13 02:21:15 MST 2011
Please stop this nonsense :mad:

Start to use LPCXpresso as IDE with debugger & CMSIS.

You are confusing yourself and others. M0 is not M3, this code was obviously written for LPC1769. If you don't find the simple problem with it, you have proven, that you are not able (or too lazy) to read C code and User Manuals.
So please step back and start learning how to use LPCXpresso as a powerful tool instead of starting in the middle of nowhere with defining non existing registers and not understanding pointers.

The rest of the world is starting with Tutorials and provided examples, so why don't you try that?
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 01:14:16 MST 2011
I just made these changes from that code:
     1.changed header file to LPC11xx.h
     2.changed memory mappings to corresponding memory address of LPC1114:

Quote:
#define STCTRL 0xE000E010
#define RELOAD 0xE000E014
#define FIO0DIR 0x50008000
#define FIO0PIN 0x50003FFC
#define LEDPIN (1<<7)                     



Here is my edited code:

/*
===============================================================================
 Name        : main.c
 Author      :
 Version     :
 Copyright   : Copyright (C)
 Description : main definition
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC11xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
//__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#define STCTRL 0xE000E010
#define RELOAD 0xE000E014
#define FIO0DIR 0x50008000
#define FIO0PIN 0x50003FFC
#define LEDPIN (1<<7)

volatile unsigned int msTicks;

int main(void) {

    unsigned int *p = (unsigned int *)STCTRL;
    //STCTRL = 7  enable timer and interrupt
    *p = 7;
    p = (unsigned int *)RELOAD;
    //RELOAD = (FIRC / 100) - 1 = 40,000 - 1 = 39,999 = 0x9C3F
    // 10 mSec
    *p = 0x9C3F;

    p = (unsigned int *)FIO0DIR;
    *p = LEDPIN;

    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;
        if(*p & LEDPIN) {
            p += 2;
        } else {
            p++;
        }
        *p = LEDPIN;
    }
}
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Fri May 13 00:35:16 MST 2011
Hi akhilpo,

You could have just told me what post it was from, but that's ok.

I was asking you to post the code you wrote so we can help you.

Larry
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Fri May 13 00:17:37 MST 2011
This is the one he posted for 17xx.
/*
===============================================================================
 Name        : main.c
 Author      : 
 Version     :
 Copyright   : Copyright (C) 
 Description : main definition
===============================================================================
*/

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include <cr_section_macros.h>
#include <NXP/crp.h>

// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;

#define STCTRL 0xE000E010
#define RELOAD 0xE000E014
#define FIO0DIR 0x2009C000
#define FIO0PIN 0x2009C014
#define LEDPIN (1<<22)

volatile unsigned int msTicks;

int main(void) {
    
    unsigned int *p = (unsigned int *)STCTRL;
    //STCTRL = 7  enable timer and interrupt
    *p = 7;
    p = (unsigned int *)RELOAD;
    //RELOAD = (FIRC / 100) - 1 = 40,000 - 1 = 39,999 = 0x9C3F
    // 10 mSec
    *p = 0x9C3F;

    p = (unsigned int *)FIO0DIR;
    *p = LEDPIN;

    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;
        if(*p & LEDPIN) {
            p += 2;
        } else {
            p++;
        }
        *p = LEDPIN;
    }
}
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Thu May 12 23:47:52 MST 2011

Quote: akhilpo
I tried to port the code provided by jharwood to LPC1114. But its not working for me. Here are the changes that I have done:



What post did you get the code from?

The code in the SysTick_Handler is written specifically for the LPC1769.

You might want to show us all you code and we can see what else may need to be adapted for the LPC1114.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by akhilpo on Thu May 12 23:33:00 MST 2011
I tried to port the code provided by jharwood to LPC1114. But its not working for me. Here are the changes that I have done:

Quote:
#define STCTRL 0xE000E010
#define RELOAD 0xE000E014
#define FIO0DIR 0x50008000
#define FIO0PIN 0x50003FFC
#define LEDPIN (1<<7)

0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue May 10 23:16:22 MST 2011

Quote: gbm

The code must blink with exactly 1/2 ratio - infinite loop with no conditionals and no interrupts cannot yield any other effect.



I had a similar program on another brand of MCU and it surprised me by not producing a symmetrical pulse.

I was more interested in the pulse shape at different frequencies.  This program does allow for quite a range of frequencies. It might be worth creating a chart showing what frequency is obtained with different shift values and shift direction.  It might take some time to measure the longer pulse widths.  It will probably be easier to do the math.

I didn't think you were using the debugger, just thought I would mention it.  Thanks for the tip on the debug settings.  One of these days I will figure them all out.

The program is not rotten,  it's quick and dirty, and the IDE is broken.  Did I say that?:eek::)
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gbm on Tue May 10 22:55:46 MST 2011
My debugger doesn't complain about the lack of main() - debugger's attitute towards main may be changed in debug settings. Anyway, I don't use the debugger, just wanted to check if it is able to handle my stuff correctly.

The code must blink with exactly 1/2 ratio - infinite loop with no conditionals and no interrupts cannot yield any other effect.

I noticed that if I remove the checksum placeholder, the code is not downloaded correctly - maybe the flash programming routine does not compute the checksum if flash image is too short. I don't think it was written for such rotten programs as nanoblink.

Unfortunately the code generated for Cortex M0 is bigger than the one for M3, so it doesn't fit below 0x1c.
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue May 10 21:45:51 MST 2011
gbm,

If you change all "ResetISR" references in nanoblink.c to "main"  and the ENTRY(ResetISR) in nanoblink_17.ld to ENTRY(main)the debugger won't complain about main not being found. 

I like how changing the shift value changes the blink rate.  It's a great 32 byte programmable oscillator routine.  Have you scoped it to see what the waveform looks like?
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jharwood on Tue May 10 16:42:00 MST 2011
Very clever, gbm :cool:
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by larryvc on Tue May 10 15:07:54 MST 2011
It blinks.  I am very impressed.:)

Feel free to buy yourself an LPCXpresso 1227 board as your prize!:D

I think NXP and CodeRedSupport should definitely take note of this thread and vote on it.  1,456 views in 20 days.:cool:

Thanks,
Larry
0 Kudos

1,080 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by gbm on Tue May 10 14:21:56 MST 2011
My settings are ok, but I am using a different version of LPCxpresso. I have removed the Debug folder from the exported project - maybe this is the problem. The missing script was in Debug folder - maybe it wasn't recreated.

Try the complete .zip - attached. Anyway, the only link script file changed was the main one.

The compiler warning is normal - see the comment in C source. ;)

[ATTACH]428[/ATTACH]
0 Kudos