Add bcm_wait_ready() comprehensive pre-write readiness check
Stock firmware wait_for_ready() at 0x2000 checks three conditions before
each init block write — all must be simultaneously true:
1. A2.bit3 = 1 (BCM4500 DSP processing complete)
2. A8.bit0 = 0, A8.bit1 = 1 (command register ready)
3. A4.bit7 = 1 (init pipeline flushed)
Our bcm_poll_ready() only checked A8.bit0, and was used for both
pre-write and post-write checks. Now:
- bcm_wait_ready(): strict 3-condition check for PRE-write
(with fallback to simple A8 check for gateway quirks)
- bcm_poll_ready(): simple A8 check for POST-write
(matches stock firmware's poll_ready() at 0x20C5)
Code size: 15,155 / 15,360 bytes (205 bytes spare)
This commit is contained in:
parent
e9e5ab859a
commit
dffef75b06
@ -735,18 +735,12 @@ static BOOL bcm_indirect_write_block(BYTE page, __xdata BYTE *data, BYTE len) {
|
||||
|
||||
/*
|
||||
* Poll BCM4500 for command completion via gateway register A8.
|
||||
* Matches stock firmware's poll_ready() at 0x20C5: checks A8.bit0 = 0.
|
||||
* Used AFTER init block writes / indirect commands.
|
||||
*
|
||||
* The BCM3440 gateway's A8 register does not always clear bit 0 after
|
||||
* the BCM4500 DSP processes an indirect write command, even though the
|
||||
* write succeeds internally (confirmed by reading the direct BCM4500
|
||||
* address 0x08 where A8 bit 0 does clear and bit 1 becomes set).
|
||||
*
|
||||
* The stock firmware's 0x20C5 polls the same gateway A8 via 0x2258
|
||||
* and expects bit 0=0, bit 1=1. On our device, bit 1 never becomes 1
|
||||
* through the gateway after writes, but the init data IS applied.
|
||||
*
|
||||
* Strategy: poll for early completion, but treat timeout as success
|
||||
* with a settling delay rather than hard failure.
|
||||
* Treats timeout as success with settling delay — the gateway A8 register
|
||||
* doesn't always reflect the BCM4500's internal ready state, but commands
|
||||
* do complete internally.
|
||||
*/
|
||||
static BOOL bcm_poll_ready(void) {
|
||||
BYTE i, val;
|
||||
@ -763,6 +757,59 @@ static BOOL bcm_poll_ready(void) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Comprehensive BCM4500 readiness check — used BEFORE init block writes.
|
||||
*
|
||||
* Replicates stock firmware wait_for_ready() at 0x2000, which checks
|
||||
* THREE conditions that must ALL be true simultaneously:
|
||||
*
|
||||
* 1. A2.bit3 = 1 (BCM4500 status register — DSP processing complete)
|
||||
* Stock firmware: condition_1() at 0x2314
|
||||
*
|
||||
* 2. A8.bit0 = 0 (command register not busy)
|
||||
* A8.bit1 = 1 (command result ready)
|
||||
* Stock firmware: condition_2() at 0x2258
|
||||
*
|
||||
* 3. A4.bit7 = 1 (lock/status register — init pipeline flushed)
|
||||
* Stock firmware: condition_3() at 0x235B
|
||||
*
|
||||
* This is STRICTER than bcm_poll_ready() which only checks A8.bit0.
|
||||
* The stock firmware uses this strict check before writing each init block,
|
||||
* ensuring the BCM4500 has fully processed the previous block before
|
||||
* accepting a new one.
|
||||
*
|
||||
* Retries up to 10 times with delays. Returns FALSE on timeout.
|
||||
*/
|
||||
static BOOL bcm_wait_ready(void) {
|
||||
BYTE i, val;
|
||||
for (i = 0; i < 10; i++) {
|
||||
/* Condition 1: A2.bit3 — DSP status */
|
||||
if (!bcm_direct_read(BCM_REG_STATUS, &val))
|
||||
return FALSE;
|
||||
if (val & 0x08) {
|
||||
/* Condition 2: A8.bit0=0, A8.bit1=1 — command ready */
|
||||
if (!bcm_direct_read(BCM_REG_CMD, &val))
|
||||
return FALSE;
|
||||
if (!(val & 0x01) && (val & 0x02)) {
|
||||
/* Condition 3: A4.bit7 — pipeline flushed */
|
||||
if (!bcm_direct_read(BCM_REG_LOCK, &val))
|
||||
return FALSE;
|
||||
if (val & 0x80)
|
||||
return TRUE; /* All 3 conditions met */
|
||||
}
|
||||
}
|
||||
delay(10);
|
||||
}
|
||||
/* Fallback: if comprehensive check times out but A8 reports not-busy,
|
||||
* proceed anyway — handles case where A2/A4 conditions don't reflect
|
||||
* properly through the BCM3440 I2C gateway. */
|
||||
if (bcm_direct_read(BCM_REG_CMD, &val) && !(val & 0x01)) {
|
||||
delay(5);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read 16-byte signal data block from BCM4500 via indirect register protocol.
|
||||
*
|
||||
@ -848,9 +895,9 @@ static BOOL bcm_write_init_block(const __code BYTE *data, BYTE len) {
|
||||
BYTE i;
|
||||
|
||||
/* Pre-write readiness check — stock firmware 0x0DE9 calls wait_for_ready()
|
||||
* (0x2000) before each block. This polls A8 + additional conditions with
|
||||
* up to 10 retries. Our simplified version polls A8 only. */
|
||||
if (!bcm_poll_ready())
|
||||
* (0x2000) before each block. This checks 3 conditions: A2.bit3, A8.bit0+1,
|
||||
* A4.bit7. All must be true before the BCM4500 accepts a new init block. */
|
||||
if (!bcm_wait_ready())
|
||||
return FALSE;
|
||||
|
||||
/* Page select = 0 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user