Wixelcmd read provides address too high message

board.c
board.c (6.1 KB)

Hello Kevin,

I found this when I googled.

sourceforge.net/p/sdcc/mailman/message/13598342/

As I mentioned, when I dont use XDATA for arrays I got this error

Compiling apps/test_adc/test_adc.rel
Linking apps/test_adc/test_adc.hex

?ASlink-Warning-Paged Area PSEG Length Error

?ASlink-Warning-Paged Area PSEG Boundary Error
make: *** [apps/test_adc/test_adc.hex] Error 1

Then I had to use XDATA or CODE to move the arrays it compiled fine.

Can you please confirm if that is the problem.

Thanks

I haven’t tried compiling or running your program yet, but I took a brief look at your test_adc.c and noticed a few problems.

First of all, it seems like you’re experimenting with the different address space qualifiers (CODE, DATA, PDATA, XDATA) without really understanding what they mean. I would suggest reading over the description of these qualifiers in the Wixel SDK documentation here.

Any variable with a name that starts with “param_” is treated as a Wixel app parameter by the Wixel software, as mentioned in the “Wixel App File Format” section of the Wixel user’s guide. In order for this to work properly, the variable must use the CODE qualifier. That means its value can be changed when (and only when) the app is loaded onto the Wixel. For instance, the example_blink_led app contains a parameter declared like this:

int32 CODE param_blink_period_ms = 500;

When you load this app in the Wixel Configuration Utility, the parameter is configurable on the right:

In your test_adc.c, you’ve removed the CODE qualifier from some parameters (maybe by accident), which means they’re being put in the wrong memory location (in RAM instead of flash memory), and the Wixel SDK can’t make sense of them. So you should change these lines:

int32 param_input_mode = -1;
int32 param_bar_graph = 1;
int32 param_report_period_ms = 40;

back to the way they were in the original test_adc.c:

int32 CODE param_input_mode = 0;
int32 CODE param_bar_graph = 1;
int32 CODE param_report_period_ms = 40;

Putting your adcOutput arrays in code space is the same problem in reverse: it won’t work for what you’re trying to do because they are stored in flash memory and therefore read-only. (Like the SDK documentation says, the CODE qualifier is appropriate for variables and data structures that never need to be changed, like look-up tables.) You should be able to put them in XDATA space instead:

uint16 XDATA adcOutputX[MAX_BUF_SZ] = {0};
uint16 XDATA adcOutputY[MAX_BUF_SZ] = {0};
uint16 XDATA adcOutputZ[MAX_BUF_SZ] = {0};

Could you try making those changes and see if they help?

- Kevin

Thanks Kevin. Really appreciate your help. I don’t remember changing them. It might have happened by mistake. I was not aware of this mechanism of the parameters. Is test_adc covered in users guide? Anyway, I did compile ok with the changes you suggested. Looking at the memory map, I see the address being used is 000022F7. It will take me couple of days to try it out on the device. Will keep you posted.

Regards

The user’s guide doesn’t specifically talk about the test_adc app. However, if you haven’t already, it would be a good idea to look it over for more general information (especially the Wixel App File Format section I mentioned before) and to read the SDK documentation.

- Kevin

Thanks for you help. That fixed the problem. Now I am getting the hang of working with Wixel. However there are few more things that I have to understand.

Moving on to debug the problem. I am using P0 interrupt on rising edge. I picked up code that was posted in the forum which is posted below. If I use this code as is, I loose control over Wixel. However if I remove the last line (EA = 1), things do tend to work as expected. I dont have anything connected to P0 inputs so the interrupt counter seems to indicate no interrupts. Question is how/when to use EA = 1. Since I rely on a whole bunch of printfs to debug my code, I need to be connected to Wixel to gather all data. Also since I use port 0 and timer 1 interrupts and keep one of the interrupt enabled while the other is disabled, I dont want to inadvertently disable interrupts that may cause the wixel to stop responding. Would enabling port 0 interrupt via IEN1 be sufficient or do I have to use EA = 1? Similar question will apply to timer 1 interrupt. Appreciate your help.

[code]void initialize()
{
systemInit();
usbInit();
//setup a falling edge interrupt on P0_1.
PICTL = 0b00001001; //Port 0, inputs 3 to 0 interrupt enable, only for now
//and falling edge interrupt
IEN1 = 0b00100000; //enable port 0 interrupts
EA = 1; //enable all interrupts

}[/code]

Thanks

Hello,

I was able to solve the problem after I changed the code as shown below. The code which is commented out was the original code.

[code]void enablePort0Trigger(void)
{
#if 0
PICTL = (PICTL & ~0b00000001); // Setup Rising edge

PICTL |= 0b00001000; 		//Port 0, inputs 3 to 0 int enable, 
                    		//and rising edge interrupt
IEN1 = 0b00100000;  		//enable port 0 interrupts
//EA = 1;

#endif

P0IE = 0;         // Disable the P0 interrupt while we are reconfiguring it (maybe not necessary).
__asm nop __endasm; __asm nop __endasm; __asm nop __endasm;

PICTL |= (1<<3);  // PICTL.P0IENL = 1  Enable the Port 0 interrupts for inputs 0-3 (USB_RESUME is #7).
PICTL &= ~(1<<0); // PICTL.P0ICON = 0  Detect rising edges (this is required for waking up).
P0IE = 1;         // IEN1: Enable P0 int POIE is bit 5 (port 0 int enable)
__asm nop __endasm; __asm nop __endasm; __asm nop __endasm;
EA = 1;	      // IEN0: Each int source is individually enabled/disabled

}[/code]

For now, wixel responds normally to all the commands from wixel configuration tool.

Again, Thanks for all the help.

Regards

I’m glad to hear you’re getting things working. By the way, if you want to post source code in the future, it’s easier to read if you put it inside [code][/code] tags.

- Kevin

Hello,

I’m back again with the same problem. The printfs dont show up. I have modified test_adc. The possible conflict I see is with usbComService() which uses Port 0 and port 0 interrupt. The strange thing is even if I comment out ADC, DMA, DSM etc, I still dont get printfs. However, when param_input_mode = -1, I do get printfs even though the path is similar.

If usbComService is using port 0, can I move to other port for example, P1 or P2 and be able to get the printfs?

Here is a summary of what I’m doing.

selecting Port0 (0,1,2) as peripheral input ports since I’m using analog inputs as I am using adxl377. One question I have here is will configuring those ports (0,1,2) as GPIO with pu/pd as done by test_adc can read analog signals?
Configuring rest of the unused ports as output ports as per the datasheet pg. 87.
Initialize, ADC,DMA,DSM(Timer1).
Enabling port0 interrupt and triggering on rising edge.
When I get P0 interrupt, I disable P0 and enable DSM for about 50ms to sample input data.
After 50 ms I disable DSM(Timer1 interrupt) and enable P0 interrupt.

I have attached the source code.

Regards
newcode.c (20.3 KB)

Hello.

Yes, you can still take analog readings on pins of the CC2511F32 that have pull-ups or pull-downs enabled. The test_adc app shows how to do that.

It sounds like you are seeing no output in your terminal program from the Wixel when param_input_mode is a value other than -1. You should first figure out if you are even calling printf. Your code won’t call printf if timer1Count is 0, so you might try adding a call to printf on line 587 that prints the value of timer1Count. Another issue you might have is that you are trying to print the VT100 command for “go to 0,0” multiple times in the same report, which means that later parts of your report could override earlier parts. You should only print that command once at the beginning of each report.

–David

Thanks David! The problem turned out to have to do with the MAX_BUF_SZ and printing the graph. I was using 128 words. Add to that, the graphs which may have flooded the USB interface and cause all kinds of problems including usb interface going down and windows would print that usb is not responding. Commenting out most of the code still caused the same behavior. But bringing down the buffer size to 8 has stabilized things greatly so I can proceed further.

Thanks for point out the 0,0 location thing. Should I change the input ports to P2_1,2,3? I can do that if P0 has conflicts with USB realated code. Since I dont have other debug mechanisms, I have to rely heavily on printfs. In addition to LEDs and printfs, can I use other methods?

Regards

Sorry, here I go again.

When I went back to the data sheet, this is what I found on page 91

When using the ADC in an application, some or all of the P0 pins must be configured as
ADC inputs. The port pins are mapped to the ADC inputs so that P0_7 – P0_0 corresponds
to AIN7 - AIN0. To configure a P0 pin to be used as an ADC input the corresponding bit in
the ADCCFG register must be set to 1. The default values in this register select the Port 0
pins as non-ADC input i.e. digital input/outputs.

The settings in the ADCCFG register override the settings in P0SEL (the register used to
select a pin to be either GPIO or to have a peripheral function).

With this information from the data sheet, it appears that I have to use the P0 ports as peripheral ports. However, page 103 says:

Trigger on rising edge. P0SEL.SELP0_1 and P0DIR.P0_1 must be 0

So it appears that this may not fit my plans of using P0 pins as GPIO and trigger on rising edge and then start ADC conversion because ADCCFG will override P0SEL.

What can be done to trigger on rising edge on port 0 input and still use those ports as ADC ports?

My thoughts are to setup port 0 as GPIO input ports, after a rising edge P0 interrupt, (within the interrupt) change the configuration of P0 ports to peripheral since ADCCFG overrides P0SEL. Go through ADC conversion and revert back the P0 ports to GPIO input waiting for the next P0 interrupt.

Right now, as soon as I enable P0 rising edge trigger, I get stuck somewhere with the LED solid green. I am toggling redled if I get an interrupt but I dont think I am getting an interrupt. If I dont enable P0 rising edge trigger, everything is normal.

Thanks for your help.

I should have said this in my previous post, but the USB code for the Wixel does not use Port 0. Why do you think the USB code conflicts with Port 0? All of the pins on Port 2 are already being used for something else on the Wixel, so I do not recommend using them unless there is a good reason. For example P2_3 is used to detect when power is supplied to VIN.

I have not tried to use a single Wixel pin to generate interrupts and perform ADC conversions. If configuring it as an ADC pin prevents the interrupts from working, you might try leaving the pin configured for interrupts most of the time, and then temporarily configuring it as an ADC pin whenever you need to take a reading.

Alternatively, you might try wiring the analog signal to two different pins, and using one of the pins for interrupts while using the other pin for analog-to-digital conversion.

–David

Thanks David. Since I read this in the data sheet, and I found the code listed below, I thought there was some dependency even though it said bit 7.

P0ICON 0 R/W Port 0, inputs 7 to 0 interrupt configuration. This bit selects the interrupt request condition for all port 0 inputs. For CC2511Fx, this bit must be set to 0 when USB is used, since the internal USB resume interrupt mapped to P0[7] uses rising edge.

if (P0IFG & 0x80)
    {
	usbSuspendMode = 0;
    }

Thanks for confirming that. My thought was to configure pins 0,1,2 as GPIO to trap rising edge. Then from within the interrupt, switch to peripheral and get the reading and switch it back. Hopefully I can do that.

The biggest problem I’m facing now is as soon as I enable either P0 or T1 interrupts, the prints stop working. I did separate the two so that I can get each one working independently. I have followed the examples provided in other APPS but that is not working. I feel that when there is an interrupt, either the ISR in the vector table is invalid or configuring the registers exposes some bug in printf which stops printing. It sounds wierd. If someone would like to share examples of how to go about defining ISRs or providing other pointers will really help.

Regards

Okay, I see now that there is some code in the usbSleep function in the Wixel SDK that modifies P0IE and PICTL, because those registers are needed to allow the Wixel to wake up from suspend mode. If you simply avoid calling usbSleep in your application, you should not have to worry about that.

If you want help debugging your problem with the P0 and T1 interrupts causing printf to stop working, I suggest that you simplify your code as much as possible and post it here. For example, since either interrupt causes the problem, then you can pick whichever interrupt is simpler to use and remove all the code for the other one. You should remove all commented-out code and any code that isn’t strictly necessary for showing the problem. The program should be runnable on an ordinary Wixel with no other hardware. You should say what the expected output is and what the actual output is. If you post this information, I can take a look at it and I might have some advice.

–David

Thanks for taking time to look into the code. I chose to post Timer1 interrupt code as it needs no additional hardware. I am posting the file as an attachment.

This is a modified version of test_adc.c. This is a bare bones version which calculates the number of times the interrupt has occured. This program basically waits for a cool-off period after which it will start DSM for a period of 10msec, which is captureWindow. The interrupt count is incremented with each interrupt and later printed.

Regards
timer1.c (9.28 KB)

Adding another file which is not part of the original test_adc code.
hal.h (4.8 KB)

Hello,

I have eliminated printing to the console and relying on toggling LED to verify if DSM is working. I have attached the code here. It appears to be working fine. In this new file, I test ISR for a limited period of time after which I stop DSM. However, I still need to print the data that I need as further work is based on the values of ADC stored. Would really appreciate if someone can provide a solution to print or with other innovative ways of examining the relevant data.

Regards
timer1.c (9.71 KB)

The code you posted was still not as simple as it should be. The file hal.h was not needed, and there were many unused macro definitions.

I simplified your code down to this:

#include <wixel.h>
#include <usb.h>
#include <usb_com.h>
#include <stdio.h>

#define T1CCTL0_IM   0x40
#define T1CCTL1_IM   0x40
#define T1CCTL2_IM   0x40

#define T1CTL_CH0IF  0x20
#define T1CCTL2_CMP  0x38

#define MAX_BUF_SZ      32
#define DATA_AQU_TIME   10
#define COOLOFF_PERIOD  6000

uint32 DATA volatile captureWindow = 0;

uint8 XDATA report[1024];
uint16 DATA reportLength = 0;
uint16 DATA reportBytesSent = 0;

uint16 DATA volatile timer1Count = 0;

void initDSM(void)
{
    P1SEL = 0x02;
    PERCFG = 0x40;
    P1DIR = 0x02;
    T1CTL = T1CTL & ~0x03;
    T1CNTL = 0x00;
    T1CC0H = 0x25;
    T1CC0L = 0x22;
    T1CTL = T1CTL & ~0x10;
    T1CCTL0 = (T1CCTL0 | 0x04);
    T1CCTL0 = T1CCTL0 & ~T1CCTL0_IM;
    T1CCTL1 = T1CCTL1 & ~T1CCTL1_IM;
    T1CCTL2 = T1CCTL2 & ~T1CCTL2_IM;
    T1CC1L = 0;
    T1CC1H = 0;
    T1CTL = T1CTL | 0x02;
    T1CCTL1 = T1CCTL1 & ~0x07;
}

void enableDSM(void)
{
    EA = 0;
    T1CNTL = 0x00;
    T1CC1L = 0;
    T1CC1H = 0;
    IEN1 = IEN1 & ~0x11111101;
    T1IE = 1;
    OVFIM = 1;
    EA = 1;
    T1CCTL1 = (T1CCTL1 | 0x38);
}

void disableDSM(void)
{
    EA = 0;

    T1CTL &= ~0x03;
    T1CCTL1 &= ~0x07;

    OVFIM = 0;
    T1CCTL1 = (T1CCTL1 & ~T1CCTL1_IM);

    T1CCTL1 = T1CCTL1 & ~0x38;
    IEN1 = IEN1 & ~0x00000010;
    T1IE = 0;
    EA = 1;
}

ISR(T1, 0)
{
    setDigitalOutput(14, 1);
    timer1Count++;
    T1CTL = (T1CTL | 0xF0) & ~0x20;  // Clear CH0IF.
    setDigitalOutput(14, 0);
}

void updateLeds()
{
    usbShowStatusWithGreenLed();
    LED_YELLOW(0);
    LED_RED(getMs() >> 9 & 1);
}

void putchar(char c)
{
    report[reportLength] = c;
    reportLength++;
}

void sendReportIfNeeded()
{
    static uint32 lastReport;
    uint8 bytesToSend;

    // Create reports.
    if (getMs() - lastReport >= 100 && reportLength == 0)
    {
        lastReport = getMs();
        reportBytesSent = 0;
        printf("hi\r\n");
    }

    // Send the report to USB in chunks.
    if (reportLength > 0)
    {
        bytesToSend = usbComTxAvailable();
        if (bytesToSend > reportLength - reportBytesSent)
        {
            // Send the last part of the report.
            usbComTxSend(report + reportBytesSent, reportLength - reportBytesSent);
            reportLength = 0;
        }
        else
        {
            usbComTxSend(report + reportBytesSent, bytesToSend);
            reportBytesSent += bytesToSend;
        }
    }
}

void main()
{
    uint32 triggerTime;

    systemInit();
    usbInit();
    initDSM();

    triggerTime = getMs();

    while(1)
    {
        boardService();
        updateLeds();
        usbComService();
        sendReportIfNeeded();

        if (getMs() - triggerTime > COOLOFF_PERIOD)
        {
            captureWindow = triggerTime = getMs();
            enableDSM();
        }

        if (captureWindow && ((getMs() - captureWindow) > DATA_AQU_TIME))
        {
            disableDSM();
        }
    }
}

By adding the line LED_RED(getMs() >> 9 & 1); in updateLeds and observing the red LED, I found out that something went wrong after the program had been running for a few seconds: either the main loop stopped running or the getMs() function stopped working.

I noticed the following incorrect lines of code in your program:

IEN1 = (IEN1 & ~0x11111101); // Enable T1 int mask
IEN1 = (IEN1 & ~0x00000010); // Disable Timer 1 Interrupt

I think these lines are attempting to set or clear the T1IE bit in the IEN1 register, but there are many problems with them.

To write a binary constant in C, you should use the 0b prefix instead of 0x. To set a bit, you should use the binary OR operator (|) instead of using & and ~. To enable the Timer 1 interrupt, you need to set the bit to 1, not 0. With all that advice taken together, the correct lines would have been:

IEN1 = (IEN1 & 0b11111101); // Disable Timer 1 interrupt
IEN1 = (IEN1 | 0b00000010); // Enable Timer 1 Interrupt

However, IEN1 is a special register: because its address is a multiple of 8, the 8051 architecture allows us to directly read and write from individual bits inside it, such as T1IE. So you can simply write:

T1IE = 0;
T1IE = 1;

You already have lines of code that are writing to T1IE this way, so the problematic lines of code that attempt to modify IEN1 are not needed. Removing those lines makes the problem go away.

The first problematic line has many unintended side effects, such as clearing T4IE. Clearing T4IE would prevent the Wixel’s timing functions like getMs from working, and that could be what caused the issue.

–David

Thanks David. Really appreciate your help. Obviously changing b to x was a typo and I did not catch it. As far as unused macros and cleaning up are concerned, will do that in the second phase. Need to stich together everything else together and make it work.

Thanks again