PSOC1 Timer read value / ISR 16bit variable problem

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hello,

I was struggled days for my project, but I can't either get a clue out of these problems or find a way go around of them.
Here I post what I encountered and looking for someone else who has any thought.
 

   

(1)

   

When I tried to read timer values, I always got the compare values I set in the module parameters, like:

   


Timer8_ms with a period/compare value of 99/49, when I call "Timer8_ms_bReadTimer()", I always got a constant 49 returned.

   

Same problem occurrs when I utilitizing Timer16 module. I've tried to copy values from register like "Timer8_ms_COUNTER_REG" "Timer8_ms_COMPARE_REG" but they are all constant as well.

   

code is like this:
    tmp_ten_us = Timer8_ms_bReadTimer();
    RTC.ten_us = 99 - tmp_ten_us;    //    converting count-down 10us value to count-up for easier human reading
    tmp_ms = Timer16_min_wReadTimer();
    RTC.ms = 59999 - tmp_ms;    //    converting count-down ms value to count-up for easier human reading

   

 

   

(2)

   

When ever I tried to manipulated or referencing an "unsigned int" inside an ISR--like "ms++" or "if ( ms > 999 )", the MCU hangs and I could only re-active it via setting XRES high. Is it normal, or am I missing something important?

 

   

Any idea? Thanks.

0 Likes
28 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the forum!

   

As usual: best will be to post your complete project here, so that we can look at all of your settings.

   

To do so, use Designer -> File -> Archive Project and then attach the resulting file.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Forgot to say, this project is performance required, and I need an UART as fast as possible, like at least 500kbps or higher for transferring  ADC values and timing back to a host computer.

   


So adding anything inside the ISR to work around problems will be my last option..
 

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The UART runs in internal hardware (thanks PSoC!!!) so you have time for your interrupt executing about 250 instructions while one byte is transmitted. That is fairly enough to handle an interrupt.

   

Again: Post your project and we will have a look at.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 Bob,  thanks for your quick reply. But, since I am away from computer right now, I cannot post the complete code immediately. 

   

 

   

Even though, it will be a great help if you can tell me 

   

1.read the current timer counter value should be working via calling "Timer16_wReadTimer()" or so. 

   

2.16bit variables are compatible in ISR mostly.

   

 

   

I don't have much firmware coding experience so it was composed mainly in C code.. 

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

1) bReadTimer() and wReadTimer() are the right routines.

   

2) Of course you may use global or local int16 within interrupt handlers

   

Do you use an ICE-Cube or why are you sure that accessing an int16 stalls your handler?

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Read carefully the API calls you are using, I think you should

   

use the Timer8_bReadTimerSaveCV API to get value.

   

 

   

Did you declare your ISR variable as volatile ?

   

 

   

    

   

          http://www.barrgroup.com/Embedded-Systems/How-To/C-Volatile-Keyword    Volatile

   

 

   

Regards, Dana.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Did you ever consider using a PSoC4 CY8C42XX? Fmax 48MHz, UART 1Mbps, ADC 12-Bit, I2C and more...

   

The Pioneer Kit offers debugging capabilities, the Prototype Board (for $4) can be programmed via BootLoader with a Pioneer-tested project.

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

What part are you using ?

   

 

   

Regards, Dana.

0 Likes
lock attach
Attachments are accessible only for community members.
Anonymous
Not applicable

Just sit back to my computer.

   

To Bob,

   

Thanks for telling me UART didn't take much resource away from MCU core. I have to take care that while I was using another 8051. Will see how much I can push it..

To your question regarding int16 problem in ISR: the system running as expect once I commented all lines that have int16 variables within. When uncommented, it halts immediately while timer w/ interrupt enabled starts. No ICE cube was used..though I wish there is one in hand.

And I was planning moving on to one that with easier debugging capability..after I was familiar enough to these 8-bit ones and basic C programming. Thanks for suggesting PSoC4(LP).

   

 

   

To Dana,

   

Yes, I have tried volatile on my variables that need to be handled in my ISR. Results are the same w/o it. Not sure extern or not matters? I think I've tried using "extern unsigned int" as well..
I'm using CY8C29466PXI on C3210 kit. Coding space and RAM is still under 60% after compiling.

   



Please check attached archive..since I tried many things so it is veeeeeery messy. Sorry for that.
It was under developement and control interface is UART. if it runs correctly and select option 4, there should be a continuous ADC converting after a 100ms waiting--Tmr_wait ( 100 ). But in this code, the RTC.ms and RTC.ten_us can't get correct values so the wait-function hangs..you can check the information returned from UART.

   

 

   

Thanks.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

You use external when you are using a variable in  another file.

   

 

   

Example

   

 

   

in main.c you declare

   

 

   

uint16 myvar = 0;

   

 

   

in mycile.c then you declare

   

 

   

extern myvar;

   

 

   

if its used in an ISR in mycfile.c then

   

 

   

extern volatile myvar;

   

 

   

and in main.c it becomes

   

 

   

uint16 volatile myvar = 0;

0 Likes
Anonymous
Not applicable

To Dana,

   

I've tried ReadTimerSaveCV. But it will cause a system hang or mal-function to other codes--like error in getting input--, so I goes back to ReadTimer. I don't know why.

   

 

   

I thought counter register is what I really care, not compare reg, so it doesn't matter if SaveCV or not..since I want to use it as a hardware-like time clock. Hope I didn't get the idea wrong..

   

 

   

Thanks.

0 Likes
Anonymous
Not applicable

Dear Dana,

   

I use substitue "#define EXT" or "#define EXT extern" for switching global variable or external one in main_vars.h. As you can see in the first few lines in every .c files. And there's only main.c has "#define __GLOBALS__" that declares the variables' home is here. It was working in Keil C51..and IMAGECRAFT didn't cry about it.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

I do not see where you have set up your C interrupts with

   

the required ljmp (in boot.tpl which is in root project directory) -

   

 

   

    

   

          http://www.cypress.com/?id=4&rID=36720

   

 

   

I thought counter register is what I really care, not compare reg, so it doesn't matter if SaveCV or not..since I want to use it as a hardware-like time clock. Hope I didn't get the idea wrong..

   

You are correct here.

   

 

   

Regards, Dana.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Just as an aside thought maybe this ref material might be useful, attached.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Dana,

   

 

   

The code was using the "C ISR Declaration" way in the link you provided: using #pragma directive and inserts a "ljmp _C_func" between appointed lines in Timer[what-ever]INT.asm. It has no problem if the code is relatively simpler. I also tried lcall along with PRESERVE_CPU_CONTEXT and RESTORE_CPU_CONTEXT but int16 still causing hang if interrupt sources started, like timer8 or timer16.

   


I will give boot.tpl another try as you suggested here and in many other discussions.

   

 

   

Thanks.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Your EXT-mimic takes a bit of getting used to...

   

Interrupt handling in PSoC1 is a bit complicated. You successfully declared your handlers using #pragma, but you did not yet connect one of the handlers to the correct interrupt number.

   

When you look into boot.asm you find at the beginning a hint to make required changes in a file named "boot.tpl" from which the file boot.asm will be generated.

   

You have to insert the correct LJMP  _YourHandler into the right places (mark the leading "_")

   

I would suggest you to try that on a smaller project to get it right.

   

 

   

Bob

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

That part of the link does NOT apply to the Imagecraft #pragma implementation,

   

continue reading down in the page.

   

 

   

You have to code the ISR vector into the jump table in boot.tpl

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Bob and Dana,

   

I saw the boot.asm has correct "ljmp _[C-func]"-s, like _Tmr_10uS/ms/min_INT, in correlating positions. I don't think I have to change it? I bought the idea of EXT defines from a former college..and found it useful if the codes has to be somewhat big and complex..meanwhile there are a lot of data needed to be shared between functions..

   

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

But anyway..after save-as the whole workspace and re-editing the "boot.tpl" (change `@INTERRUPT_14` to ljmp _[xxxx] and then back to `@INTERRUPT_14`)..int16 in ISRs are working again..wired. Is there something I should take care for preventing possible compiling corruption?

However, reading counters with ReadTimer function still get constants.. 😕
 

   

At least I got a working solution for my RTC.

   

Big thanks to both of you. :))

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Verify that you can get a breakpoint in the C ISR, the setup still seems

   

baffling to me, especially why your boot.asm file seems to have the

   

ljmps in the C ISR w/o modifiying boot.tpl.

   

 

   

Something is wacky.

   

 

   

Regards, Dana.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

The entries in the interrrupt-table are done automatically when a component is used that -like a Timer- has an interrupt defined. The target lies within one of the generated files and could be filled with your own asm instructions. Saving and restoring the environment is user's duty.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

I have reviewed the codes and there is a mistake in my post has to be addressed:

   

The auto-generated routine like "ljmp _Timer8_ms_ISR" or so in boot.asm actually redirect to Timer8_msINT.asm.

   

Once I have placed a custom routine like "ljmp _Tmr_ms_INT" in the appointed section within Timer8_msINT.asm, custom C interrupt code like "void Tmr_ms_INT ( void )" should be compiled as expected. Though I already read related posts over and over again, I still forgot this basic. Maybe too many codes have overflowed my eyes and mind. 😕

   

Even though, I still hope for clarifying:

   

1.Why int16s have caused problems then went normal afterward? Shouldn't it the IDE's (PSOC Designer) duty to keep the compiling clean enough? I mean itself should be able to make a clean compilation every time a full compiling is executed.

   

2.Why ReadTimer-s are still failed? And can I take a direct copy from REG like "a = Timer8_ms_COUNTER_REG;" for getting a correct current count-down value from "Timer8_ms"? I failed to do both of above. And that makes timers lack something important IMHO..

0 Likes
Anonymous
Not applicable

In your file c_isr.c there is a "return" keyword  at the end of each function. An interrupt doesn't not return a value hence the void at the begenning of the line. Remove the return keyword, it should help.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

I am not sure that matters, in fact Imagecraft and HiTech do not

   

complain when encountering a simple return;

   

 

   

   

Return Statement

    A function can return a value of any type, using the return statement,    
     
      Syntax:     
     
      return       exp;     
     
      return (       exp);     
     
      return;     
    

The return statement can occur anywhere in the function, and will immediately end that function and return control to the function which called it. If there is no return statement, the function will continue execution until the closing of the function definition, and return with an undefined value.

The type of the expression returned should match the type of the function; C will automatically try to convert exp to the return-type.

 

Regards, Dana.

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You can be darn sure that the compiler is able to handle 16bit integers in an interrupt handler, I did that several times so far! The reason for the not-working project is related to something different.

   

You mentioned that you changed the boot.tpl-file? In the project you submitted was nothing changed in that file, so can you supply us with your actual project version?

   

 

   

Bob

0 Likes
Anonymous
Not applicable

 dannaknight,

   

I tried removing the return keyword from the functions in the interrupt handler and it does make a difference in the list file. There is one of the return (the last one I think) that generate a "pop", so that will generate an overflow.

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Eric, maybe I do not understand something. All returns from ISRs result

   

in a POP unless user executes a jump out of the ISR. I looked at C standard

   

to see if a return on a void f() was any different then a f() just ending in braces,

   

and thats where I drew the info I posted from.

   

 

   

Of course a POP in main() restarts, not sure.......

   

 

   

So maybe I have something to learn here ?

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Danaa, maybe you are right, I can't say. Maybe it doesn't change anything but I would avoid placing a return since an interrupt handler is not a regular function. How can we be sure the compiler will interpret it correctly. (Just a thought)

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

I was told today (I'm at embedded world meeting all the Cypress staff) that ther was an error with a 16bit integer in former times, nobody knew for sure if that kind of bug was cured or even pops up anew:

   

When a 16bit integer was allocated on a page boundary, so that one byte resides on page n and the other half on page n+1, there were errors when that var got accessed. I am positively sure that a bug like that has been fixed.

   

Regarding the pop instruction on end of an interrupt handler:

   

There are at end of a handler some instructions needed to restore the original processor state:

   

Some memory locations that are used as pseudo-registers for C are pushed on the stack, of course CPU-registers A and X and additionally the page register and some more special function registers. When no call to other functions is made within the handler, the C-compiler will keep track of used pseudo-registers and of saving only those. A handler is always finished by a pop of the A-register and a RETI (not only a RET) instruction which pops from stack the processor state (flags etc) and the formerly saved program counter.

   

 

   

Bob

0 Likes