Ashwath M Pavithran
/
csi066_rev0p3_harald_prog
Publishing for sharing with Harald
Diff: EasyFuse_Prog.cpp
- Revision:
- 3:3e8c16b6620c
- Child:
- 4:1c48c9fa44fc
diff -r c7229eac380b -r 3e8c16b6620c EasyFuse_Prog.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/EasyFuse_Prog.cpp Thu Jun 21 22:11:25 2018 +0000 @@ -0,0 +1,461 @@ +#include "mbed.h" + +extern Serial pc; +extern int frequ; //unit kHz +extern char dev_addr; //fixed + +char get_half_byte(int *); //defined in I2C_read.cpp + + +char get_byte(int *flag) { + char cur_char; + char temp; + int flag1 = 0; + cur_char = get_half_byte(&flag1); + if (flag1 == 1) { + cur_char = cur_char << 4; + temp = get_half_byte(&flag1); + cur_char = (cur_char | temp); + } + *flag = flag1; + return cur_char; +} + +void print_nvm_reg(uint8_t *max_Vout, uint8_t *max_Vout_trim, uint8_t *high_time, uint8_t *low_time, uint8_t *adc_samp_rate, +uint8_t *adc_range, uint8_t *adc_time_out, uint8_t *comp_offset, uint8_t *range_trim, uint8_t *PMOS_off, uint8_t *Driver2, uint8_t *Driver3, +uint8_t *DMOS, uint8_t *CCM_threshold, uint8_t *DMOS_ctrl_trim, uint8_t *adc_op_mode) { + + pc.printf("\033[%dm ", 35);//change text color to red + pc.printf("\n\n\n\r\t Register contents :\n\r\t "); + for ( int i = 0; i<26; i++) pc.printf("\304"); + pc.printf("\n\n\r\t 1. max_Vout = 0x%2.2X",*max_Vout); + pc.printf("\n\n\r\t 2. max_Vout_trim = 0x%2.2X",*max_Vout_trim); + pc.printf("\n\n\r\t 3. high_time = 0x%2.2X",*high_time); + pc.printf("\n\n\r\t 4. low_time = 0x%2.2X",*low_time); + pc.printf("\n\n\r\t 5. adc_samp_rate = 0x%2.2X",*adc_samp_rate); + pc.printf("\n\n\r\t 6. adc_range = 0x%2.2X",*adc_range); + pc.printf("\n\n\r\t 7. adc_time_out = 0x%2.2X",*adc_time_out); + pc.printf("\n\n\r\t 8. comp_offset = 0x%2.2X",*comp_offset); + pc.printf("\n\n\r\t 9. range_trim = 0x%2.2X",*range_trim); + pc.printf("\n\n\r\t 10. PMOS_off = 0x%2.2X",*PMOS_off); + pc.printf("\n\n\r\t 11. Driver2 = 0x%2.2X",*Driver2); + pc.printf("\n\n\r\t 12. Driver3 = 0x%2.2X",*Driver3); + pc.printf("\n\n\r\t 13. DMOS = 0x%2.2X",*DMOS); + pc.printf("\n\n\r\t 14. CCM_threshold = 0x%2.2X",*CCM_threshold); + pc.printf("\n\n\r\t 15. DMOS_ctrl_trim = 0x%2.2X",*DMOS_ctrl_trim); + pc.printf("\n\n\r\t 16. adc_op_mode = 0x%2.2X",*adc_op_mode); + pc.printf("\n\n\r\t "); + for ( int i = 0; i<26; i++) pc.printf("\315"); + pc.printf("\033[%dm", 32);//change text color to green + pc.printf("\n\r"); +} + +void edit_nvm_reg(uint8_t *max_Vout, uint8_t *max_Vout_trim, uint8_t *high_time, uint8_t *low_time, uint8_t *adc_samp_rate, +uint8_t *adc_range, uint8_t *adc_time_out, uint8_t *comp_offset, uint8_t *range_trim, uint8_t *PMOS_off, uint8_t *Driver2, uint8_t *Driver3, +uint8_t *DMOS, uint8_t *CCM_threshold, uint8_t *DMOS_ctrl_trim, uint8_t *adc_op_mode) { + + char temp; + int flag1; + char count; + char reg_data; + + char reg_name[16][15] = {"max_Vout", "max_Vout_trim", "high_time", "low_time", "adc_samp_rate", + "adc_range", "adc_time_out", "comp_offset", "range_trim", "PMOS_off", "Driver2", "Driver3", + "DMOS", "CCM_threshold", "DMOS_ctrl_trim", "adc_op_mode" }; + + uint8_t *reg_addr[16] = { max_Vout, max_Vout_trim, high_time, low_time, adc_samp_rate, + adc_range, adc_time_out, comp_offset, range_trim, PMOS_off, Driver2, Driver3, + DMOS, CCM_threshold, DMOS_ctrl_trim, adc_op_mode}; + + pc.printf("\n\n\n \r\tDo you want to edit the registers? (y/n) : "); + temp = 0; + while ( temp!='y' && temp!='n') { + temp = pc.getc(); + } + if (temp == 'n') { + pc.printf("\n\n \r\tContinue with above contents"); + return; + } + temp = 'y'; + while (temp =='y') { + //get selection + flag1 = 0; + while (!flag1) { + pc.printf("\n\n\n\r\tEnter (1 - 16) to select the register to edit and hit 'enter' key: "); + temp = '0'; + count = 0; + while (temp != '\r') { //look for enter key + count = (count * 10) + (temp - '0'); // converting to number + temp = pc.getc(); + if ((temp < '0' || temp > '9') && temp !='\r') { + pc.printf(" \n\r\t\033[%dm Invalid Chracter!! No worries, let us try again \033[%dm",41,40); + break; + } + } + if (count >= 1 && count <= 16 && temp == '\r') flag1 = 1; + else if (temp == '\r') pc.printf(" \n\r\t\033[%dm Invalid Chracter!! No worries, let us try again \033[%dm",41,40); + } + count = count - 1; //array starts from 0 + //Read New Register Data + flag1 = 0; + while (!flag1) { + pc.printf("\n\n \r\tEnter new value in hex (00 to ff) for \033[%dm %s \033[%dm register : ",35,reg_name[count],32); + reg_data = get_half_byte(&flag1); + if (flag1 == 1) { + reg_data = reg_data << 4; + temp = get_half_byte(&flag1); + reg_data = (reg_data | temp); + } + if (flag1==0) pc.printf(" \033[%dm Invalid Chracter!! No worries, let us try again \033[%dm",41,40); + } + *(reg_addr[count]) = reg_data; + + print_nvm_reg( max_Vout, max_Vout_trim, high_time, low_time, adc_samp_rate, + adc_range, adc_time_out, comp_offset, range_trim, PMOS_off, Driver2, Driver3, + DMOS, CCM_threshold, DMOS_ctrl_trim, adc_op_mode); + + pc.printf("\n\n \r\tDo you want to make more changes? (y/n) : "); + temp = pc.getc(); + } //end of edit while loop +} + +void i2c_write_fn(I2C *i2c_obj, char ptr, char write_data) { + int flag1; + wait_us(10); + (*i2c_obj).start(); + flag1 = (*i2c_obj).write(dev_addr); + if (flag1 != 1) pc.printf("\n\n\r\tNo Ack for dev addr :("); + flag1 = (*i2c_obj).write(ptr); + if (flag1 != 1) pc.printf("\n\n\r\tNo Ack reg pointer :("); + flag1 = (*i2c_obj).write(write_data); + if (flag1 != 1) pc.printf("\n\n\r\tNo Ack data :("); + wait_us(5); + (*i2c_obj).stop(); +} + +char i2c_read_fn(I2C *i2c_obj, char ptr) { + int flag1; + char read_data; + wait_us(10); + (*i2c_obj).start(); + flag1 = (*i2c_obj).write(dev_addr); + if (flag1 != 1) pc.printf("\n\n\n\r\tNo Ack for dev addr :("); + flag1 = (*i2c_obj).write(ptr); + if (flag1 != 1) pc.printf("\n\n\r\tNo Ack reg pointer :("); + (*i2c_obj).stop(); + wait_us(10); + (*i2c_obj).start(); + flag1 = (*i2c_obj).write(dev_addr | 0x01); //lsb 1 for read + if (flag1 != 1) pc.printf("\n\n\r\tNo Ack for dev addr :("); + read_data = (*i2c_obj).read(0); //0- donot send ack after read is done + wait_us(5); + (*i2c_obj).stop(); + wait_us(120); + return read_data; +} + +uint64_t EasyFuse_read(I2C *i2c_obj) { + char reg_ptr = 0x00; + char reg_data[10]; + char data; + uint8_t NVM_READ = 0x70 ; + uint8_t NVM_CTLR_ADR = 0x0a ; //Register address for NVM CTRL + uint64_t NVM_data = 0x0000000000000000; + + //Variables to store read data + uint8_t max_Vout; + uint8_t max_Vout_trim; + uint8_t high_time; + uint8_t low_time; + uint8_t adc_samp_rate; + uint8_t adc_range; + uint8_t adc_time_out; + uint8_t comp_offset; + uint8_t range_trim; + uint8_t PMOS_off; + uint8_t Driver2; + uint8_t Driver3; + uint8_t DMOS; + uint8_t CCM_threshold; + uint8_t DMOS_ctrl_trim; + uint8_t adc_op_mode; + + int i; + char temp; + + pc.printf("\n\n\n\r\t"); + for ( i = 0; i<60; i++) pc.printf("\304"); + pc.printf("\n\n\n\r\tPerforming an NVM read and loading the contents to the register"); + pc.printf("\n\n\r\tSwitching to faster clock before reading the NVM"); + i2c_write_fn(i2c_obj,0x02,0x01); //switching to faster clock for NVM read + i2c_write_fn(i2c_obj,0x03,0x01); //switching to faster clock for NVM read + wait_ms(1); + i2c_write_fn(i2c_obj,NVM_CTLR_ADR,NVM_READ); //Perform a complete read; will be sucessful only if NVM is not empty + wait_ms(100); + + //check if tm_nvm_read bit has cleared itself + temp = 0; + while (temp == 0){ + data = i2c_read_fn(i2c_obj,NVM_CTLR_ADR); + data = data & 0x40; + if (data == 0x00) { + pc.printf("\n\n\r\ttm_nvm_read has cleared; so loading Register with NVM complete"); + temp = 1; + } + else wait_ms(100); + } + + pc.printf("\n\n\n\r\tReading register 0x00 to 0x09"); + for( reg_ptr = 0x00; reg_ptr <= 0x09; reg_ptr = reg_ptr+1) { + reg_data[reg_ptr] = i2c_read_fn(i2c_obj,reg_ptr); + } + + //Storing read data into variables + max_Vout = reg_data[0] & 0x0f; + max_Vout_trim = reg_data[1] & 0x1f; + high_time = reg_data[2] & 0x7f; + low_time = reg_data[3] & 0x7f; + adc_samp_rate = reg_data[4]>>4; + adc_range = (reg_data[4]>>2) & 0x03; + adc_time_out = reg_data[4] & 0x03; + comp_offset = reg_data[5] & 0x1f; + range_trim = reg_data[6] & 0x1f; + PMOS_off = reg_data[7] & 0x0f; + Driver2 = reg_data[8] & 0x0f; + Driver3 = (reg_data[8]>>4) & 0x0f; + DMOS = (reg_data[9]>>7) & 0x01; + CCM_threshold = (reg_data[7]>>4) & 0x0f; + DMOS_ctrl_trim = reg_data[9] & 0x1f; + adc_op_mode = (reg_data[5]>>7) & 0x01; + + pc.printf("\n\n\r\tFollowing data was read from the Register"); + + print_nvm_reg(&max_Vout, &max_Vout_trim, &high_time, &low_time, &adc_samp_rate, + &adc_range, &adc_time_out, &comp_offset, &range_trim, &PMOS_off, &Driver2, &Driver3, + &DMOS, &CCM_threshold, &DMOS_ctrl_trim, &adc_op_mode); + + //push data into NVM_data + NVM_data = NVM_data | (max_Vout+1); //max_Vout(register) = max_Vout(NVM) - 1 + NVM_data = (NVM_data<<5) | max_Vout_trim; + NVM_data = (NVM_data<<7) | high_time; // <<x : x corresponds to no. of bits + NVM_data = (NVM_data<<7) | low_time; + NVM_data = (NVM_data<<4) | adc_samp_rate; + NVM_data = (NVM_data<<2) | adc_range; + NVM_data = (NVM_data<<2) | adc_time_out; + NVM_data = (NVM_data<<5) | comp_offset; + NVM_data = (NVM_data<<5) | range_trim; + NVM_data = (NVM_data<<4) | PMOS_off; + NVM_data = (NVM_data<<4) | Driver2; + NVM_data = (NVM_data<<4) | Driver3; + NVM_data = (NVM_data<<1) | DMOS; + NVM_data = (NVM_data<<4) | CCM_threshold; + NVM_data = (NVM_data<<5) | DMOS_ctrl_trim; + NVM_data = (NVM_data<<1) | adc_op_mode; + + pc.printf("\n\n\n\r\tReconstructed data read from NVM = 0x%016llX",NVM_data); + return NVM_data; +} + + +void EasyFuse_prog() { + uint64_t NVM_data = 0x0000000000000000; + uint64_t NVM_read_data; + + // Register variables + uint8_t max_Vout = 0x07; + uint8_t max_Vout_trim = 0x00; + uint8_t high_time = 0x12; + uint8_t low_time = 0x29; + uint8_t adc_samp_rate = 0x06; + uint8_t adc_range = 0x01; + uint8_t adc_time_out = 0x02; + uint8_t comp_offset = 0x00; + uint8_t range_trim = 0x0f; + uint8_t PMOS_off = 0x08; + uint8_t Driver2 = 0x08; + uint8_t Driver3 = 0x08; + uint8_t DMOS = 0x01; + uint8_t CCM_threshold = 0x0f; + uint8_t DMOS_ctrl_trim = 0x0c; + uint8_t adc_op_mode = 0x01; + + // NVM Register Control Bit locations; PWR_ON set in all the definitions + uint8_t NVM_RESET = 0x31 ; + uint8_t NVM_PWE1 = 0x02 ; + uint8_t NVM_CLK1 = 0x34 ; + uint8_t NVM_PWR_ON = 0x30 ; + uint8_t NVM_READ = 0x70 ; + + uint8_t NVM_CTLR_ADR = 0x0a ; //Register address for NVM CTRL + + char reg_data = 0xaa; + char temp; + char high_time_prog = 0x04; + char low_time_prog = 0x04; + int flag1 = 0; + int i = 0; + + int delay1 = 20; + int delay2 = 2 * delay1; + + I2C i2c(p9,p10); + i2c.frequency((frequ/2)*1000); + LPC_PINCON->PINMODE_OD0 = (LPC_PINCON->PINMODE_OD0 | 0x0003); // To make p9 & P10 open_drain + i2c.stop(); //add a stop after hot-read + + pc.printf("\n\n\r\tFollowing are the default register data that will be programmed: \n\r "); + print_nvm_reg(&max_Vout, &max_Vout_trim, &high_time, &low_time, &adc_samp_rate, + &adc_range, &adc_time_out, &comp_offset, &range_trim, &PMOS_off, &Driver2, &Driver3, + &DMOS, &CCM_threshold, &DMOS_ctrl_trim, &adc_op_mode); + + edit_nvm_reg(&max_Vout, &max_Vout_trim, &high_time, &low_time, &adc_samp_rate, + &adc_range, &adc_time_out, &comp_offset, &range_trim, &PMOS_off, &Driver2, &Driver3, + &DMOS, &CCM_threshold, &DMOS_ctrl_trim, &adc_op_mode); + + //push data into NVM_data + NVM_data = NVM_data | (max_Vout+1); //max_Vout(register) = max_Vout(NVM) - 1 + NVM_data = (NVM_data<<5) | max_Vout_trim; + NVM_data = (NVM_data<<7) | high_time; // <<x : x corresponds to no. of bits + NVM_data = (NVM_data<<7) | low_time; + NVM_data = (NVM_data<<4) | adc_samp_rate; + NVM_data = (NVM_data<<2) | adc_range; + NVM_data = (NVM_data<<2) | adc_time_out; + NVM_data = (NVM_data<<5) | comp_offset; + NVM_data = (NVM_data<<5) | range_trim; + NVM_data = (NVM_data<<4) | PMOS_off; + NVM_data = (NVM_data<<4) | Driver2; + NVM_data = (NVM_data<<4) | Driver3; + NVM_data = (NVM_data<<1) | DMOS; + NVM_data = (NVM_data<<4) | CCM_threshold; + NVM_data = (NVM_data<<5) | DMOS_ctrl_trim; + NVM_data = (NVM_data<<1) | adc_op_mode; + pc.printf("\n\n\n\r\tData to be written into NVM = 0x%016llX",NVM_data); + pc.printf("\n\n\r\tPlease note that max_Vout has been incremented. max_Vout(NVM) = max_Vout(register) + 1"); + pc.printf("\n\n\r\t"); + for ( i = 0; i<80; i++) pc.printf("\304"); + pc.printf("\n\n\r\tContinue EasyFuse Programming? (y/n): "); + temp = 0; + while ( temp!='y' && temp!='n') { + temp = pc.getc(); + } + if (temp == 'n') { + pc.printf("\n\n\r\tAborting... :("); + return; + } + //EasyFuse Empty check + pc.printf("\n\n\r\tPerforming NVM Empty check by trying to load register with NVM contents"); + i2c_write_fn(&i2c,0x02,0x01); //switching to faster clock for NVM read + i2c_write_fn(&i2c,0x03,0x01); //switching to faster clock for NVM read + wait_ms(1); + i2c_write_fn(&i2c,NVM_CTLR_ADR,NVM_READ); //Perform a complete read; will be sucessful only if NVM is not empty + wait_ms(100); + + //check if tm_nvm_read bit has cleared itself + temp = 0; + while (temp == 0){ + reg_data = i2c_read_fn(&i2c,NVM_CTLR_ADR); + reg_data = reg_data & 0x40; + if (reg_data == 0x00) { + pc.printf("\n\n\r\ttm_nvm_read has cleared; so loading Register with NVM complete"); + temp = 1; + } + else wait_ms(100); + } + + reg_data = i2c_read_fn(&i2c,0x02); + reg_data = reg_data<<4; + reg_data = reg_data | i2c_read_fn(&i2c,0x03); + if (reg_data == 0xff) pc.printf(" |\033[%dm Register read might not be sucessfull \033[%dm ",45,40); + if (reg_data == 0x11) pc.printf("\n\n\r\t\033[%dm EasyFuse empty \033[%dm",44,40); //no change at address 0x02 & 0x03 + else { + pc.printf("\n\n\r\t\033[%dm EasyFuse not empty \033[%dm",45,40); + pc.printf("\n\n\r\t Better to abort the test.. :("); + //return; + } + + //added for debug.. delete later + pc.printf("\n\n\n\r\tWe will next configure the oscillator. Proceed? (y/n): "); + temp = 0; + while ( temp!='y' && temp!='n') { + temp = pc.getc(); + } + if (temp == 'n') { + pc.printf("\n\n\r\tAborting.. :("); + return; + } + pc.printf("\n\n\r\tEnabled 'fc_enable' & driver1. Monitor the oscillator at the output of comparator"); + i2c_write_fn(&i2c,0x0c,0x22); +osc_trim: + i2c_write_fn(&i2c,0x02,high_time_prog); //Recommended clocks period + i2c_write_fn(&i2c,0x03,low_time_prog); // for programming is 10us + wait_ms(1); + + pc.printf("\n\n\n\r\t\033[%dm", 44);//change backround to blue + pc.printf("Please check if Oscillator period is approx 10us (9.4us to 10.4us) \033[%dm\n\n\r\tPress 'y' to continue; Press 'm' to modify clock trim settings : ",40); + + temp = 0; + while ( temp!='y' && temp!='m' && temp!='m' ) { + temp = pc.getc(); + } + if (temp == 'n') { + pc.printf("\n\n\r\tAborting.. :("); + return; + } + if (temp == 'm') { + pc.printf("\n\n\n\n\r\tCurrent high_time trim = 0x%2.2X & low_time trim = 0x%2.2X",high_time_prog,low_time_prog); + flag1 = 0; + while (!flag1) { + pc.printf("\n\n\r\tEnter new high_time trim in hex (00 to ff): 0x"); + high_time_prog = get_byte(&flag1); + if (flag1 == 0) pc.printf(" \033[%dm Invalid Chracter!! No worries, let us try again \033[%dm",41,40); + } + flag1 = 0; + while (!flag1) { + pc.printf("\n\n\r\tEnter new low_time trim in hex (00 to ff) : 0x"); + low_time_prog = get_byte(&flag1); + if (flag1 == 0) pc.printf(" \033[%dm Invalid Chracter!! No worries, let us try again \033[%dm",41,40); + } + pc.printf("\n\n\r\tProgramming new high_time trim = 0x%2.2X & new low_time trim = 0x%2.2X",high_time_prog,low_time_prog); + goto osc_trim; + } + + pc.printf("\n\n\r\tDisabled 'fc_enable' & driver1."); + i2c_write_fn(&i2c,0x0c,0x00); + wait_ms(delay2); + pc.printf("\n\n\n\r\tAll set to program the EasyFuse, time to blow up some ploy fuses! ..**BOOOM**\n\n\r"); + i2c_write_fn(&i2c,NVM_CTLR_ADR,NVM_PWR_ON); //turn ON supply to EasyFuse + wait_ms(100); + i2c_write_fn(&i2c,NVM_CTLR_ADR,NVM_RESET); //turn ON supply to EasyFuse & RESETN = 1 + wait_ms(1); + i2c_write_fn(&i2c,NVM_CTLR_ADR,NVM_PWR_ON); //RESETN = 0, Prog mode enabled: CKL1 = 0 during RESETN = 0, + temp = 0; + pc.printf("\n\n\n\r\tConnect PROG to 5V and press 'c' to continue"); + while ( temp!='c') { + temp = pc.getc(); + } + wait_us(delay2); + i2c_write_fn(&i2c,NVM_CTLR_ADR,NVM_RESET); //RESETN = 1, + wait_us(delay2); + for ( i = 0; i < 64; i = i+1) { + temp = NVM_RESET + (((NVM_data>>i) & 0x01)?(NVM_PWE1):0); //NVM_PWE1 if NVM_data[i]=1 & CLK1 de-asserted + i2c_write_fn(&i2c,NVM_CTLR_ADR,temp); + wait_us(delay2); + temp = NVM_RESET; + i2c_write_fn(&i2c,NVM_CTLR_ADR,temp); //de-assert NVM_PWE1 + wait_us(delay2); + temp = NVM_RESET + NVM_CLK1; + i2c_write_fn(&i2c,NVM_CTLR_ADR,temp); //assert CLK1 + wait_us(delay2); + } + pc.printf("\n\n\n\r\t\a\033[%dm", 44);//change backround to blue + pc.printf("Finished programming. Let us confirm if the NVM has been programmed correctly by reading the NVM. Proceed (y/n): "); + pc.printf("\033[%dm", 40);//change backround to black + + temp = 0; + while ( temp!='y' ) { + temp = pc.getc(); + } + NVM_read_data = EasyFuse_read(&i2c); + if ( NVM_data == NVM_read_data ) pc.printf("\n\n\r\tData written into NVM matches data read from NVM\n\n\n\r\t\033[%dm NVM PROGRAMMING SUCESSFULL. Hoorayyy!\a \033[%dm\n\r",44,40); + else pc.printf("\n\n\r\tuh-oh.. Data written into NVM does not match data read from NVM\n\n\n\r\t\033[%dm NVM PROGRAMMING FAILED!\a \033[%dm\n\r",41,40); +} \ No newline at end of file