Final Jacaranda Program; updated during Harald's visit; In NVM program, set tm_en_vout_mon =1 before updating the oscillator frequency.
EasyFuse_Prog.cpp
- Committer:
- CactusSemi
- Date:
- 2018-06-21
- Revision:
- 3:3e8c16b6620c
- Child:
- 4:8afc50e5a7bc
File content as of revision 3:3e8c16b6620c:
#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); }