RAM Paging and C?

A catchall for PSoC Mixed-Signal Array (microcontroller) discussions not captured by the other forums.

Moderator: ericb

RAM Paging and C?

Postby smithb79 on Mon Jun 19, 2006 1:21 pm

I am trying to deal with RAM paging for the 2k RAM devices. I am writing in C in PsoC Designer.

My program runs into the ground after I allocate more than 256 bytes. I thought the solution was to go to Project->Settings and click the "Enable Paging" box, but that is already set (stack page = 7, stack offset = 0). I would then think that the compiler would handle the RAM paging in the background, but that does not seem to be the case.

Anybody out there who allocates more than 256 bytes and using C, please respond. I need your advice! How do you use the entire RAM space with C?
smithb79
Bite-Size Cheese
Bite-Size Cheese
 
Posts: 20
Joined: Mon May 15, 2006 5:23 am
Location: Seattle, WA

Postby wrightpc on Mon Jun 19, 2006 2:27 pm

The C compiler should be working fine.

Do you have some assembly sections, or just in C? If you have enabled paging then any assembly sections need to also use paging.

Only other thought is do you have the right chip? If you try to use 2k on a device that does not have it then the stack will fail and the program not run.

Paul. :)
User avatar
wrightpc
The Big Cheese
The Big Cheese
 
Posts: 736
Joined: Thu Jul 28, 2005 7:56 pm
Location: Christchurch, New Zealand

Postby smithb79 on Mon Jun 19, 2006 2:45 pm

It's all being written in C, with just a single interrupt that provides a 25 msec timer flag. I also have a bunch of look-up tables that are 20 bytes each (10 words), so it's easy to exceed 256 bytes. Everything works fine if I comment out enough of the tables to come in under 256 bytes, but once I call for more than 256 bytes, the variables do not work anymore. For example, the byte that serves as the flag in the interrupt routine will not change, even if the emulator shows an increment command on it.

I'm using a CY8C29 emulator right now. I double-checked the RAM specs once I realized that it failed under 256 bytes allocated. I called Cypress and they said much the same thing - the compiler should handle it transparently.

Odd...maybe I'll have to examine the paging registers and see exactly where things are going... :roll:
smithb79
Bite-Size Cheese
Bite-Size Cheese
 
Posts: 20
Joined: Mon May 15, 2006 5:23 am
Location: Seattle, WA

Postby graaja on Mon Jun 19, 2006 5:16 pm

Hello Smith,

Can you post your project here?
User avatar
graaja
PSoC Master
PSoC Master
 
Posts: 3084
Joined: Thu Dec 18, 2003 4:35 pm
Location: India

Postby wrightpc on Mon Jun 19, 2006 8:05 pm

Why do you have lookup tables in RAM? If they don't change then define them as const and the compiler will put them in FLASH. Could be the compiler is somehow sticking the tables across a page.

Also, is your interrupt in assembly? If so them allocate your variable in the interrupt assembly file in the region InterruptRAM, as this is guaranteed page0. Could be your interrupt variable was being pushed to page1, meaning your interrupt routine would be altering a variable on page0, corrupting it's value. You can get your C file to use it by defining as "extern unsigned char name".

As Ganesh said, post your project so we can see the issue.

Paul. :)
User avatar
wrightpc
The Big Cheese
The Big Cheese
 
Posts: 736
Joined: Thu Jul 28, 2005 7:56 pm
Location: Christchurch, New Zealand

Postby smithb79 on Tue Jun 20, 2006 7:14 am

The look-up tables are generated during calibration cycles of my machine, and while the results are stored in EEPROM, they have to be generated in real-time.

I've found the error that is causing my problem, and I've attached the source for you to see. I've pared it down greatly to make it easier to read (full version is 10k of Flash, 500b of RAM), but the error appears if you run this abbreviated version.

The problem is TimeFlag, which is operated on both right after main() and inside the timer ISR. If you set breakpoints on the code with TimeFlag in both the main() section and ISR section and watch the FLAGS register, you'll see that RAM paging is enabled when TimeFlag is modified in main(), but DISABLED when operated on the interrupt. Not good if your variable is on Page 7 and the interrupt defaults to Page 0. This is how interrupts are handled (reference PsoC TRM v2.10 manual, section 4.1.3).

So that is the problem. Now for the solution - manually operating the RAM paging in the ISR, I suppose. :o


//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules

void Krnl_ISR(void);


INT8U TimeFlag = 0;
INT16U Angle_Snsr = 0;
INT16U Pressure_Snsr = 100;
INT8U Station2Ctr = 0;
INT8U Station5Ctr = 0;
INT16U Angle_Prev_2 = 0;
INT16U Angle_Prev_5 = 0;
INT8U Station2sec_Flag;
INT8U Station5sec_Flag;
INT8U MoveFlag = FALSE;
INT16U Angle_Avg[5];


INT16U UpCurve_LowLimit[10];
INT16U UpCurve_UpLimit[10];
INT16S UpCurve_Num[10];
INT16S UpCurve_Den[10];
INT16S UpCurve_Yint[10];
INT16U DownCurve_LowLimit[10];
INT16U DownCurve_UpLimit[10];
INT16S DownCurve_Num[10];
INT16S DownCurve_Den[10];
INT16S DownCurve_Yint[10];

INT16U Store_Buffer[18];

void main(void) {
INT8U qrtrsectimer = 0;

M8C_DisableGInt;
TimeFlag = 55;
TimeFlag = 0;

Timer16_1_Stop();
Timer16_1_WritePeriod(37500);
Timer16_1_EnableInt();
Timer16_1_Start();

M8C_EnableGInt;

FOREVER() {
while(TimeFlag == 0) {}
TimeFlag = 0;
qrtrsectimer++;

// Run 25 msec periodicals.


// Run 1/4 sec periodicals.
if(qrtrsectimer >= 10) {
qrtrsectimer = 0;
PRT2DR ^= 0x01;
}

}
TRAP();
}


/*----------------------------------------------------------------------------
void Krnl_ISR(void)
This ISR is driven by the timer resource once every 25 msec, and simply
increments the time flag.
----------------------------------------------------------------------------*/
void Krnl_ISR(void) {
TimeFlag++;
}
smithb79
Bite-Size Cheese
Bite-Size Cheese
 
Posts: 20
Joined: Mon May 15, 2006 5:23 am
Location: Seattle, WA

Postby smithb79 on Tue Jun 20, 2006 7:48 am

More new info -

I watched the CUR_PP register while changing how much RAM is allocated. Before I reach the 256 byte threshold, TimeFlag is put on Page 0. After more allocation, TimeFlag is put on Page 1. CUR_PP maintains the correct page during the interrupt (may be coincidence, may be on purpose), but the CPU_F register disables paging and forces Page 0 because of the interrupt mechanism.
smithb79
Bite-Size Cheese
Bite-Size Cheese
 
Posts: 20
Joined: Mon May 15, 2006 5:23 am
Location: Seattle, WA

Postby smithb79 on Tue Jun 20, 2006 8:12 am

Problem found and corrected.

I thought I could be sneaky and just do an assembly call from the timer library-supplied interrupt to my ISR, then let it return and then reti. So I did not pragma the function as an ISR, else it would return too early.

BUT, not only does #pragma interrupt_handler end the function with a reti and recognize that it is not called, it ALSO carries the RAM paging mechanism with it.

With a quick modify to boot.tpl and a pragma instruction, it works fine now. So the lesson is: never try to cheat the interrupt pragma.
smithb79
Bite-Size Cheese
Bite-Size Cheese
 
Posts: 20
Joined: Mon May 15, 2006 5:23 am
Location: Seattle, WA

Postby alager on Tue Jun 20, 2006 2:41 pm

As was previously stated, when working in C, the paging is handled by the compiler. By using the pragma statement and writing your function in C you acheived that.

If you can't have the overhead of the ISR being in C, then the alternate solution which is faster (execution wise) and smaller (ROM wise) is to declare the variable in the ISR file.
In my timer8INT file I declared a byte named "intopts". The "_" allows the C compiler to see it as a regular variable as well, so main.c can operate on it.
Code: Select all
;------------------------
; Variable Allocation
;------------------------
_intopts:: blk 1


Aaron
User avatar
alager
The Big Cheese
The Big Cheese
 
Posts: 506
Joined: Tue Mar 15, 2005 2:26 pm
Location: Peteluma, CA


Return to PSoC1 General

Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 1 guest

cron