Lime Microcontroller Calibration

#1

Hi there @Zack,
I have been developing on a custom board using Lime micro . I have written the code form MCU Calibration and it seems to be working on one of the boards .
On the other boards I am able to read the version and id of the chip so the SPI communciation is established but the MCU Calibration fails .
My program says the program buffer of the MCU is not empty . So the programming of the MCU with the binary fails .

What could be the cause of this issue ?

#2

Hi @Zack . Waiting for your reply .

#3

Hi @kishores,

Have you reused MCU calibration source code from LimeSuite? Could you share your code?

#4
#include <LMS7002M/LMS7002M.h>
#include <LMS7002M/LMS7002M_logger.h>
#include "spidev_interface.h"
#include <wiringPi.h>
#include <unistd.h>
#include <stdlib.h>
#include <LMS7002M_filter_cal.h>
#include "mcu_dc_iq_calibration.h"

#define REF_FREQ (50e6)
#define PROGRAM_BUFF_MASK 1<<0
#define PROGRAM_COMP_MASK 1<<6
#define SPI_CONTROL_MCU 1<<0;
#define IMAGE_SIZE 16384
//set the time interval of delay in seconds
int LMS_GPIO_LOW = 2;
int LMS_GPIO_HIGH = 2;
int LMS_CONFIGURABLE = 1000;
int DELAY = 30000;
//CALIBRATION defines
enum CALIB {
    TX_CHAIN = 1,
    RX_CHAIN = 2,
    BW_UPDATE = 3,
    CLK_UPDATE = 4,
    RX_FILTER = 5,
    TX_FILTER = 6,
    MCU_IMAGE_ID = 255
} calib_proc;

LMS7002M_t *lms;//Make LMS instance glLMS7002M_t *lms;//Make LMS instance global to prevent stack overflow while passing to functions

void run_calib_procedure(int proc_id) {
    int value = LMS7002M_spi_read(lms, 0x0006);
    value |= SPI_CONTROL_MCU;
    LMS7002M_spi_write(lms, 0x0006, value); //switch SPI control to MCU
    LMS7002M_spi_write(lms, 0x0000, 0x01); //run TX chain calibration
    value = LMS7002M_spi_read(lms, 0x0002);
    value &= ~(1 << 3);
    LMS7002M_spi_write(lms, 0x0002, value); //reset the 3rd bit of 0x0002
    value |= (1 << 3);
    LMS7002M_spi_write(lms, 0x0002, value); //set the 3rd bit of 0x0002
    value &= ~(1 << 3);
    LMS7002M_spi_write(lms, 0x0002, value); //reset the 3rd bit of 0x0002
    uint8_t status = LMS7002M_spi_read(lms, 0x0001) & 0xff;
    //TODO:Add timeout here
    while (status == 0xff) {
        status = LMS7002M_spi_read(lms, 0x0001) & 0xff;
    };//wait till calibration is in progress
    if (status == 0x00)
        printf("Calibration complete successful\n");
    else
        printf("Calibration failed.\n");
    value = LMS7002M_spi_read(lms, 0x0006);
    value &= ~SPI_CONTROL_MCU;
    LMS7002M_spi_write(lms, 0x0006, value); //give back control to the BB processor
}

void update_BW_or_clock(uint8_t kHz_LSB, uint8_t kHz_MSB, uint8_t MHz) {
    LMS7002M_spi_write(lms, 0x0000, kHz_LSB);
    int value = LMS7002M_spi_read(lms, 0x0002);
    value |= (1 << 2); //set the second bit
    LMS7002M_spi_write(lms, 0x0002, value);
    value = LMS7002M_spi_read(lms, 0x0002);
    value &= ~(1 << 2);
    LMS7002M_spi_write(lms, 0x0002, value); //reset the second bit
    LMS7002M_spi_write(lms, 0x0000, kHz_MSB);
    value = LMS7002M_spi_read(lms, 0x0002);
    value |= (1 << 2); //set the second bit
    LMS7002M_spi_write(lms, 0x0002, value);
    value = LMS7002M_spi_read(lms, 0x0002);
    value &= ~(1 << 2);
    LMS7002M_spi_write(lms, 0x0002, value); //reset the second bit
    LMS7002M_spi_write(lms, 0x0000, MHz);
    value = LMS7002M_spi_read(lms, 0x0002);
    value |= (1 << 2); //set the second bit
    LMS7002M_spi_write(lms, 0x0002, value);
    value = LMS7002M_spi_read(lms, 0x0002);
    value &= ~(1 << 2);
    LMS7002M_spi_write(lms, 0x0002, value); //reset the second bit
}


int main() {
    LMS7_set_log_level(LMS7_DEBUG);
    //initialize wiring pi
    wiringPiSetup();
    pinMode(6, OUTPUT);
    //create an SPI handle
    void *handle = spidev_interface_open("/dev/spidev0.0");
    if (handle == NULL) {
        printf("\nUnable to create the handle . Exiting . ");
        return -1;
    }
    //create an object
    lms = LMS7002M_create(spidev_interface_transact, handle);
    if (lms == NULL) {
        printf("Unable to create the LMS7002M interface . ");
        return -1;
    }

    //  LMS7002M_reset(lms);
    //read from the SPI device
    digitalWrite(6, LOW);
    delay(LMS_GPIO_LOW);
    digitalWrite(6, HIGH);
    //delay(LMS_GPIO_HIGH);
    //delay(LMS_CONFIGURABLE);
    //usleep(DELAY);
    LMS7002M_reset(lms);
    usleep(DELAY);
    LMS7002M_set_spi_mode(lms, 4);
    usleep(DELAY);
    LMS7002M_regs_spi_read(lms, 0x002f);
    usleep(DELAY);
    printf("rev. 0x%x\n", LMS7002M_regs(lms)->reg_0x002f_rev);
    printf("ver. 0x%x\n", LMS7002M_regs(lms)->reg_0x002f_ver);
    LMS7002M_spi_write(lms, 0x0002, 0x0000); //reset the MCU
    usleep(DELAY);
    LMS7002M_spi_write(lms, 0x0002, 0x0002); //select EEPROM/SRAM Mode .Works for mode 0x0001(EEPROM and SRAM)
    int value = LMS7002M_spi_read(lms, 0x0003); //read programming buffer register
    uint8_t *fp = (uint8_t *)calib_bin;
    //TODO:ADD timeout here
    while ( (value & PROGRAM_BUFF_MASK) ==  1 ) { //loop if program buffer is not empty
        value = LMS7002M_spi_read(lms, 0x0003);
        printf("Program buffer not empty\n");
    }
    //printf("Out of while loop");
    printf("================Ready to flash the image======================\n");
    int size = 16384;
    //write the binary into the MCU
    //NOTE:The size of binary is 16384,so total writes in steps of 32 are 16384/32=4096
    uint16_t data = 0;
    for (int i = 0; i < IMAGE_SIZE; i += 4) {
        data = (0x00 << 8) | fp[i];
        //printf("%x\t",data);
        LMS7002M_spi_write(lms, 0x0004, data);
        data = (0x00 << 8) | fp[i + 1];
        //printf("%x\t",data);
        LMS7002M_spi_write(lms, 0x0004, data);
        data = (0x00 << 8) | fp[i + 2];
        //printf("%x\t",data);
        LMS7002M_spi_write(lms, 0x0004, data);
        data = (0x00 << 8) | fp[i + 3];
        //printf("%x\t",data);
        LMS7002M_spi_write(lms, 0x0004, data);
        value = LMS7002M_spi_read(lms, 0x0003);
        //usleep(1);
        //TODO:ADD timeout here
        //printf("%d",i);
        while ( (value & PROGRAM_BUFF_MASK) ==  1 ) { //loop if program buffer is not empty
            value = LMS7002M_spi_read(lms, 0x0003); //read programming buffer register
            //printf("Waiting for the Program buffer\n");
            //usleep(1);
        }
    }
    value = LMS7002M_spi_read(lms, 0x0003);
    usleep(1);
    //TODO:Add timeout here
    while ( (value & PROGRAM_COMP_MASK) == 0 ) {
        value = LMS7002M_spi_read(lms, 0x0003);
        printf("Programming not complete\n");
        usleep(1);
    }
    printf("=================Programming complete===============================\n");
    printf("=================Running image calibration==========================\n");
    //NOTE:clk and bandwidth parameters must be passed before any other calibration
    printf("Updating reference clk rate\n");
    update_BW_or_clock(0xd0, 0x02, 0x1e); //30.72 MHz reference clock
    calib_proc = CLK_UPDATE;
    run_calib_procedure(calib_proc);
    printf("Updating bandwidth\n");
    update_BW_or_clock(0x0, 0x0, 0x05); //5 MHz bandwidth
    calib_proc = BW_UPDATE;
    run_calib_procedure(BW_UPDATE);
    printf("Doing TX chain calibration.\n");
    calib_proc = TX_CHAIN;
    run_calib_procedure(calib_proc);
    printf("Doing RX chain calibration\n");
    calib_proc = RX_CHAIN;
    run_calib_procedure(calib_proc);
    printf("Doing RX filter calibration\n");
    calib_proc = RX_FILTER;
    run_calib_procedure(calib_proc);
    printf("Doing TX filter calibration\n");
    calib_proc = TX_FILTER;
    run_calib_procedure(calib_proc);
    spidev_interface_close(handle);//close the handle
}

@Zack this is my code

#5

Hi @Zack ,
We are eagerly waiting for your reply .

#6

Hi @Zack ,
Sorry for troubling you but we really are in a fix as MCU Calibration is essential to our design .

#7

Sorry for delay, but our team is maxed out at the moment. Will check ASAP.

#8
while ( (value & PROGRAM_BUFF_MASK) ==  1 ) { //loop if program buffer is not empty
        value = LMS7002M_spi_read(lms, 0x0003);
        printf("Program buffer not empty\n");
    }

Your code is wrong, the FIFO buffer is empty when the value is 1, take a look at: