Reputation: 71
I am trying to use the ADC on STM32f407G-DISC1 board to read joystick x and y position on pins PA2 and PA1 respectively and store the values to a memory location using the DMA.
ADC1_BASE + ADC_DR
; So the data register of ADC1JOYSTICK_POS
Start conversion of regular channels on ADC1 (Set SWSTART in ADC_CR2)
@RCC
.equ RCC_BASE, 0x40023800
.equ RCC_AHB1ENR, 0x30
.equ RCC_APB2ENR, 0x44
@ GPIOA
.equ GPIOA_BASE, 0x40020000
.equ GPIO_ODR, 0x14
.equ GPIO_BSRR, 0x18
.equ GPIO_AFRL, 0x20
.equ GPIO_AFRH, 0x24
@ ADC
.equ ADC1_BASE, 0x40012000
.equ ADC2_BASE, 0x40012100
.equ ADC3_BASE, 0x40012200
.equ ADC_SR, 0x0
.equ ADC_CR1, 0x4
.equ ADC_CR2, 0x8
.equ ADC_DR, 0x4c
.equ ADC_HTR, 0x24
.equ ADC_LTR, 0x28
.equ ADC_SQR1, 0x2c
.equ ADC_SQR2, 0x30
.equ ADC_SQR3, 0x34
.equ ADC_SMPR1, 0x0C
.equ ADC_SMPR2, 0x10
.equ ADC_CCR, 0x04
@ DMA
.equ DMA1_BASE, 0x40026000
.equ DMA2_BASE, 0x40026400
.equ DMA_LISR, 0x0
.equ DMA_HISR, 0x4
.equ DMA_S0CR, 0x10 + 0x18 * 0
.equ DMA_S3CR, 0x10 + 0x18 * 3
.equ DMA_S0_NDTR, 0x14 + 0x18 * 0
.equ DMA_S0PAR, 0x18 + 0x18 * 0
.equ DMA_S0M0AR, 0x1c + 0x18 * 0
.equ DMA_S0M1AR, 0x20 + 0x18 * 0
// SysTick Timer definitions
.equ SCS, 0xe000e000
.equ SCS_SYST_CSR, 0x10 // Control/Status register
.equ SCS_SYST_RVR, 0x14 // Value to countdown from
.equ SCS_SYST_CVR, 0x18 // Current value
.equ SYSTICK_RELOAD_1MS, 15999 //1 msec at 16MHz ... 16 000 000 / 500 - 1
.section .text
JOYSTICK_POS: .word 0 @ This is where I want to store the 2 position values
_start:
bl init_io
bl init_tc
bl init_adc1
bl enable_adc1
bl init_dma2
bl dma2_joystick_config
bl start_adc1
main:
@ Load the word at JOYSTICK_POS into r6. This will stay 0 for ever
ldr r6, JOYSTICK_POS
b main
dma2_joystick_config:
push { r5, r6, lr }
ldr r5, =DMA2_BASE
@ N of data items to transfer: 2
mov r6, #2
str r6, [r5, #DMA_S0_NDTR]
ldr r5, =DMA2_BASE
ldr r6, =ADC1_BASE + ADC_DR
str r6, [r5, #DMA_S0PAR]
adr r6, JOYSTICK_POS
str r6, [r5, #DMA_S0M0AR]
@ Enable stream
ldr r6, [r5, #DMA_S0CR]
orr r6, #1
str r6, [r5, #DMA_S0CR]
pop { r5, r6, pc }
init_dma2:
push { r5, r6, lr }
@ Enable DMA2 clock
ldr r5, =RCC_BASE
ldr r6, [r5, #RCC_AHB1ENR]
orr r6, #(1<<22)
str r6, [r5, #RCC_AHB1ENR]
ldr r5, =DMA2_BASE
mov r6, #0
str r6, [r5, #DMA_S0CR]
wait_dma2_reset:
ldr r6, [r5, #DMA_S0CR]
tst r6, #1
bne wait_dma2_reset
mov r6, #0
str r6, [r5, #DMA_LISR]
str r6, [r5, #DMA_HISR]
@ Channel 0, Stream 0
@ CHSEL: 0, DIR: Peripheral to memmory,
mov r6, #0
@ PSIZE, MSIZE hword
orr r6, #(0b01<<11)
orr r6, #(0b01<<13)
@ Priority very high
orr r6, #(0b11 << 16)
@ CIRC MODE ENABLE
orr r6, #(1<<8)
@ TCIE = 1
@ orr r6, #(1<<4)
@ MEMORY INC
orr r6, #(1<<10)
str r6, [r5, #DMA_S0CR]
pop { r5, r6, pc }
start_adc1:
push { r5, r6, lr }
ldr r5, =ADC1_BASE
mov r6, #0
str r6, [r5, #ADC_SR]
@ START
ldr r6, [r5, #ADC_CR2]
orr r6, #(1<<30)
str r6, [r5, #ADC_CR2]
pop { r5, r6, pc }
enable_adc1:
push { r5, r6, lr }
ldr r5, =ADC1_BASE
ldr r6, [r5, #ADC_CR2]
orr r6, #1
str r6, [r5, #ADC_CR2]
@ Wait (10ms) for ADC to stabilize
mov r0, #10
bl delay
pop { r5, r6, pc }
init_adc1:
push { r5, r6, lr }
@ Enable ADC1 clock
ldr r5, =RCC_BASE
ldr r6, [r5, #RCC_APB2ENR]
orr r6, #(1<<8)
str r6, [r5, #RCC_APB2ENR]
ldr r5, =ADC1_BASE
@ Reset adc registers
mov r6, #0
str r6, [r5, #ADC_CR2]
str r6, [r5, #ADC_CR1]
str r6, [r5, #ADC_SMPR1]
str r6, [r5, #ADC_SMPR2]
str r6, [r5, #ADC_SQR1]
str r6, [r5, #ADC_SQR2]
str r6, [r5, #ADC_SQR3]
str r6, [r5, #ADC_CCR]
@ CLK prescaler
orr r6, #(2<<16)
str r6, [r5, #ADC_CCR]
@ CR1 settings
@ SCAN MODE
orr r6, #(1<<8)
str r6, [r5, #ADC_CR1]
@CR2 settings
@ set CONT mode
mov r6, #0b10
@ EOC after each conversion
orr r6, #(1<<10)
@ Enable DMA, DDS
orr r6, #(0b11<<8)
str r6, [r5, #ADC_CR2]
@ Two conversions
mov r6, #(1<<20)
str r6, [r5, #ADC_SQR1]
@ Select order, PA1, PA2
mov r6, #1
orr r6, #(2 << 5)
str r6, [r5, #ADC_SQR3]
@ SAMPLE TIME
@ mov r6, #9
@ str r6, [r5, #ADC_SMPR2]
pop { r5, r6, pc }
init_io:
push { r5, r6, lr }
@ Enable GPIOA clock
ldr r5, =RCC_BASE
ldr r6, [r5, #RCC_AHB1ENR]
orr r6, #1
str r6, [r5, #RCC_AHB1ENR]
@ GPIOA_MODER
ldr r5, =GPIOA_BASE
@ set pins 1,2 as analog
ldr r6, [r5]
orr r6, #(0b11 << 2)
orr r6, #(0b11 << 4)
str r6, [r5]
pop { r5, r6, pc }
@ This is just code for the timer, so it's more clear what "bl delay" does
@ This works
init_tc:
push {r5, r6, lr}
ldr r6, =SCS
ldr r5, =SYSTICK_RELOAD_1MS
str r5, [r6, #SCS_SYST_RVR]
ldr r5, =0
str r5, [r6, #SCS_SYST_CVR]
ldr r5, =5
str r5, [r6, #SCS_SYST_CSR]
pop {r5, r6, pc}
delay:
push {r5, r6, lr}
ldr r5, =SCS
LOOPTC: ldr r6, [r5, #SCS_SYST_CSR]
tst r6, #0x10000
beq LOOPTC
subs r0, r0, 1
bne LOOPTC
pop {r5, r6, pc}
Upvotes: 0
Views: 1540
Reputation: 71
I have solved this issue by moving JOYSTICK_POS: .word 0
from .text section which is basically the code section and gets stored in ROM, to the .data section which is meant for storing data and gets stored in RAM. So the configuration was ok afterall.
Upvotes: 0