There are 1542 lines of code, and all sorts of things that are not explained - for instance, what is an "instance" of the A/D converter? What is the ADC_Type? Isn't there only one type?
void LPADC_DoAutoCalibration(ADC_Type *base) appears twice, and the two versions are different. Which one should I look at?
My code is rather more concise (77 lines, instead of 1542 lines) and well documented, and was written from the instructions in the manual.
// ----------- Set Up and Calibrate ADC -------------------------------------------------------------------------
.global SetUpADC
SetUpADC: LDR R3,=LPC_SYSCON_BASE
MOVS R0,#0
STR R0,[R3,ADCCLKSEL]
MOVS R0,#0
STR R0,[R3,ADCCLKDIV]
LDR R0,[R3,AHBCLKCTRL0]
ORRS R0,R0,#1<<27 // enable clock to ADC
STR R0,[R3,AHBCLKCTRL0]
LDR R3,=LPC_ADC0_BASE
MOVS R0,#2 // reset ADC module
STR R0,[R3,ADC_CTRL]
MOVW R0,#2<<8 // reset both FIFOs
STR R0,[R3,ADC_CTRL]
LDR R0,=1<<6|0x80<<16 // REFSEL=VREFH, PUDLY=0x80
STR R0,[R3,ADC_CFG]
MOVS R0,#1 // enable ADC module
STR R0,[R3,ADC_CTRL]
LDR R0,=1|1<<4|7<<16 // offset calibration 128 averages
STR R0,[R3,ADC_CTRL]
wcal0: LDR R0,[R3,ADC_STAT]
TST R0,#1<<10 // test for calibration complete
BEQ.n wcal0
LDR R0,=1|1<<3|7<<16 // gain calibration 128 averages
STR R0,[R3,ADC_CTRL]
wcal1: LDR R0,[R3,ADC_GCC0]
TST R0,#1<<24 // Gain calibration #0 valid
BEQ.n wcal1
wcal2: LDR R0,[R3,ADC_GCC1]
TST R0,#1<<24 // Gain calibration #1 valid
BEQ.n wcal2
LDR R0,[R3,ADC_GCC0] // Calculate GCR0
UXTH R1,R0
LSLS R0,R0,#16
RSBS R1,R1,#131072
UDIV R0,R0,R1
ORRS R0,R0,#1<<24
STR R0,[R3,ADC_GCR0]
LDR R0,[R3,ADC_GCC1] // Calculate GCR1
UXTH R1,R0
LSLS R0,R0,#16
RSBS R1,R1,#131072
UDIV R0,R0,R1
ORRS R0,R0,#1<<24
STR R0,[R3,ADC_GCR1]
wcal3: LDR R0,[R3,ADC_STAT] // test for calibration complete
TST R0,#1<<10
BEQ.n wcal3
MOVS R0,#1<<7|3<<5 // CH0A (Vbatt) only
STR R0,[R3,ADC_CMDL1]
LDR R0,=5<<8|4<<12|2<<24 // 35 cycles, 16 averages, next = 2
STR R0,[R3,ADC_CMDH1]
MOVS R0,#1<<7|1 // CH1A (Vmains) only
STR R0,[R3,ADC_CMDL2]
LDR R0,=5<<8|4<<12|3<<24 // 35 cycles, 16 averages, next = 3
STR R0,[R3,ADC_CMDH2]
MOVS R0,#1<<7|2 // CH2A (PSMon) only
STR R0,[R3,ADC_CMDL3]
LDR R0,=5<<8|4<<12|4<<24 // 35 cycles, 16 averages, next = 4
STR R0,[R3,ADC_CMDH3]
MOVS R0,#1<<7|2 // CH3A (Thermistor) only
STR R0,[R3,ADC_CMDL4]
LDR R0,=5<<8|4<<12|5<<24 // 35 cycles, 16 averages, next = 5
STR R0,[R3,ADC_CMDH4]
MOVS R0,#1<<7|1<<5|4 // CH4B (ChargerShunt) only
STR R0,[R3,ADC_CMDL5]
LDR R0,=5<<8|4<<12 // 35 cycles, 16 averages, finish
STR R0,[R3,ADC_CMDH5]
LDR R0,=1|1<<24
STR R0,[R3,ADC_TCTRL5] // trigger 5 (CTR0,MAT3), execute CMD1
MOVS R0,#1<<21
STR R0,[R3,ADC_IE] // INTERRUPT ON trigger 5 completion
BX LR
The most important question is whether the GCC values should read zero. Is this normal? As the range is from 0 to 65536, the chances of it being exactly zero seem small.
If I knew whether the fault was in the reading or in the calibrating, then I would be half way to finding it.