AnsweredAssumed Answered

Booting an ADAU from EEPROM via host MCU

Question asked by ElmarJ on Nov 2, 2015
Latest reply on Nov 2, 2015 by ElmarJ

I would like to boot my ADAU1702 SigmaDSP via my host processor, by using the EEPROM binaries created by SigmaStudio.

 

This would have a few advantages over using the "self boot" or boot via the "exported system files":

- Less memory footprint required in microcontroller (the DSP program does not fit in my microcontroller any more): everything is stored in an inexpensive EEPROM (24AA256 eg). (compared to the method with having all exported system files in the MCU).

- Memory can be easily changed without recompiling. This is nice because the person who is tweaking the acoustical performance is not the one who is compiling the source code. (I see the problems ahead with parameters being changed from MCU).

- It is easily possible to have multiple DSP programs ready at different locations in my EEPROM, I can ask my source to boot from a different location

- No need for selfboot checking after startup.

 

So, I analyzed the ADAU1702 selfboot chapter in the ADAU1702 datasheet, (page 27 and 28), and wrote a routine to be able to load the DSP code in smaller chunks: reading data from I2C EEPROM, parsing it and when I run out of buffer reading a new piece and writing it to the DSP.

 

My function is as following:

void DspLoadFromEeprom(uint8_t dspAddr, uint8_t eeAddr) {     //Reads the EEPROM     //Parses messages     //Send them to DSP      uint8_t buf[0xff];     char msg[256];      uint16_t rp;    //read pointer     uint16_t ap;    //available counter     int res;       uint16_t temp;    //temp for loading regs in multiples      uint8_t cmd;     uint16_t cmdLen;     uint16_t cmdAddr;      rp = 0;        //readpointer     ap = 0;        //availablepointer        if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }      while (1) {         cmd = buf[rp++ % sizeof(buf)];         ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }          switch (cmd) {             case DSP_CMD_END:                 DebugMsg("- DSP end\r\n");                 return 0;                 break;              case DSP_CMD_WRITE:                 DebugMsg("- DSP write\r\n");                 cmdLen = buf[rp++ % sizeof(buf)] * 0x100;                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                  cmdLen += buf[rp++ % sizeof(buf)];                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                  //skip device address, we might know that ;)                 rp++;                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                  cmdAddr = buf[rp++ % sizeof(buf)] * 0x100;                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                 cmdAddr += buf[rp++ % sizeof(buf)];                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                  //Debug for now, implement I2C later                 //rp +=  ap--;                  cmdLen -= 3;    //Because we already read address and two reg bytes!                  while (cmdLen) {                     //cmdLen is here how many bytes we have to send                     if (ap < cmdLen)                         temp = ap;        //If we do not have enough buffered, first send as many as we have.                     else                         temp = cmdLen;                      sprintf(msg, "  I2C_Write(0x%02x, 0x%04x, buf[0x%04x], 0x%04x);\r\n", dspAddr, cmdAddr, rp % sizeof(buf), temp);                     DebugMsg(msg);                      //Test exception for reg 0x081C //                    if (cmdAddr == 0x081c) { //                        buf[rp % sizeof(buf)+1] = buf[rp % sizeof(buf)+1] & 0xBF; //                        DebugMsg("Exception!\r\n"); //                    }                      Kakatoe_I2C_Write(dspAddr, cmdAddr, &buf[rp % sizeof(buf)], temp);                      cmdAddr += temp;                     rp += temp;                     ap -= temp;                     cmdLen -= temp;                      if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                 }                 //max addr in buffer:                  break;              case DSP_CMD_DELAY:                 DebugMsg("- DSP delay\r\n");                  cmdLen = buf[rp++ % sizeof(buf)] * 0x100;                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                 cmdLen += buf[rp++ % sizeof(buf)];                 ap--; if (ap == 0) {    Kakatoe_I2C_Read(eeAddr, rp, &buf, sizeof(buf)); ap += sizeof(buf);    }                  sprintf(msg, "  Delay %d units\r\n", cmdLen);                 DebugMsg(msg);                  break;              case DSP_CMD_NOP:                 DebugMsg("- DSP nop\r\n");                 break;              case DSP_CMD_SETMULWRITE:                 DebugMsg("- DSP Set Multiple Write\r\n");                 break;              case DSP_CMD_WBEDGEFAL:                 DebugMsg("- DSP WB Edge Falling\r\n");                 break;              case DSP_CMD_ENDWAITWB:                 DebugMsg("- DSP End and Wait WB\r\n");                 break;              default:                 DebugMsg("DSP Unkown cmd!\r\n");                 break;         }     }

 

However there are some problems:

- It does not work. When I first write this program to DSP using Sigma, it works. When I then run above function, it resets the volume controls. That is a good sign already, but when I power the DSP from scratch and write this, it will not work.

 

- I can see the EEPROM data is a bit different than the logs in SigmaStudio show. When I write the same program to EEPROM and to the DSP, and I compare the logs I can find that in one of the first commands, DSP Core Control register bit IFCW is set by EEPROM, but in the SigmaStudio logs this bit is zero. This bit enables external writes via the control port. I would assume that this bit needs to be set when writing through the I2C port, hence sigma studio does not set it. Should I also clear this? I tried this but it won`t fix the problem.

 

 

- SigmaStudio seems to program a lot of zero`s, whereas the EEPROM program omits this. Are all registers of the DSP set to zero on powerup?

 

 

This is the log produced by my function:

- DSP write   I2C_Write(0x68, 0x081c, buf[0x0006], 0x0002); Exception! - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP nop - DSP write   I2C_Write(0x68, 0x0800, buf[0x0020], 0x0020); - DSP write   I2C_Write(0x68, 0x0000, buf[0x0046], 0x0028); - DSP write   I2C_Write(0x68, 0x0400, buf[0x0074], 0x008b);   I2C_Write(0x68, 0x048b, buf[0x0000], 0x00f6); - DSP write   I2C_Write(0x68, 0x081c, buf[0x00fc], 0x0002); - DSP write   I2C_Write(0x68, 0x081d, buf[0x0005], 0x0001); - DSP write   I2C_Write(0x68, 0x081e, buf[0x000c], 0x0002); - DSP write   I2C_Write(0x68, 0x081f, buf[0x0014], 0x0001); - DSP write   I2C_Write(0x68, 0x0820, buf[0x001b], 0x0003); - DSP write   I2C_Write(0x68, 0x0821, buf[0x0024], 0x0003); - DSP write   I2C_Write(0x68, 0x0822, buf[0x002d], 0x0002); - DSP write   I2C_Write(0x68, 0x0823, buf[0x0035], 0x0002); - DSP write   I2C_Write(0x68, 0x0824, buf[0x003d], 0x0002); - DSP write   I2C_Write(0x68, 0x0825, buf[0x0045], 0x0002); - DSP write   I2C_Write(0x68, 0x0826, buf[0x004d], 0x0002); - DSP write   I2C_Write(0x68, 0x0827, buf[0x0055], 0x0002); - DSP write   I2C_Write(0x68, 0x081c, buf[0x005d], 0x0002); - DSP End and Wait WB - DSP end

 

 

Attached I have logs from SigmaStudio, as well as the EEPROM contents.

 

Can somebody with insight-knowledge have a thought about this?

Attachments

Outcomes