//===================================== u8 sx1278_LoRaEntryTx(void) //===================================== { u8 addr,temp; sx1278_Config(); //setting base parameter ANT_EN_H(); ANT_CTRL_TX(); SPIWrite(REG_LR_PADAC,0x87); //Tx for 20dBm SPIWrite(LR_RegHopPeriod,0x00); //RegHopPeriod NO FHSS SPIWrite(REG_LR_DIOMAPPING1,0x41); //DIO0=01, DIO1=00, DIO2=00, DIO3=01 SPIWrite(LR_RegIrqFlags,LoRa_ClearIRQ_Value); SPIWrite(LR_RegIrqFlagsMask,0xF7); //Open TxDone interrupt SPIWrite(LR_RegPayloadLength,21); //RegPayloadLength 21byte addr = SPIRead(LR_RegFifoTxBaseAddr); //RegFiFoTxBaseAddr SPIWrite(LR_RegFifoAddrPtr,addr); //RegFifoAddrPtr SysTime = 0; while(1) { temp=SPIRead(LR_RegPayloadLength); if(temp==21) { break; } if(SysTime>=3) return 0; } }
/****************************************************************************** **Name: SI4432_Reset **Function: Software Reset SI4432 module **Input: none **Output: none ******************************************************************************/ void SI4432_Reset(void) { SPIWrite(0x0708); //Software reset while (nIRQ); // Wait for chip ready SPIRead(0x03); //Clr nIRQ SPIRead(0x04); }
//===================================== u8 sx1278_LoRaRxPacket(void) //===================================== { u8 i; u8 addr; u8 packet_size; if(Get_NIRQ()) { for(i=0;i<32;i++) RxData[i] = 0x00; addr = SPIRead(LR_RegFifoRxCurrentaddr); //last packet addr SPIWrite(LR_RegFifoAddrPtr,addr); //RxBaseAddr -> FiFoAddrPtr if(sx1278SpreadFactorTable[Lora_Rate_Sel]==6) //When SpreadFactor is six£¬will used Implicit Header mode(Excluding internal packet length) packet_size=21; else packet_size = SPIRead(LR_RegRxNbBytes); //Number for received bytes SPIBurstRead(0x00, RxData, packet_size); SPIWrite(LR_RegIrqFlags,LoRa_ClearIRQ_Value); for(i=0;i<17;i++) { if(RxData[i]!=sx1278Data[i]) break; } if(i>=17) //Rx success return(1); else return(0); } else return(0); }
//===================================== u8 sx1278_LoRaEntryRx(void) //===================================== { u8 addr,temp; ANT_EN_L(); ANT_CTRL_RX(); sx1278_Config(); //setting base parameter SPIWrite(REG_LR_PADAC,0x84); //Normal and Rx SPIWrite(LR_RegHopPeriod,0xFF); //RegHopPeriod NO FHSS SPIWrite(REG_LR_DIOMAPPING1,0x01); //DIO0=00, DIO1=00, DIO2=00, DIO3=01 Valid header SPIWrite(LR_RegIrqFlagsMask,0x3F); //Open RxDone interrupt & Timeout SPIWrite(LR_RegIrqFlags,LoRa_ClearIRQ_Value); SPIWrite(LR_RegPayloadLength,21); //RegPayloadLength 21byte(this register must difine when the data long of one byte in SF is 6) addr = SPIRead(LR_RegFifoRxBaseAddr); //Read RxBaseAddr SPIWrite(LR_RegFifoAddrPtr,addr); //RxBaseAddr -> FiFoAddrPtr¡¡ SPIWrite(LR_RegOpMode,0x8d); //Continuous Rx Mode//Low Frequency Mode //SPIWrite(LR_RegOpMode,0x05); //Continuous Rx Mode//High Frequency Mode SysTime = 0; while(1) { if((SPIRead(LR_RegModemStat)&0x04)==0x04) //Rx-on going RegModemStat break; if(SysTime>=3) return 0; //over time for error } }
void firmware_start(void) { // For SDK 1.5.2, either address has shifted and not mirrored in // eagle.rom.addr.v6.ld, or extra initial member was added. SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); char buf[128]; SPIRead(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); /*for (int i = 0; i < sizeof(buf); i++) { static char hexf[] = "%x "; ets_printf(hexf, buf[i]); }*/ bool inited = false; for (int i = 0; i < sizeof(buf); i++) { if (buf[i] != 0xff) { inited = true; break; } } if (!inited) { static char msg[] = "Writing init data\n"; ets_printf(msg); SPIRead((uint32_t)&default_init_data - 0x40200000, buf, sizeof(buf)); SPIWrite(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); } asm("j call_user_start"); }
/****************************************************************************** **Name: SI4432_Standby **Function: config SI4432 module into Standby mode **Input: none **Output: none ******************************************************************************/ void SI4432_Standby(void) { SPIWrite(0x0803); //Clr FIFO SPIWrite(0x0800); SPIRead(0x03); //Clr nIRQ SPIRead(0x04); SPIWrite(0x0701); //Standby }
/****************************************************************************** **Name: SI4432_ClearFIFO **Function: clear FIFO **Input: none **Output: none ******************************************************************************/ void SI4432_ClearFIFO(void) { SPIRead(0x03); //Clr nIRQ SPIRead(0x04); SPIWrite(0x0701 //to Standby SPIWrite(0x0803 //Clr FIFO SPIWrite(0x0800); }
/****************************************************************************** **Name: SI4432_Sleep **Function: config SI4432 module into sleep **Input: none **Output: none ******************************************************************************/ void SI4432_Sleep(void) { SPIWrite(0x0803); //Clr FIFO SPIWrite(0x0800); SPIRead(0x03); //Clr nIRQ SPIRead(0x04); SPIWrite(0x0700); //Sleep }
//extern char _text_end; //============================================================================= // IRAM code //============================================================================= // call_user_start() - вызов из заголовка, загрузчиком // ENTRY(call_user_start) in eagle.app.v6.ld //----------------------------------------------------------------------------- void __attribute__ ((noreturn)) call_user_start(void) { // Cache_Read_Disable(); IO_RTC_4 = 0; // Отключить блок WiFi (уменьшение потребления на время загрузки) GPIO0_MUX_alt = VAL_MUX_GPIO0_SDK_DEF; // Отключить вывод CLK на GPIO0 SPI0_USER |= SPI_CS_SETUP; // +1 такт перед CS = 0x80000064 #if FQSPI == 80 // xSPI на 80 MHz GPIO_MUX_CFG_alt |= BIT(MUX_SPI0_CLK_BIT); // QSPI = 80 MHz SPI0_CTRL = (SPI0_CTRL & SPI_CTRL_F_MASK) | SPI_CTRL_F80MHZ; #else // xSPI на 40 MHz GPIO_MUX_CFG_alt &= ~(1<< MUX_SPI0_CLK_BIT); SPI0_CTRL = (SPI0_CTRL & SPI_CTRL_F_MASK) | SPI_CTRL_F40MHZ; #endif // OTA #if DEBUGSOO > 1 p_printf("\nStart OTA loader.\n"); #endif uint32_t buffer[SPI_FLASH_SEC_SIZE/4]; SPIRead(esp_init_data_default_addr + MAX_SYS_CONST_BLOCK, buffer, (sizeof(OTA_flash_struct)+3)&~3); OTA_flash_struct *OTA = (OTA_flash_struct *)buffer; if(OTA->id == OTA_flash_struct_id) { uint32 image_start = OTA->image_addr; uint32 sectors = OTA->image_sectors; SPIRead(image_start, buffer, 4); if(*(uint8 *)buffer == firmware_start_magic) { #if DEBUGSOO > 0 p_printf("Update firmware from 0x%x, %u sectors: ", image_start, sectors); #endif ets_delay_us(1000000); // 1 sec uint32 write_to = 0; for(uint32 i = 0; i < sectors; i++) { SPIRead(image_start + i * SPI_FLASH_SEC_SIZE, buffer, SPI_FLASH_SEC_SIZE); SPIEraseSector(i); SPIWrite(write_to, buffer, SPI_FLASH_SEC_SIZE); write_to += SPI_FLASH_SEC_SIZE; #if DEBUGSOO > 0 p_printf("x"); #endif } #if DEBUGSOO > 0 p_printf("\nOk."); #endif if(image_start >= write_to) SPIEraseSector(image_start / SPI_FLASH_SEC_SIZE); _ResetVector(); } } #if DEBUGSOO > 1 p_printf("\nGoto next loader.\n"); #endif // Всё, включаем кеширование, далее можно вызывать процедуры из flash Cache_Read_Enable(0, 0, 0); // Переход в область кеширования flash, // Запускаем загрузку SDK с указателем на заголовок SPIFlashHeader (находится за данным загручиком по адресу с align 16) // ((loader_call)((uint32)(&loader_flash_boot) + FLASH_BASE - IRAM_BASE + 0x10))((struct SPIFlashHeader *)(((uint32)(&_text_end) + FLASH_BASE - IRAM_BASE + 0x17) & (~15))); ((loader_call)(loader_flash_boot_addr))((struct SPIFlashHeader *)(next_flash_header_addr)); }
int load_app_from_flash_raw(const uint32_t flash_addr) { image_header_t image_header; uint32_t pos = flash_addr + APP_START_OFFSET; if (SPIRead(pos, &image_header, sizeof(image_header))) { return 1; } pos += sizeof(image_header); for (uint32_t section_index = 0; section_index < image_header.num_segments; ++section_index) { section_header_t section_header = {0}; if (SPIRead(pos, §ion_header, sizeof(section_header))) { return 2; } pos += sizeof(section_header); const uint32_t address = section_header.address; bool load = false; if (address < 0x40000000) { load = true; } if (address >= 0x40100000 && address < 0x40108000) { load = true; } if (address >= 0x60000000) { load = true; } if (!load) { pos += section_header.size; continue; } if (SPIRead(pos, (void*)address, section_header.size)) return 3; pos += section_header.size; } register uint32_t sp asm("a1") = 0x3ffffff0; register uint32_t pc asm("a3") = image_header.entry; __asm__ __volatile__ ("jx a3"); return 0; }
/* SPIReadByte: Get two bytes from denstination register. * return: 2 bytes data */ uint32_t SPIRead2Bytes(uint8_t reg){ uint32_t data; // digitalWrite(SLAVE_CS, LOW); SPIWrite(reg); data = SPIRead(); data = (data << 8)| SPIRead(); // digitalWrite(SLAVE_CS, HIGH); return data; }
void TEXT_SECTION_ATTR user_start_trampoline (void) { __real__xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, load_non_32_wide_handler); SPIFlashInfo sfi; SPIRead (0, &sfi, sizeof (sfi)); // Cache read not enabled yet, safe to use if (sfi.size < 2) // Compensate for out-of-order 4mbit vs 2mbit values sfi.size ^= 1; uint32_t flash_end_addr = (256 * 1024) << sfi.size; uint32_t init_data_hdr = 0xffffffff; SPIRead (flash_end_addr - 4 * SPI_FLASH_SEC_SIZE, &init_data_hdr, sizeof (init_data_hdr)); no_init_data = (init_data_hdr == 0xffffffff); call_user_start(); }
static u08 ReadMacReg(u08 bytAddress) { u08 bytData; if (bytAddress > 0x1F) return FALSE; // address invalid, [TO DO] SEL_MAC(TRUE); // ENC CS low SPIWrite(&bytAddress,1); // write opcode SPIRead(&bytData, 1); // read dummy byte SPIRead(&bytData, 1); // read value SEL_MAC(FALSE); return bytData; }
/** @brief Get 2 bytes from denstination register. * @param reg : register * @return 2 bytes data */ uint32_t SPIRead2Bytes(uint8_t reg){ uint32_t data; if (selectedShieldVersion < 4){ digitalWrite(CS, LOW); } SPIWrite(reg); data = SPIRead(); data = (data << 8)| SPIRead(); if (selectedShieldVersion < 4){ digitalWrite(CS, HIGH); } return data; }
/****************************************************************************** **Name: SI4432_TxPacket **Function: transmit package data in buffer to FIFO **Input: buffer, bytes to sent **Output: 0--error ** 1--ok ******************************************************************************/ byte SI4432_TxPacket(byte *buffer, int len) { if (!buffer) return 0; // no nil buffer! if (len > FIFOSIZE) return 0; // no over size ego SPIRead(0x03); //Clr nIRQ SPIRead(0x04); BurstWrite(0x7F, buffer, len); SPIWrite(0x0709); //Tx state while(digitalRead(nIRQ) && (millis()-lastTime<Tx_WAIT_TIMEOUT)); irqStatus1 = SPIRead(0x03); //Clr nIRQ irqStatus2 = SPIRead(0x04); if (irqStatus1 & 0x04 == 0x04) return 1; return 0; }
/*************************************************************************** * * Function : set_sdm_src_switch * * IN : param, a value to write to the regiter UsbPhyMmanagement3 * OUT : * * RET : Return the value of register UsbPhyMmanagement3 * * Notes : From register 0x0583, bits 3:3 * **************************************************************************/ unsigned char set_sdm_src_switch( enum sdm_src_switch_opened param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(USB_PHY_MMANAGEMENT_3_REG); /* * 0: SDM_SRC USB switch is opened * 1: SDM_SRC USB switch is closed */ switch( param ) { case SDM_SRC_SWITCH_OPEN_E: value = old_value | SDM_SRC_SWITCH_OPENED_PARAM_MASK; break; case SDM_SRC_SWITCH_CLOSE_E: value = old_value & ~ SDM_SRC_SWITCH_OPENED_PARAM_MASK; break; } SPIWrite(USB_PHY_MMANAGEMENT_3_REG, value); return old_value; }
char IMURead(char adress,char Device) { char TempData=0; char Result=0; TempData = (adress | 0b10000000); //set RW bit, and adress (clipped to 7 bits) if(Device==ACCEL_ID) // select the right CS to assert according to device selection ACCEL_SPI_CS = 0; else if(Device==GYRO_ID) GYRO_SPI_CS = 0; else if(Device==MAGNET_ID) MAGNET_SPI_CS=0; SPIWrite(TempData); Result = SPIRead(0); ACCEL_SPI_CS = 1; GYRO_SPI_CS = 1; MAGNET_SPI_CS= 1; return Result; }
/*************************************************************************** * * Function : set_coulomb_counter_offset_computation * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 4:4 * **************************************************************************/ unsigned char set_coulomb_counter_offset_computation( enum computation_enable param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * (auto-cleared) * 0: disable offset average computation. * 1: enable offset average computation */ switch( param ) { case COMPUTATION_ENABLE_E: value = old_value | COMPUTATION_ENABLE_PARAM_MASK; break; case COMPUTATION_DISABLE_E: value = old_value & ~ COMPUTATION_ENABLE_PARAM_MASK; break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
/*************************************************************************** * * Function : set_coulomb_counter_calibration_mode * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 3:3 * **************************************************************************/ unsigned char set_coulomb_counter_calibration_mode( enum calibration_enable param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * 0: doesn't set ADconverter in calibration mode. * 1: set ADconverter in calibration mode */ switch( param ) { case CALIBRATION_ENABLE_E: value = old_value | CALIBRATION_ENABLE_PARAM_MASK; break; case CALIBRATION_DISABLE_E: value = old_value & ~ CALIBRATION_ENABLE_PARAM_MASK; break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
/*************************************************************************** * * Function : set_coulomb_counter_reset_accumlator * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 1:1 * **************************************************************************/ unsigned char set_coulomb_counter_reset_accumlator( enum reset_accumlator_enable param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * (auto-cleared) * 0: inactive * 1: allow to reset Accumulator and SampleConversion * counters when a reading is done.r */ switch( param ) { case RESET_E: value = old_value | RESET_ACCUMLATOR_ENABLE_PARAM_MASK; break; case UN_RESET_E: value = old_value & ~ RESET_ACCUMLATOR_ENABLE_PARAM_MASK; break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
int do_flash_read(uint32_t addr, uint32_t len, uint32_t block_size, uint32_t max_in_flight) { uint8_t buf[FLASH_SECTOR_SIZE]; uint8_t digest[16]; struct MD5Context ctx; uint32_t num_sent = 0, num_acked = 0; if (block_size > sizeof(buf)) return 0x52; MD5Init(&ctx); while (num_acked < len) { while (num_sent < len && num_sent - num_acked < max_in_flight) { uint32_t n = len - num_sent; if (n > block_size) n = block_size; if (SPIRead(addr, buf, n) != 0) return 0x53; send_packet(buf, n); MD5Update(&ctx, buf, n); addr += n; num_sent += n; } { if (SLIP_recv(&num_acked, sizeof(num_acked)) != 4) return 0x54; if (num_acked > num_sent) return 0x55; } } MD5Final(digest, &ctx); send_packet(digest, sizeof(digest)); return 0; }
/*************************************************************************** * * Function : set_coulomb_counter_mux_offset * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 7:7 * **************************************************************************/ unsigned char set_coulomb_counter_mux_offset( enum select param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * 0: select offset from CC_Offset register. * 1: select internal average offset */ switch( param ) { case SELECT_FROM_OFFSET_REGISTER_E: value = old_value | SELECT_PARAM_MASK; break; case SELECT_INTERNAL_E: value = old_value & ~ SELECT_PARAM_MASK; break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
/*************************************************************************** * * Function : set_coulomb_counter_read_enable * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 0:0 * **************************************************************************/ unsigned char set_coulomb_counter_read_enable( enum read_enable param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * (auto-cleared) * 0: inactive * 1: allows to transfer the accumulator data, * SampleConversion and SampleCounter data to the associated * registers */ switch( param ) { case READ_ENABLE_E: value = old_value | READ_ENABLE_PARAM_MASK; break; case READ_DISABLE_E: value = old_value & ~ READ_ENABLE_PARAM_MASK; break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
/*************************************************************************** * * Function : set_comlomb_data_transfert * * IN : param, a value to write to the regiter CoulombDataManagement * OUT : * * RET : Return the value of register CoulombDataManagement * * Notes : From register 0x0C11, bits 1:1 * **************************************************************************/ unsigned char set_comlomb_data_transfert( enum data_transfert param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_DATA_MANAGEMENT_REG); /* * allows to transfer the accumulator data to the NconAccu * registers */ switch( param ) { case NOT_TRANSFERT_TO_NCONACCU_E: value = old_value | DATA_TRANSFERT_PARAM_MASK; break; case TRANSFERT_TO_NCONACCU_E: value = old_value & ~ DATA_TRANSFERT_PARAM_MASK; break; } SPIWrite(COULOMB_DATA_MANAGEMENT_REG, value); return old_value; }
/*************************************************************************** * * Function : set_comlomb_reset_bit_data * * IN : param, a value to write to the regiter CoulombDataManagement * OUT : * * RET : Return the value of register CoulombDataManagement * * Notes : From register 0x0C11, bits 0:0 * **************************************************************************/ unsigned char set_comlomb_reset_bit_data( enum bit_data_reset param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_DATA_MANAGEMENT_REG); /* * allows to reset the 21bits accumulator data */ switch( param ) { case BIT_DATA_RESET_E: value = old_value | BIT_DATA_RESET_PARAM_MASK; break; case BIT_DATA_UN_RESET_E: value = old_value & ~ BIT_DATA_RESET_PARAM_MASK; break; } SPIWrite(COULOMB_DATA_MANAGEMENT_REG, value); return old_value; }
/*************************************************************************** * * Function : set_coulomb_counter_number_of_convertion * * IN : param, a value to write to the regiter CoulombCounterControl * OUT : * * RET : Return the value of register CoulombCounterControl * * Notes : From register 0x0C00, bits 6:5 * **************************************************************************/ unsigned char set_coulomb_counter_number_of_convertion( enum number_convertion param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(COULOMB_COUNTER_CONTROL_REG); /* * 00: 4 * 01: 8 * 10: 16 */ value = old_value & ~NUMBER_CONVERTION_PARAM_MASK ; switch( param ) { case NUMBER_CONVERTION_4_E: value = value | (NUMBER_CONVERTION_4 << 0x5); break; case NUMBER_CONVERTION_8_E: value = value | (NUMBER_CONVERTION_8 << 0x5); break; case NUMBER_CONVERTION_16_E: value = value | (NUMBER_CONVERTION_16 << 0x5); break; } SPIWrite(COULOMB_COUNTER_CONTROL_REG, value); return old_value; }
int copy_raw(const uint32_t src_addr, const uint32_t dst_addr, const uint32_t size) { // require regions to be aligned if (src_addr & 0xfff != 0 || dst_addr & 0xfff != 0) { return 1; } const uint32_t buffer_size = FLASH_SECTOR_SIZE; uint8_t buffer[buffer_size]; uint32_t left = ((size+buffer_size-1) & ~(buffer_size-1)); uint32_t saddr = src_addr; uint32_t daddr = dst_addr; while (left) { if (SPIEraseSector(daddr/buffer_size)) { return 2; } if (SPIRead(saddr, buffer, buffer_size)) { return 3; } if (SPIWrite(daddr, buffer, buffer_size)) { return 4; } saddr += buffer_size; daddr += buffer_size; left -= buffer_size; } return 0; }
/*************************************************************************** * * Function : set_pwm_out1_enable * * IN : param, a value to write to the regiter PwmOutManagement5 * OUT : * * RET : Return the value of register PwmOutManagement5 * * Notes : From register 0x1066, bits 0:0 * **************************************************************************/ unsigned char set_pwm_out1_enable( enum pwm_out1_enable param ) { unsigned char value = 0; unsigned char old_value; old_value = SPIRead(PWM_OUT_MANAGEMENT_5_REG); /* * 0: Disable PWMOut1 generator * 1: Enable PWMOut1 generator */ switch( param ) { case PWM_OUT_1_ENABLE_E: value = old_value | PWM_OUT_1_ENABLE_PARAM_MASK; break; case PWM_OUT_1_DISABLE_E: value = old_value & ~ PWM_OUT_1_ENABLE_PARAM_MASK; break; } SPIWrite(PWM_OUT_MANAGEMENT_5_REG, value); return old_value; }
int do_flash_digest(uint32_t addr, uint32_t len, uint32_t digest_block_size) { uint8_t buf[FLASH_SECTOR_SIZE]; uint8_t digest[16]; uint32_t read_block_size = digest_block_size ? digest_block_size : sizeof(buf); struct MD5Context ctx; if (digest_block_size > sizeof(buf)) return 0x62; MD5Init(&ctx); while (len > 0) { uint32_t n = len; struct MD5Context block_ctx; MD5Init(&block_ctx); if (n > read_block_size) n = read_block_size; if (SPIRead(addr, buf, n) != 0) return 0x63; MD5Update(&ctx, buf, n); if (digest_block_size > 0) { MD5Update(&block_ctx, buf, n); MD5Final(digest, &block_ctx); send_packet(digest, sizeof(digest)); } addr += n; len -= n; } MD5Final(digest, &ctx); send_packet(digest, sizeof(digest)); return 0; }
uint8_t Read4500reg(uint8_t bank,uint8_t address,uint8_t* p_data) { *p_data = SPIRead((bank<<8)|(address& 0xFF)); return HATS_AUDIO_NO_ERROR; }