Weird attiny85 reaction when adding a for loop

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A little background on the program. This program is measuring the time between the falling edges of INT0 (68 of these edges is contained in one signal) then it compares it to the stored values in 3 arrays (3 stored signals) and sees if it equals to any of those. If it does it performs an action based on which signal it equals to.

 

Program waits untill a falling edge signal is captured on the INT0 pin. Then it resets TIMER0 TCNT0 and a variable that counts number of overflows. When another falling edge signal comes along, the program stores the current TCNT0 and number of overflows to _temp variables in main() function. It then in main() interates thorugh all 3 stored signals, calculates their required TCNT0 (with offset) and number of overflows values and checks if the computed (expected time for a certain signal) time matches the actual time between the falling edges. It does this for all 68 falling edges and all 3 arrays.

 

The problem is if I check in a for loop for all 3 signal arrays the attiny85 starts to behave strangely. It doesnt produce any TIMER0 overflows, captures only one INT and so prevents any further computations. But if I check only for one signal like so:

for(uint8_t i = 0;i < 1; i++) {}

 no errors appear.

 

I am guessing this has something to do with optimizations? I am using Atmel Studio with optimizations on.

 

How can I get past this problem?

 

The code/comments are written in my native language so if you need me to translate the comments or something let me know.

 

Thanks for the help!

Attachment(s): 

This topic has a solution.
Last Edited: Sat. Jan 24, 2015 - 06:38 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I haven't looked very closely, but I see that you're using several large global arrays in SRAM.  You've got 7 arrays of 68 uint8_t elements each.  That's 476 bytes.  The t85 has 512 bytes of SRAM, leaving you with only 36 bytes of SRAM for all other .bss and .data variables, as well as for the stack.  That's not very much.  I'd speculate that adding the loop increases the stack usage, and the stack is overflowing into your arrays.

 

All of those arrays are declared const, so you can place them in flash instead of SRAM.  Look into using __flash

https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html

 

EDIT:  A (slightly) closer look shows another 15 bytes used by other globals (5 of those [due to vrednosti_bitov_us] can be moved to flash as well) .  That leaves only 24 bytes for stack.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sat. Jan 24, 2015 - 06:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seems like this could be the problem, I've changed all those array types to: 

const __flash uint8_t array[] = {};

TIMER0 is overflowing and INTs are fireing. But there is now a problem with calculations. I have an array of pointers to those __flash signal arrays:

const uint8_t *vrste_vklop_bitov_kaz[VB_STEV] = { vklopni_biti_tv, vklopni_biti_vk_ojac, vklopni_biti_iz_ojac };

And a function which calculates required number of onverflows and tcnt value:

(This gets all messed up for some reason, please see the c file and this function...)

inline void izracunaj_bit_ovf_tcnt(uint8_t index, const uint8_t *biti, uint8_t *st_ovf, uint8_t *tcnt)
{
    *st_ovf = vrednosti_bitov_us[biti
] / (CASOVNIK_US * CASOVNIK_ST_VR); *tcnt = (vrednosti_bitov_us[biti
] / CASOVNIK_US) - (*st_ovf * CASOVNIK_ST_VR); }

 

This function gets called in the main() like so:

uint8_t st_ovf = 0;
uint8_t tcnt_vr = 0;
izracunaj_bit_ovf_tcnt(tr_bit_index - 1, vrste_vklop_bitov_kaz[i], &st_ovf, &tcnt_vr);

Where i iterates over all those pointers in *vrste_vklop_bitov_kaz[].

 

The thing is, it seems like wether tr_bit_index = 0 or tr_bit_index = 1. I get the same results and its the result for the tr_bit_index = 0.

Where am I wrong?

Last Edited: Sat. Jan 24, 2015 - 07:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What happens when tr_bit_index is 0?:

izracunaj_bit_ovf_tcnt(tr_bit_index - 1, vrste_vklop_bitov_kaz[i], &st_ovf, &tcnt_vr);
.
.
.
inline void izracunaj_bit_ovf_tcnt(uint8_t index, const uint8_t *biti, uint8_t *st_ovf, uint8_t *tcnt)
{
    *st_ovf = vrednosti_bitov_us[biti[index]] / (CASOVNIK_US * CASOVNIK_ST_VR);
    *tcnt = (vrednosti_bitov_us[biti[index]] / CASOVNIK_US) - (*st_ovf * CASOVNIK_ST_VR);
}

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've had to also change the type of the array that contains pointers to the __flash arrays to the same type, const __flash uint8_t (makes sense). I've also had to change the parameters of the inline function that computes the number of overflows and tcnt to accept __flash pointer to __flash array.

 

There were also a mistake with tr_bit_index incrementing to fast. But the main problems were with the __flash keyword.
Now everything works fine. Thanks alot joeymorin!!

Last Edited: Sat. Jan 24, 2015 - 08:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Its never 0 (in theory), I guess I could do a check, just to be sure. I've posted below what else was wrong.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I've had to also change the type of the array that contains pointers to the __flash arrays to the same type, const __flash uint8_t (makes sense).
I assume you mean you changed this:

const uint8_t *vrste_vklop_bitov_kaz[VB_STEV] = { vklopni_biti_tv, vklopni_biti_vk_ojac, vklopni_biti_iz_ojac };

... into this:

const __flash uint8_t *vrste_vklop_bitov_kaz[VB_STEV] = { vklopni_biti_tv, vklopni_biti_vk_ojac, vklopni_biti_iz_ojac };

This will declare and initialise vrste_vklop_bitov_kaz[] to be an array of pointers to const __flash uint8_t, i.e. an array of pointers to some things with those things residing in flash.  However, the array itself will still reside in SRAM.

 

In order to place that array in flash:

const __flash uint8_t * const __flash vrste_vklop_bitov_kaz[VB_STEV] = { vklopni_biti_tv, vklopni_biti_vk_ojac, vklopni_biti_iz_ojac };

Since in your case the array you are declaring is only 3 elements (6 bytes) long, there isn't a huge impact on SRAM usage, but it's a good thing to know how to do.

 

A useful post:

https://www.avrfreaks.net/comment/795198#comment-795198

 

A useful site:

http://cdecl.org/

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Sun. Jan 25, 2015 - 12:43 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

  Is this Slovenian language?

  Are you decoding an infraRed television remote-controller?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thats right. Making one remote out of three remotes for easier operation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for clearing that. I understand this __flash keyword better now.