This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

limits on size of for loop? or on arrays?

Other Parts Discussed in Thread: MSP430G2553

I come from more of a web-based programming experience, I'm pretty new to C and to microcontrollers so I'm still learning a lot both about the C language and about the MSP430, and there's probably a very simple solution to my problem... In any way:

I'm using an MSP430G2553 and I'm programming it with Code Composer Studio 5.

I made an application that can animate 3 sets of 40 leds using 5 chained shift registers whose outputs go through 5 darlington arrays (ULN2803, they also have 8 inputs/outputs).

In my program I can animate all 40 leds just fine using 5 "shiftOut()" 's (one for each shift register). Now I thought I would try a more complex / extensive animation, so I put together 4 arrays that hold about 257 values each (each array holds the values for one of the shift registers, I didn't need a fifth array because one of the shift registers will always have "0xFF" for this animation).

I'm trying to iterate through these 4 arrays doing a "shifOut()" for each array (plus another "shiftOut(0xFF)"). But when my program gets to this point it doesn't do the animation, the MSP430 just resets itself and starts all over again.

I couldn't quite figure this one out, I thought it might be some sort of memory overflow problem or something, so I tried breaking everything down into smaller pieces. So instead of having a single for loop that iterates 257 times, I now have 12 for loops that iterate 20 times and 1 last for loop that iterates 17 times, so I still I have a total of 257 iterations, but they are broken down into 13 different for loops. I also broke down my arrays to accomplish this, instead of having 4 arrays with 257 values each, I now have 48 arrays with 20 values each, and 4 arrays with 17 values each (that is, 13 arrays for each shift register, just like I have 13 for loops...)

And when it's broken down, it works. So I'm figuring that must be it, some sort of limit for the types I'm casting in, or some sort of memory limits on the MSP430... But doing it this way I don't have the same control over the "delay()" on each iteration. I wanted to do a nifty calculation on the delay() in order to make a nifty animation, but now that I have 13 different for loops it makes it that much more complicated to calculate the delay() in any nifty fashion.

So my question is, do I really have to break everything down into smaller pieces? or is there a more correct way of casting the arrays (like float instead of int or something like that)?

Here's my code if it helps:

 


#include <msp430g2553.h>
#include <math.h>
//Define our pins
#define DATA BIT0 // DS -> 1.0
#define CLOCK BIT4 // SH_CP -> 1.4
#define LATCH BIT5 // ST_CP -> 1.5
#define ENABLE BIT6 // OE -> 1.6
#define NUM_REGISTERS 5 // change this to the number of daisy-chained shift registers
#define NUM_OUTPUTS NUM_REGISTERS*8

// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut ( unsigned char );
void enable ( void );
void disable ( void );
void pinWrite ( unsigned int, unsigned char );
void latchOn ( void );
void latchOff ( void );
void allOn( void );
void allOff( void );
void complexanimate( void );

int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= (DATA + CLOCK + LATCH + ENABLE); // Setup pins as outputs

enable(); // Enable output (pull OE low)

allOn();
delay(500);
allOff();
delay(500);

complexanimate();
}

// Delays by the specified Milliseconds
// thanks to:
// http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx
void delay(unsigned int ms)
{
while (ms--)
{
__delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
}
}

// set latch off to enable Shifting bits in
void latchOff( void )
{
//Set latch to low (should be already)
P1OUT &= ~LATCH;
}

// set latch on to set bits to output
void latchOn( void )
{
// Pulse the latch pin to write the values into the storage register
P1OUT |= LATCH;
P1OUT &= ~LATCH;
}

// Writes a value to the specified bitmask/pin. Use built in defines
// when calling this, as the shiftOut() function does.
// All nonzero values are treated as "high" and zero is "low"
void pinWrite( unsigned int bit, unsigned char val )
{
if (val){
P1OUT |= bit;
} else {
P1OUT &= ~bit;
}
}

// Pulse the clock pin
void pulseClock( void )
{
P1OUT |= CLOCK;
P1OUT ^= CLOCK;
}

// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut(unsigned char val)
{

unsigned char i;

// Iterate over each bit, set data pin, and pulse the clock to send it
// to the shift register
for (i = 0; i < 8; i++) {
pinWrite(DATA, (val & (1 << i)));
pulseClock();
}

}

// These functions are just a shortcut to turn on and off the array of
// LED's when you have the enable pin tied to the MCU. Entirely optional.
void enable( void )
{
P1OUT &= ~ENABLE;
}

void disable( void )
{
P1OUT |= ENABLE;
}

// Some custom effects by me. Can be easily modified, customized, developed.
void allOn( void ){
unsigned int s;
latchOff();
for(s=NUM_REGISTERS;s>0;s--){
shiftOut(0xFF);
}
latchOn();
} void allOff(void){
unsigned int s;
latchOff();
for(s=NUM_REGISTERS;s>0;s--){
shiftOut(0);
}
latchOn();
}
complexanimate(void){
unsigned int m;
const unsigned int sr1[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x02,0x05,0x0B,0x16,0x2C,0x59,0xB3,0x67,0xCE,0x9C,0x38,0x71,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF0,0xE1,0xC3,0x87,0x0F,0x1F,0x3E,0x7C,0xF8,0xF0,0xE0,0xC1,0x83,0x07,0x0F,0x1F,0x3F,0x7E,0xFC,0xF8,0xF0,0xE0,0xC0,0x81,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};

const unsigned int sr2[] = {0x0,0x01,0x02,0x05,0x0B,0x16,0x2C,0x59,0xB3,0x67,0xCE,0x9C,0x38,0x71,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF0,0xE1,0xC3,0x87,0x0F,0x1F,0x3E,0x7C,0xF8,0xF0,0xE0,0xC1,0x83,0x07,0x0F,0x1F,0x3F,0x7E,0xFC,0xF8,0xF0,0xE0,0xC0,0x81,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

const unsigned int sr4[] = {0x0,0x80,0x40,0xA0,0xD0,0x68,0x34,0x9A,0xCD,0xE6,0x73,0x39,0x1C,0x8E,0xC7,0xE3,0xF1,0x78,0x3C,0x1E,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0xF8,0xFC,0x7E,0x3F,0x1F,0x0F,0x07,0x03,0x81,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x03,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

const unsigned int sr5[] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0x40,0xA0,0xD0,0x68,0x34,0x9A,0xCD,0xE6,0x73,0x39,0x1C,0x8E,0xC7,0xE3,0xF1,0x78,0x3C,0x1E,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0xF8,0xFC,0x7E,0x3F,0x1F,0x0F,0x07,0x03,0x81,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF};

for (m=0;m<257;m++){
latchOff();
shiftOut(sr5[m]);
shiftOut(sr4[m]);
shiftOut(0xFF);
shiftOut(sr2[m]);
shiftOut(sr1[m]);
latchOn();
delay(50);
}
}

Here is the same code broken down into smaller pieces:

 


complexanimate1(void){
unsigned int m;
const unsigned int sr1a[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x05,0x0B,0x16,0x2C,0x59,0xB3,0x67,0xCE,0x9C};
const unsigned int sr1b[] = {0x38,0x71,0xE3,0xC7,0x8F,0x1E,0x3C,0x78,0xF0,0xE1,0xC3,0x87,0x0F,0x1F,0x3E,0x7C,0xF8,0xF0,0xE0,0xC1};
const unsigned int sr1c[] = {0x83,0x07,0x0F,0x1F,0x3F,0x7E,0xFC,0xF8,0xF0,0xE0,0xC0,0x81,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFE,0xFC};

const unsigned int sr2a[] = {0x00,0x01,0x02,0x05,0x0B,0x16,0x2C,0x59,0xB3,0x67,0xCE,0x9C,0x38,0x71,0xE3,0xC7,0x8F,0x1E,0x3C,0x78};
const unsigned int sr2b[] = {0xF0,0xE1,0xC3,0x87,0x0F,0x1F,0x3E,0x7C,0xF8,0xF0,0xE0,0xC1,0x83,0x07,0x0F,0x1F,0x3F,0x7E,0xFC,0xF8};
const unsigned int sr2c[] = {0xF0,0xE0,0xC0,0x81,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x01,0x03,0x07};

const unsigned int sr4a[] = {0x00,0x80,0x40,0xA0,0xD0,0x68,0x34,0x9A,0xCD,0xE6,0x73,0x39,0x1C,0x8E,0xC7,0xE3,0xF1,0x78,0x3C,0x1E};
const unsigned int sr4b[] = {0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x07,0x83,0xC1,0xE0,0xF0,0xF8,0xFC,0x7E,0x3F,0x1F};
const unsigned int sr4c[] = {0x0F,0x07,0x03,0x81,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x80,0xC0,0xE0};

const unsigned int sr5a[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x40,0xA0,0xD0,0x68,0x34,0x9A,0xCD,0xE6,0x73,0x39};
const unsigned int sr5b[] = {0x1C,0x8E,0xC7,0xE3,0xF1,0x78,0x3C,0x1E,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x07,0x83};
const unsigned int sr5c[] = {0xC1,0xE0,0xF0,0xF8,0xFC,0x7E,0x3F,0x1F,0x0F,0x07,0x03,0x81,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F};

for (m=0;m<20;m++){
latchOff();
shiftOut(sr5a[m]);
shiftOut(sr4a[m]);
shiftOut(0xFF);
shiftOut(sr2a[m]);
shiftOut(sr1a[m]);
latchOn();
delay(250);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5b[m]);
shiftOut(sr4b[m]);
shiftOut(0xFF);
shiftOut(sr2b[m]);
shiftOut(sr1b[m]);
latchOn();
delay(200);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5c[m]);
shiftOut(sr4c[m]);
shiftOut(0xFF);
shiftOut(sr2c[m]);
shiftOut(sr1c[m]);
latchOn();
delay(150);
}
}

void complexanimate2(void){
unsigned int m;
const unsigned int sr1d[] = {0xF8,0xF0,0xE0,0xC0,0x80,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
const unsigned int sr1e[] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x01};
const unsigned int sr1f[] = {0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x01};

const unsigned int sr2d[] = {0x0F,0x1F,0x3F,0x7F,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F};
const unsigned int sr2e[] = {0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF};
const unsigned int sr2f[] = {0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF};

const unsigned int sr4d[] = {0xF0,0xF8,0xFC,0xFE,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE};
const unsigned int sr4e[] = {0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF};
const unsigned int sr4f[] = {0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF};

const unsigned int sr5d[] = {0x1F,0x0F,0x07,0x03,0x01,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01};
const unsigned int sr5e[] = {0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x80};
const unsigned int sr5f[] = {0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x80};

for (m=0;m<20;m++){
latchOff();
shiftOut(sr5d[m]);
shiftOut(sr4d[m]);
shiftOut(0xFF);
shiftOut(sr2d[m]);
shiftOut(sr1d[m]);
latchOn();
delay(100);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5e[m]);
shiftOut(sr4e[m]);
shiftOut(0xFF);
shiftOut(sr2e[m]);
shiftOut(sr1e[m]);
latchOn();
delay(75);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5f[m]);
shiftOut(sr4f[m]);
shiftOut(0xFF);
shiftOut(sr2f[m]);
shiftOut(sr1f[m]);
latchOn();
delay(50);
}
}
void complexanimate3(void){
unsigned int m;
const unsigned int sr1g[] = {0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00};
const unsigned int sr1h[] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
const unsigned int sr1i[] = {0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC};

const unsigned int sr2g[] = {0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F};
const unsigned int sr2h[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07};
const unsigned int sr2i[] = {0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00};

const unsigned int sr4g[] = {0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE};
const unsigned int sr4h[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0};
const unsigned int sr4i[] = {0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00};

const unsigned int sr5g[] = {0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00};
const unsigned int sr5h[] = {0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01};
const unsigned int sr5i[] = {0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F};

for (m=0;m<20;m++){
latchOff();
shiftOut(sr5g[m]);
shiftOut(sr4g[m]);
shiftOut(0xFF);
shiftOut(sr2g[m]);
shiftOut(sr1g[m]);
latchOn();
delay(75);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5h[m]);
shiftOut(sr4h[m]);
shiftOut(0xFF);
shiftOut(sr2h[m]);
shiftOut(sr1h[m]);
latchOn();
delay(100);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5i[m]);
shiftOut(sr4i[m]);
shiftOut(0xFF);
shiftOut(sr2i[m]);
shiftOut(sr1i[m]);
latchOn();
delay(150);
}
}
void complexanimate4(void){
unsigned int m;
const unsigned int sr5j[] = {0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF};
const unsigned int sr5k[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01};
const unsigned int sr5l[] = {0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0};
const unsigned int sr5m[] = {0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF};

const unsigned int sr4j[] = {0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8};
const unsigned int sr4k[] = {0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF};
const unsigned int sr4l[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned int sr4m[] = {0x00,0x01,0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

const unsigned int sr2j[] = {0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F};
const unsigned int sr2k[] = {0x0F,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF};
const unsigned int sr2l[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned int sr2m[] = {0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

const unsigned int sr1j[] = {0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF};
const unsigned int sr1k[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80};
const unsigned int sr1l[] = {0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x1F,0x0F,0x07,0x03};
const unsigned int sr1m[] = {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF};

for (m=0;m<20;m++){
latchOff();
shiftOut(sr5j[m]);
shiftOut(sr4j[m]);
shiftOut(0xFF);
shiftOut(sr2j[m]);
shiftOut(sr1j[m]);
latchOn();
delay(100);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5k[m]);
shiftOut(sr4k[m]);
shiftOut(0xFF);
shiftOut(sr2k[m]);
shiftOut(sr1k[m]);
latchOn();
delay(75);
}
for (m=0;m<20;m++){
latchOff();
shiftOut(sr5l[m]);
shiftOut(sr4l[m]);
shiftOut(0xFF);
shiftOut(sr2l[m]);
shiftOut(sr1l[m]);
latchOn();
delay(50);
}
for (m=0;m<17;m++){
latchOff();
shiftOut(sr5m[m]);
shiftOut(sr4m[m]);
shiftOut(0xFF);
shiftOut(sr2m[m]);
shiftOut(sr1m[m]);
latchOn();
delay(20);
}
}

// END
  • I do not use c nor CCS.

    I think you createf four arrays of integer constants totaling ~2KB. Because they are constants, they only need to be in Flash and the G2553 has enough Flash for that.

    But because of the way you wrote c code and the way the c compiler handles what you wrote, the resulting object code not only contains those ~2KB of constant in Flash, The code also tries to copy them into RAM allocated to the stack. But G2553 has only 0.5KB of RAM. Thus it crashes at run time.

    To correct this, you need to tell your c compiler to use those constants directly from Flash. Tell it not to copy the constants from Flash to RAM. It is unnecessary even if you have enough RAM.

     

  • John D'Orazio said:
    I'm trying to iterate through these 4 arrays doing a "shifOut()" for each array (plus another "shiftOut(0xFF)"). But when my program gets to this point it doesn't do the animation, the MSP430 just resets itself and starts all over again.

    I couldn't quite figure this one out, I thought it might be some sort of memory overflow problem or something, so I tried breaking everything down into smaller pieces. So instead of having a single for loop that iterates 257 times, I now have 12 for loops that iterate 20 times

    I made a short experiment on mspgcc and I think i found the reason (if the result is comparable to what GCC does)

    It has nothing to do with loops. It's the way you defined your constants. Defining your arrays const does NOT put them into flash. The initialization values are put into flash (of course - where else?) but then the compiler reserves space on stack and copies them over from flash to stack. This is because you declared them as local variables. Sicne local variables are allocated at runtime, you don't get a linker waring about memory overflow. However, at runtime, the stack will overflow with your 'constants' and is unable to store teh return address from your funciton calls. A s a result, the system crashes and reboots.

    If you declare these constants as static, they are allocated at linktime, and the linker can put them into flash properly (which it has already done for the init values before).
    You'll even notice a small decrease of code size (no copy loop necessary to init the arrays).

    Note: 'const' primarily means that you are not allowed to write, not that it will reside in read-only space :)

  • Ok both of your comments have been insightful. I'm still learning about how memory allocation works. I'm lucky I had a friend over today who is pretty learned in this kind of programming and it looks like we worked out a solution.

    Since the arrays are using up quite a bit of memory, we want to declare them locally (inside a routine) and declare them as variables, not as constants or as static, this way the memory dedicated to them is allocated right on the moment, then disallocated and reused again for the next iteration.  Perhaps there is a better way (for example you were mentioning to tell the compiler to read only from flash and not copy to RAM, that's something I have no idea how to do...)  And since the arrays are only holding hex values and are never larger than 1 byte, I can declare them as char instead of as int.

    Anyway here is my working code now:

    char complexanimate1(int ix){
      unsigned char sr1[] = { 257 hex values  };
      return sr1[ix];
    }
    char complexanimate2(int ix){
      unsigned char sr2[] = { 257 hex values  };
      return sr2[ix];
    }
    char complexanimate3(int ix){
      unsigned char sr3[] = { 257 hex values  };
      return sr3[ix];
    }
    char complexanimate4(int ix){
      unsigned char sr4[] = { 257 hex values  };
      return sr4[ix];
    }
    char complexanimate5(int ix){
      unsigned char sr5[] = { 257 hex values  };
      return sr5[ix];

    char complexanimate(void){
      unsigned int m;
      for(m=0;m<257;m++){
        latchOff();
        shiftOut(complexanimate5(m));
        shiftOut(complexanimate4(m));
        shiftOut(complexanimate3(m));
        shiftOut(complexanimate2(m));
        shiftOut(complexanimate1(m));
        latchOn();
      }

    Dealing with the arrays locally like this and declaring them as variable instead of as constant lets the same memory be allocated then freed up every time the routines that return the values from the arrays are called. I don't know if that has an impact on performance...

  • As I told you to begin with, I do not use c. But I think if you add the attribute static to the const declarations, the compiler would leave those const in Flash and would not try to copy them into RAM -- just like what JMG suggested.

    Use your original code, change the 4 statements from "const unsigned int ..." into "static const unsigned char ...". I think it will run correctly. Take a look at how much Flash it uses, how much RAM it uses.

    Now use your recent code that breaks the big arrays into pieces. Take a look too. I think it uses more Flash, more RAM, and takes longer to run too.

  • I did try changing the 4 statements from "const unsigned int" to "static unsigned char", but that broke on linktime. I didn't realize that you can declare as "static const unsigned char"... I'll try that then. I still don't quite understand these declarations, it's all pretty new to me...

  • John D'Orazio said:
    Since the arrays are using up quite a bit of memory, we want to declare them locally (inside a routine) and declare them as variables, not as constants or as static, this way the memory dedicated to them is allocated right on the moment, then disallocated and reused again for the next iteration.

    I understand your intention, but it was thinkign into the wrong direction. Since you initialize the arrays, the initialization dat astill needs to be stored in flash and copied to ram each time you enter the function. Also, since you defined all these arrays in teh function, they all are created on the stack on function entry. You'll always need all the space at this point. Sure, it would be freed on function exit but this didn't work for you (see below). Finally, you never write to them, so why puttign them into local variables on ram? The init values are already in flash to init the arrays, so they can as well be used as the arrays directly, which is done by declaring them static const or putting them as const in global memory.

    John D'Orazio said:
    I did try changing the 4 statements from "const unsigned int" to "static unsigned char", but that broke on linktime.

    And for a reason. Now the space required on stack for the non-static local variables is allocated in global memory at linktime. And the linekr now knows how much memory is needed and tells you that it doesn't fit. For non-static local variables, the same amount of memory is needed, but only at runtim. The linker cannto tell you when and how much this will be and cannot tell you that you fdon't have the memory at all for this.

    Only global or static const variables (well, they are no variables if they are const :) ) are directly placed in flash and don't consume any ram.
    If you declare a local variable as static, it statically allocates ram as if it were a global vbariable, with the difference that its name is not known outside the funciton. Then, and only then, const will cause them to be put statically into flash.

    P.s.: you may also declare a global variable as static. This has no influence on its storage, but it will limit the visibility of its name (the 'scope') to the current .c file. It's not 'global' anymore but local to the current file. You cannot access it form other .c files then and it won't conflict with diferent global variables of the same name in other .c files.

  • JMG,

    May be one could create the constants in Flash moments before they are needed. And erase them moments after they are not needed any more.

    For that matter, this scheme applies to the code too. But not sure about the code that implements this scheme.

    --OCY (just kidding)

  • old_cow_yellow said:
    May be one could create the constants in Flash moments before they are needed. And erase them moments after they are not needed any more.

    Well, for unrelated constant data, this doesn't make much sense, but if the constants are calculated by a formula that depends on runtime variable values, this could make sense. E.g. if you need a sine wave whose frequency or amplitude depends on synamic settings, you might want to create the table in flash dynamically in flash and then use DMA to move it out through DAC.
    Or when you calibrate your device, you might want to create a calibrated version of your constants in flash.

    About code, well, a code that loads other code dynamically from external storage could be considered following this scheme. Early DOS overlay machanisms worked this way as well as todays virtual memory. If you step back and look from a greater distance, many things follow the same pattern where you wouldn't expect it while implementation details clobber your view.

  • Ok I think I'm starting to get the picture, I now tried declaring the arrays as static const and it works just fine.

    Jens-Michael Gross said:
    The init values are already in flash to init the arrays, so they can as well be used as the arrays directly, which is done by declaring them static const or putting them as const in global memory.

    Only global or static const variables are directly placed in flash and don't consume any ram.

    P.s.: you may also declare a global variable as static. This has no influence on its storage, but it will limit the visibility of its name (the 'scope') to the current .c file. It's not 'global' anymore but local to the current file. You cannot access it form other .c files then and it won't conflict with diferent global variables of the same name in other .c files.

    Ok let's see if I understand. If I only want to store and access the arrays and their values from flash without using RAM, in order to improve performance and avoid memory overflows, I have a few different options:

    1 - declare the arrays at the global level (e.g. "unsigned char" at the beginning of my main.c file, outside of any routines). The arrays will be visible outside of main.c. (Or do they have to be declared as "const unsigned char" in order not to be loaded into RAM?)
    2 - declare the arrays at the global level as static (e.g. "static unsigned char"). The arrays will not be visible outside of main.c.
    3 - declare the arrays locally within a routine, as static const (e.g. "static const unsigned char").

    So at this point I am declaring them within a routine as static const. Would there be any performance improvements if I declare them globally rather than locally, or does that not make a difference?

     

  • John D'Orazio said:
    1 - declare the arrays at the global level (e.g. "unsigned char" at the beginning of my main.c file, outside of any routines). The arrays will be visible outside of main.c. (Or do they have to be declared as "const unsigned char" in order not to be loaded into RAM?)

    If you don't declare them as const, they have to go into ram as they are writable. The init values are stored in flash and the arrays are initialized on startup but can be changed later by the application. If you declare them const, theey won't be copie dinto ram. Instead the 'init data' in flash will be referenced by the code. The arrays will be visible for all parts of the applciation at linktime (but if you don't declare them in a header file, they won't be visible in other .c files at compile time, maybe leading to double-declaraion errors at linktime)

    John D'Orazio said:
    2 - declare the arrays at the global level as static (e.g. "static unsigned char"). The arrays will not be visible outside of main.c.

    Right. And if you declare them as static const, they will end up in flash.

    John D'Orazio said:
    3 - declare the arrays locally within a routine, as static const (e.g. "static const unsigned char").

    Anythign declared (or rather defined, as you provide init values) in a fuction will only be visible inside this function. Static variables have permanent storage which will be accounted for during linktime and are initialized at program startup. const variabels are allocated on stack at funciton entry and theoir memory requirements are unknown to the linker. They are initialized from flash at funciton startup. Static const variables end up in flash while still only visible from within the function.

    John D'Orazio said:
    So at this point I am declaring them within a routine as static const. Would there be any performance improvements if I declare them globally rather than locally, or does that not make a difference?

    There is no performance difference. The only difference is that you may have different static const arrays with the same name in different functions. But I think, this is more important for variables like 'i' and 'x' :)

  • Ok thanks that's some really helpful information! I'm gonna be using this for theatrical special effects in a couple weeks in a charitable event. As soon as I have a video of the performance I'll post a link, you have some merit in it too!

**Attention** This is a public forum