Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Wixelcmd read provides address too high message


#21

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)


#22

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


#23

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)


#24

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


#25

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


xdata_sfr_address