/* ================================================================== >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< ------------------------------------------------------------------ Copyright (c) 2019-2020 by Lattice Semiconductor Corporation ALL RIGHTS RESERVED ------------------------------------------------------------------ IMPORTANT: THIS FILE IS USED BY OR GENERATED BY the LATTICE PROPELâ„¢ DEVELOPMENT SUITE, WHICH INCLUDES PROPEL BUILDER AND PROPEL SDK. Lattice grants permission to use this code pursuant to the terms of the Lattice Propel License Agreement. DISCLAIMER: LATTICE MAKES NO WARRANTIES ON THIS FILE OR ITS CONTENTS, WHETHER EXPRESSED, IMPLIED, STATUTORY, OR IN ANY PROVISION OF THE LATTICE PROPEL LICENSE AGREEMENT OR COMMUNICATION WITH LICENSEE, AND LATTICE SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. LATTICE DOES NOT WARRANT THAT THE FUNCTIONS CONTAINED HEREIN WILL MEET LICENSEE 'S REQUIREMENTS, OR THAT LICENSEE' S OPERATION OF ANY DEVICE, SOFTWARE OR SYSTEM USING THIS FILE OR ITS CONTENTS WILL BE UNINTERRUPTED OR ERROR FREE, OR THAT DEFECTS HEREIN WILL BE CORRECTED. LICENSEE ASSUMES RESPONSIBILITY FOR SELECTION OF MATERIALS TO ACHIEVE ITS INTENDED RESULTS, AND FOR THE PROPER INSTALLATION, USE, AND RESULTS OBTAINED THEREFROM. LICENSEE ASSUMES THE ENTIRE RISK OF THE FILE AND ITS CONTENTS PROVING DEFECTIVE OR FAILING TO PERFORM PROPERLY AND IN SUCH EVENT, LICENSEE SHALL ASSUME THE ENTIRE COST AND RISK OF ANY REPAIR, SERVICE, CORRECTION, OR ANY OTHER LIABILITIES OR DAMAGES CAUSED BY OR ASSOCIATED WITH THE SOFTWARE.IN NO EVENT SHALL LATTICE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS FILE OR ITS CONTENTS, EVEN IF LATTICE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. LATTICE 'S SOLE LIABILITY, AND LICENSEE' S SOLE REMEDY, IS SET FORTH ABOVE. LATTICE DOES NOT WARRANT OR REPRESENT THAT THIS FILE, ITS CONTENTS OR USE THEREOF DOES NOT INFRINGE ON THIRD PARTIES' INTELLECTUAL PROPERTY RIGHTS, INCLUDING ANY PATENT. IT IS THE USER' S RESPONSIBILITY TO VERIFY THE USER SOFTWARE DESIGN FOR CONSISTENCY AND FUNCTIONALITY THROUGH THE USE OF FORMAL SOFTWARE VALIDATION METHODS. ------------------------------------------------------------------ ================================================================== */ #include "uab.h" #include unsigned char uab_init(struct uab_instance *this_uab, unsigned int base_addr) { this_uab->base = base_addr; return 0; } static unsigned char uab_wait_ready(struct uab_instance *this_uab) { unsigned char status; // unsigned char read_busy[4] = { 0xF0, 0x00, 0x00, 0x00 }; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); do { status = device->uab_stat; } while (!(status & UAB_STAT_RDY)); //check the ready bit return 0; } static unsigned char uab_ufm_addr_set(struct uab_instance *this_uab, unsigned int pageno, unsigned int ufm) // 14 bits UFM Page address { unsigned int flash_addr = 0; unsigned int i; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); if (ufm == UFM3) { if (pageno >= UFM3_SIZE) return UAB_ERR; } else if (ufm == UFM2) { if (pageno >= UFM2_SIZE) return UAB_ERR; } else if (ufm == UFM1) { if (pageno >= UFM1_SIZE) return UAB_ERR; } else if (ufm == UFM0) { if (pageno >= UFM0_SIZE) return UAB_ERR; } else if (ufm == CFG1) { if (pageno >= CFG1_SIZE) return UAB_ERR; } else if (ufm == CFG0) { if (pageno >= CFG0_SIZE) return UAB_ERR; } else { return UAB_ERR; } device->addr_reg = (ufm << 14) + pageno; return 0; } //returns sum of all bytes, for checksum calculation unsigned char uab_ufm_page_read(struct uab_instance *this_uab, unsigned int pageno, unsigned int ufm, unsigned char *buff, unsigned char *checksum) { unsigned char sum = 0; unsigned char data[16]; int i; if ((NULL == this_uab)||(buff == NULL)) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); if( uab_wait_ready(this_uab)) // make sure uab is ready for operation { return UAB_ERR; } // set the UFM and page number if(uab_ufm_addr_set(this_uab, pageno, ufm) != 0) { return UAB_ERR; } // set the operation mode to write device->oper_mode = UAB_OP_READ; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } #if 1 // read the page data *(unsigned int *)data = device->rd_data3; *(unsigned int *)(data + 4) = device->rd_data2; *(unsigned int *)(data + 8) = device->rd_data1; *(unsigned int *)(data + 12) = device->rd_data0; for(i = 0; i < 4; i++) { buff[i] = data[3-i]; buff[i+4] = data[7-i]; buff[i+8] = data[11-i]; buff[i+12] = data[15-i]; } for (i = 0; i < 16; i++) sum = sum + buff[i]; #else buff[0] = device->rd_data0; buff[1] = device->rd_data1; buff[2] = device->rd_data2; buff[3] = device->rd_data3; #endif *checksum = sum; return UAB_SUCC; } unsigned char uab_ufm_page_write(struct uab_instance *this_uab, unsigned int pageno, unsigned int ufm, unsigned char *data, unsigned char *checksum) { int i; unsigned char buff[16]; unsigned char sum = 0; if ((NULL == this_uab) ||(data == NULL)) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); for (i = 0; i < 16; i++) { sum = sum + data[i]; } if( uab_wait_ready(this_uab)) // make sure uab is ready for operation { return UAB_ERR; } // set the UFM and page number if(uab_ufm_addr_set(this_uab, pageno, ufm) != 0) { return UAB_ERR; } // set the operation mode to write device->oper_mode = UAB_OP_WRITE; for(i = 0; i < 4; i++) { buff[i] = data[3-i]; buff[i+4] = data[7-i]; buff[i+8] = data[11-i]; buff[i+12] = data[15-i]; } // feed the page data device->wr_data3 = *(unsigned int *)buff; device->wr_data2 = *(unsigned int *)(buff + 4); device->wr_data1 = *(unsigned int *)(buff + 8); device->wr_data0 = *(unsigned int *)(buff + 12); // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *checksum = sum; return UAB_SUCC; } unsigned char uab_ufm_erase(struct uab_instance *this_uab, unsigned int ufm) { unsigned int erase_ufm = 0; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); if(ufm == CFG0) { erase_ufm = CFG0_ERASE; } else if(ufm == CFG1) { erase_ufm = CFG1_ERASE; } else if(ufm == UFM0) { erase_ufm = UFM0_ERASE; } else if(ufm == UFM1) { erase_ufm = UFM1_ERASE; } else if(ufm == UFM2) { erase_ufm = UFM2_ERASE; } else if(ufm == UFM3) { erase_ufm = UFM3_ERASE; } else if(ufm == CSEC) { erase_ufm = CSEC_ERASE; } else if(ufm == USEC) { erase_ufm = USEC_ERASE; } else if(ufm == PUBKEY) { erase_ufm = PUBKEY_ERASE; } else if(ufm == AESKEY) { erase_ufm = AESKEY_ERASE; } else if(ufm == FEABITS) { erase_ufm = FEABITS_ERASE; } else { return UAB_ERR; } if( uab_wait_ready(this_uab)) // make sure uab is ready for operation { return UAB_ERR; } // set the UFM device->addr_reg = erase_ufm; // set the operation mode to write device->oper_mode = UAB_OP_ERASE; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } /* This function will write a page, but only update a single bytes. * All other bytes will be written with 0's, therefore not changing their value * byteno is 0-15 */ unsigned char uab_ufm_byte_write(struct uab_instance *this_uab, unsigned int pageno, unsigned char byteno, unsigned int ufm, unsigned char data) { unsigned char buff[16] = { 0x00 }; unsigned char checksum; if (NULL == this_uab) { return UAB_ERR; } buff[byteno] = data; uab_ufm_page_write(this_uab, pageno, ufm, buff, &checksum); return 0; } unsigned char uab_ufm_byte_read(struct uab_instance *this_uab, unsigned int pageno, unsigned char byteno, unsigned int ufm, unsigned char *data) { unsigned char buff[16] = { 0x00 }; unsigned char checksum; if (NULL == this_uab) { return UAB_ERR; } uab_ufm_page_read(this_uab, pageno, ufm, buff, &checksum); *data = buff[byteno]; return 0; } unsigned char uab_refresh(struct uab_instance *this_uab) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); device->force_reboot = 3; //Request XO3D to load from same configuration return UAB_SUCC; } // cfg: 0 - CFG0, 1 - CFG1 // auth: 0 - DONE, 1 - AUTH DONE unsigned char uab_done_set(struct uab_instance *this_uab, uint32_t cfg, uint32_t auth) { volatile uint32_t status; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // ADDR_REG = cfg + (auth ? 0xCC000000 : 0x5E000000); // OPER_MODE = OPER_MODE_WRPBK; device->addr_reg = cfg + (auth ? UAB_WRITE_AUTHDONE_CFG0 : UAB_WRITE_DONE_CFG0); // START_OPER = 1; // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } static uint32_t uab_read_sr(struct uab_instance *this_uab, uint32_t reg) { uint32_t sr; volatile uint32_t status; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = reg ? UAB_READ_SR1 : UAB_READ_SR0; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } sr = device->rd_data3; return sr; } /* unsigned char uab_boot_addr_get(struct uab_instance *this_uab, unsigned int *boot_src) { uint32_t addr, sr0, sr1; uint32_t boot_sel, boot_fail, latter; if (NULL == this_uab) { return UAB_ERR; } sr0 = uab_read_sr(this_uab, UAB_SR0); sr1 = uab_read_sr(this_uab, UAB_SR1); latter = (sr1 >> 16) & 0x1; boot_sel = (sr1 >> 17) & 0x7; boot_fail = (sr0 >> 21) & 0x1; // primary boot fail switch (boot_sel) { case 0: addr = 0; break; case 1: addr = 1; break; case 5: addr = latter ? 1 : 0; break; case 7: addr = latter ? 0 : 1; break; case 4: addr = 1; break; case 3: default: addr = 0; } if (boot_fail) { addr = !addr; } *boot_src = addr; return UAB_SUCC; } */ unsigned char uab_pubkey_read(struct uab_instance *this_uab, unsigned char pubkey[64]) { unsigned int op_code[4] = {UAB_READ_PUBKEY0, UAB_READ_PUBKEY1, UAB_READ_PUBKEY2, UAB_READ_PUBKEY3}; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); for(int i = 0; i < 4; i++) { // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = op_code[i]; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } pubkey[16*i] = device->rd_data0; pubkey[16*i+1] = device->rd_data0 >> 8; pubkey[16*i+2] = device->rd_data0 >> 16; pubkey[16*i+3] = device->rd_data0 >> 24; pubkey[16*i+4] = device->rd_data1; pubkey[16*i+5] = device->rd_data1 >> 8; pubkey[16*i+6] = device->rd_data1 >> 16; pubkey[16*i+7] = device->rd_data1 >> 24; pubkey[16*i+8] = device->rd_data2; pubkey[16*i+9] = device->rd_data2 >> 8; pubkey[16*i+10] = device->rd_data2 >> 16; pubkey[16*i+11] = device->rd_data2 >> 24; pubkey[16*i+12] = device->rd_data3; pubkey[16*i+13] = device->rd_data3 >> 8; pubkey[16*i+14] = device->rd_data3 >> 16; pubkey[16*i+15] = device->rd_data3 >> 24; } return UAB_SUCC; } unsigned char uab_pubkey_read_int(struct uab_instance *this_uab, unsigned int pubkey[16]) { unsigned int op_code[4] = {UAB_READ_PUBKEY0, UAB_READ_PUBKEY1, UAB_READ_PUBKEY2, UAB_READ_PUBKEY3}; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); for(int i = 0; i < 4; i++) { // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = op_code[i]; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } pubkey[4*i] = device->rd_data0; pubkey[4*i+1] = device->rd_data1; pubkey[4*i+2] = device->rd_data2; pubkey[4*i+3] = device->rd_data3; } return UAB_SUCC; } unsigned char uab_pubkey_write(struct uab_instance *this_uab, unsigned char pubkey[64]) { unsigned int op_code[4] = {UAB_WRITE_PUBKEY0, UAB_WRITE_PUBKEY1, UAB_WRITE_PUBKEY2, UAB_WRITE_PUBKEY3}; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); for(int i = 0; i < 4; i++) { // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = op_code[i]; device->wr_data0 = (pubkey[3 + i*16] <<24) + (pubkey[2 + i*16] <<16) + (pubkey[1 + i*16] <<8) + pubkey[0 + i*16]; device->wr_data1 = (pubkey[7 + i*16] <<24) + (pubkey[6 + i*16] <<16) + (pubkey[5 + i*16] <<8) + pubkey[4 + i*16]; device->wr_data2 = (pubkey[11 + i*16] <<24) + (pubkey[10 + i*16] <<16) + (pubkey[9 + i*16] <<8) + pubkey[8 + i*16]; device->wr_data3 = (pubkey[15 + i*16] <<24) + (pubkey[14 + i*16] <<16) + (pubkey[13 + i*16] <<8) + pubkey[12 + i*16]; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } } return UAB_SUCC; } unsigned char uab_usec_read(struct uab_instance *this_uab, unsigned short *usec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_USEC; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *usec = device->rd_data3>>16; return UAB_SUCC; } unsigned char uab_usec_write(struct uab_instance *this_uab, unsigned short usec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = UAB_WRITE_USEC; device->wr_data3 = usec << 16; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_usec_shadow_write(struct uab_instance *this_uab, unsigned short usec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSHADOW; device->addr_reg = UAB_WRITE_USEC; device->wr_data3 = usec << 16; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_csec_read(struct uab_instance *this_uab, unsigned int *csec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_CSEC; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *csec = device->rd_data3; return UAB_SUCC; } unsigned char uab_csec_write(struct uab_instance *this_uab, unsigned int csec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = UAB_WRITE_CSEC; device->wr_data3 = csec; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_csec_shadow_write(struct uab_instance *this_uab, unsigned int csec) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSHADOW; device->addr_reg = UAB_WRITE_CSEC; device->wr_data3 = csec; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_feabit_read(struct uab_instance *this_uab, unsigned int *feabit) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_FEA; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *feabit = device->rd_data3; return UAB_SUCC; } unsigned char uab_feabit_write(struct uab_instance *this_uab, unsigned int feabit) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = UAB_WRITE_FEA; device->wr_data3 = feabit; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_feabit_shadow_write(struct uab_instance *this_uab, unsigned int feabit) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSHADOW; device->addr_reg = UAB_WRITE_FEA; device->wr_data3 = feabit; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } // enable: 0 - ECDSA, 1 - HMAC_SHA unsigned char uab_auth_enable_write(struct uab_instance *this_uab, uint32_t enable) { volatile uint32_t status; if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); device->addr_reg = enable ? UAB_WRITE_AUTHDONE_ENABLE_HMAC_SHA : UAB_WRITE_AUTHDONE_ENABLE_ECDSA; device->oper_mode = UAB_OP_WRSPR; device->start_oper = UAB_OP_START; if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_usercode_read(struct uab_instance *this_uab, unsigned char usercode[4]) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_USERCODE; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } usercode[0] = device->rd_data3; usercode[1] = device->rd_data3 >> 8; usercode[2] = device->rd_data3 >> 16; usercode[3] = device->rd_data3 >> 24; return UAB_SUCC; } unsigned char uab_udss_write(struct uab_instance *this_uab, unsigned int ufm, unsigned char udss_val) { unsigned char udss = 0; if (NULL == this_uab || (ufm & (UFM0 | UFM1) == 0)) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); udss = udss_val & (UDSS_PROG | UDSS_READ); if(udss != 0) { device->oper_mode = UAB_OP_WRSPR; // set the correct operation mode according to udss value device->addr_reg = UAB_WRITE_UDSS | udss; // set the UFM sector address to wr_data3 device->wr_data3 = ufm<<14; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } else { return UAB_ERR; } } unsigned char uab_cr0_read(struct uab_instance *this_uab, unsigned int *cr0) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_CR0; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *cr0 = device->rd_data3; return UAB_SUCC; } unsigned char uab_cr0_write(struct uab_instance *this_uab, unsigned int cr0) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = UAB_WRITE_CR0; device->wr_data3 = cr0; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_cr0_shadow_write(struct uab_instance *this_uab, unsigned int cr0) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSHADOW; device->addr_reg = UAB_WRITE_CR0; device->wr_data3 = cr0; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_cr1_read(struct uab_instance *this_uab, unsigned int *cr1) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_RDSPR; device->addr_reg = UAB_READ_CR1; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } *cr1 = device->rd_data3; return UAB_SUCC; } unsigned char uab_cr1_write(struct uab_instance *this_uab, unsigned int cr1) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSPR; device->addr_reg = UAB_WRITE_CR1; device->wr_data3 = cr1; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; } unsigned char uab_cr1_shadow_write(struct uab_instance *this_uab, unsigned int cr1) { if (NULL == this_uab) { return UAB_ERR; } volatile struct uab_dev *device = (volatile struct uab_dev *) (this_uab->base); // set the operation mode to write device->oper_mode = UAB_OP_WRSHADOW; device->addr_reg = UAB_WRITE_CR1; device->wr_data3 = cr1; // start operation device->start_oper = UAB_OP_START; // wait operation done if(uab_wait_ready(this_uab)) { return UAB_ERR; } return UAB_SUCC; }