I am writing a boot loader for Pic18F67K22 device. Program data 0x200- 0x1FFFF. Boot code resides in memory location <0x200 and is unaffected by boot load program update. The program 0x200-0x1FFFF is getting proper values during programming and verified by reading device in IDE MPLAB8.92 with ICD3. When I run verify code the data from 0x200-0xFFFF is correct but once I get to 0x10000 all data reads back as 0x00. I also tested the device without the ICD3 and get the same result. I also tried compiling using a lookup table at 0rg 0x10000 to remove the boot load from the test and I get returned data 0x00. The program pointer is 21 byte wide for Low + high + upper and program memory is selected via EECON1,EEPGD & EECON1,CFGS. The TBLPTRU is correct at 0x01. I am reading the data from an external flash device. Any thoughts why its not reading ?
bt
bcf INTCON,7 ;// disable ALL interrupts
clrf EE_25LC_addr_L
clrf EE_25LC_addr_H
clrf EE_25LC_addr_U
call Init_Read_Boot ;// Set the 25LC1024 Start read address
movlw 0x00 ;// Set Start
movwf TBLPTRL
movwf File_byte_Counter_Low
movlw 0x02
movwf TBLPTRH
movwf File_byte_Counter_High
movlw 0x00
movwf TBLPTRU
movwf File_byte_Counter_Upper
Program_Loop
lfsr FSR0,0x500
movlw .128
movwf ByteCounter
call ReadProgMem ;// Read block
lfsr FSR0,0x400
movlw .128
movwf ByteCounter
call Read_EEPROM ;// 0x400 Modify buffer with new data for write
;// Erase
movf File_byte_Counter_Low,w
movwf TBLPTRL ;// Set Start
movf File_byte_Counter_High,w
movwf TBLPTRH
movf File_byte_Counter_Upper,w
movwf TBLPTRU
BSF EECON1, EEPGD ;//0x07 point to Flash program memory
BCF EECON1, CFGS ;// 0x06 access Flash program memory
BSF EECON1, WREN ;// 0x02 enable write to memory
BSF EECON1, FREE ;// 0x04 ERASE (gets cleard on completion of Erase cycle)
movlw 0x55 ; Erase block
movwf EECON2
movlw 0xAA
movwf EECON2
bsf EECON1, WR ;// 0x01 ; Start the write
nop
TBLRD*-
;// Write
lfsr FSR0,0x400
movlw .128
movwf ByteCounter
BSF EECON1, EEPGD ;//0x07 point to Flash program memory
BCF EECON1, CFGS ;// 0x06 access Flash program memory
BSF EECON1, WREN ;// 0x02 enable write to memory
call WriteProgMem
MOVLW 55h
MOVWF EECON2 ; write 55h
MOVLW 0AAh
MOVWF EECON2 ; write 0AAh
BSF EECON1, WR ; start program (CPU stall)
movlw .128
addwf File_byte_Counter_Low, F
btfsc STATUS,C
incf File_byte_Counter_High, F
btfsc STATUS,C
incf File_byte_Counter_Upper, F
btfss File_byte_Counter_Upper,1 ;// End of program space (U1)
goto Program_Loop
BCF EECON1, WREN ;// disable write to memory
call delay_7ms
nop
banksel PORTA
bsf LATA,3 ;// EPROM CS (SElECT)
call delay_7ms
;// Add verification here
Jmp_V
banksel EE_25LC_addr_L
clrf EE_25LC_addr_L
clrf EE_25LC_addr_H
clrf EE_25LC_addr_U
call Init_Read_Boot ;// Set the 25LC1024 Start read address
movlw 0x00 ;// Set Start
movwf File_byte_Counter_Low
movlw 0x02
movwf File_byte_Counter_High
movlw 0x00
movwf File_byte_Counter_Upper
Verify_Next_Block
movf File_byte_Counter_Low,w ;// Set Start
movwf TBLPTRL
movf File_byte_Counter_High,w
movwf TBLPTRH
movf File_byte_Counter_Upper,w
movwf TBLPTRU
movlw .128
movwf ByteCounter
Verify_Loop
tblrd *+ ; Fill buffer
movf TABLAT, w
movwf CHK_Program_Byte
movlw 0x00 ;// Read opcode
movwf SSP2BUF
btfss SSP2STAT,BF ;
goto $-2
movf SSP2BUF,w
movwf CHK_Flash_Byte
movf CHK_Program_Byte,w ;// CJNE
subwf CHK_Flash_Byte,w
btfss STATUS,Z
call Exit_fail
decfsz ByteCounter,f
goto Verify_Loop
; bsf LATA,3 ;// EPROM CS (DISABLE SElECT)
movlw .128
addwf File_byte_Counter_Low, F
btfsc STATUS,C
incf File_byte_Counter_High, F
btfsc STATUS,C
incf File_byte_Counter_Upper, F
btfss File_byte_Counter_Upper,1 ;// End of program space
goto Verify_Next_Block
Before you are asking a question first make a simplified test program like this one.
;Read high FLASH bytes test
#include "p18f87k22.inc"
; CONFIG1L
CONFIG RETEN = ON ; VREG Sleep Enable bit (Enabled)
CONFIG INTOSCSEL = HIGH ; LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
CONFIG SOSCSEL = HIGH ; SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
CONFIG XINST = OFF ; Extended Instruction Set (Disabled)
; CONFIG1H
CONFIG FOSC = INTIO2 ; Oscillator (Internal RC oscillator)
CONFIG PLLCFG = OFF ; PLL x4 Enable bit (Disabled)
CONFIG FCMEN = OFF ; Fail-Safe Clock Monitor (Disabled)
CONFIG IESO = OFF ; Internal External Oscillator Switch Over Mode (Disabled)
; CONFIG2L
CONFIG PWRTEN = OFF ; Power Up Timer (Disabled)
CONFIG BOREN = SBORDIS ; Brown Out Detect (Enabled in hardware, SBOREN disabled)
CONFIG BORV = 3 ; Brown-out Reset Voltage bits (1.8V)
CONFIG BORPWR = ZPBORMV ; BORMV Power level (ZPBORMV instead of BORMV is selected)
; CONFIG2H
CONFIG WDTEN = SWDTDIS ; Watchdog Timer (WDT enabled in hardware; SWDTEN bit disabled)
CONFIG WDTPS = 1048576 ; Watchdog Postscaler (1:1048576)
; CONFIG3L
CONFIG RTCOSC = SOSCREF ; RTCC Clock Select (RTCC uses SOSC)
CONFIG EASHFT = ON ; External Address Shift bit (Address Shifting enabled)
CONFIG ABW = MM ; Address Bus Width Select bits (8-bit address bus)
CONFIG BW = 16 ; Data Bus Width (16-bit external bus mode)
CONFIG WAIT = OFF ; External Bus Wait (Disabled)
; CONFIG3H
CONFIG CCP2MX = PORTC ; CCP2 Mux (RC1)
CONFIG ECCPMX = PORTE ; ECCP Mux (Enhanced CCP1/3 [P1B/P1C/P3B/P3C] muxed with RE6/RE5/RE4/RE3)
CONFIG MSSPMSK = MSK7 ; MSSP address masking (7 Bit address masking mode)
CONFIG MCLRE = ON ; Master Clear Enable (MCLR Enabled, RG5 Disabled)
; CONFIG4L
CONFIG STVREN = ON ; Stack Overflow Reset (Enabled)
CONFIG BBSIZ = BB2K ; Boot Block Size (2K word Boot Block size)
; CONFIG5L
CONFIG CP0 = OFF ; Code Protect 00800-03FFF (Disabled)
CONFIG CP1 = OFF ; Code Protect 04000-07FFF (Disabled)
CONFIG CP2 = OFF ; Code Protect 08000-0BFFF (Disabled)
CONFIG CP3 = OFF ; Code Protect 0C000-0FFFF (Disabled)
CONFIG CP4 = OFF ; Code Protect 10000-13FFF (Disabled)
CONFIG CP5 = OFF ; Code Protect 14000-17FFF (Disabled)
CONFIG CP6 = OFF ; Code Protect 18000-1BFFF (Disabled)
CONFIG CP7 = OFF ; Code Protect 1C000-1FFFF (Disabled)
; CONFIG5H
CONFIG CPB = OFF ; Code Protect Boot (Disabled)
CONFIG CPD = OFF ; Data EE Read Protect (Disabled)
; CONFIG6L
CONFIG WRT0 = OFF ; Table Write Protect 00800-03FFF (Disabled)
CONFIG WRT1 = OFF ; Table Write Protect 04000-07FFF (Disabled)
CONFIG WRT2 = OFF ; Table Write Protect 08000-0BFFF (Disabled)
CONFIG WRT3 = OFF ; Table Write Protect 0C000-0FFFF (Disabled)
CONFIG WRT4 = OFF ; Table Write Protect 10000-13FFF (Disabled)
CONFIG WRT5 = OFF ; Table Write Protect 14000-17FFF (Disabled)
CONFIG WRT6 = OFF ; Table Write Protect 18000-1BFFF (Disabled)
CONFIG WRT7 = OFF ; Table Write Protect 1C000-1FFFF (Disabled)
; CONFIG6H
CONFIG WRTC = OFF ; Config. Write Protect (Disabled)
CONFIG WRTB = OFF ; Table Write Protect Boot (Disabled)
CONFIG WRTD = OFF ; Data EE Write Protect (Disabled)
; CONFIG7L
CONFIG EBRT0 = OFF ; Table Read Protect 00800-03FFF (Disabled)
CONFIG EBRT1 = OFF ; Table Read Protect 04000-07FFF (Disabled)
CONFIG EBRT2 = OFF ; Table Read Protect 08000-0BFFF (Disabled)
CONFIG EBRT3 = OFF ; Table Read Protect 0C000-0FFFF (Disabled)
CONFIG EBRT4 = OFF ; Table Read Protect 10000-13FFF (Disabled)
CONFIG EBRT5 = OFF ; Table Read Protect 14000-17FFF (Disabled)
CONFIG EBRT6 = OFF ; Table Read Protect 18000-1BFFF (Disabled)
CONFIG EBRT7 = OFF ; Table Read Protect 1C000-1FFFF (Disabled)
; CONFIG7H
CONFIG EBRTB = OFF ; Table Read Protect Boot (Disabled)
__RESET_CODE code 0
nop
nop
goto ContinueCpuInitiation
;
__INTERRUPT_CODE code 8
retfie 1
ContinueCpuInitiation
movlw low Table0
movwf TBLPTRL
movlw high Table0
movwf TBLPTRH
movlw upper Table0
movwf TBLPTRU
;
tblrd *+ ; read into TABLAT and increment
movf TABLAT, W ; get data from Table0 = 1
tblrd *+ ; read into TABLAT and increment
movf TABLAT, W ; get data from Table0 = 2
tblrd *+ ; read into TABLAT and increment
movf TABLAT, W ; get data from Table0 = 3
;... end test
nop
__H code 0x10000
Table0
db 1,2,3,4,5,6,7,8
END
And test it in MPAB simulator, as you can see everything works fine...
Related
For example in linux-5.15.68's arch/arm64/boot/dts/ti/k3-am64-main.dtsi,
&cbass_main {
... skip ...
pcie0_rc: pcie#f102000 {
compatible = "ti,am64-pcie-host", "ti,j721e-pcie-host";
reg = <0x00 0x0f102000 0x00 0x1000>,
<0x00 0x0f100000 0x00 0x400>,
<0x00 0x0d000000 0x00 0x00800000>,
<0x00 0x68000000 0x00 0x00001000>;
reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
... skip ...
#address-cells = <3>;
#size-cells = <2>;
...skip ...
msi-map = <0x0 &gic_its 0x0 0x10000>;
ranges = <0x01000000 0x00 0x68001000 0x00 0x68001000 0x00 0x0010000>,
<0x02000000 0x00 0x68011000 0x00 0x68011000 0x00 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
};
};
the 'ranges' property says
IO space starting at address 0x68001000 with size 64KiB is mapped to the parent bus address 0x68001000.
a 32 bit memory address space starting with address 0x68011000 and size 0x7fef000 is mapped to parent bus address 0x68011000.
The device tree document says these addresses are all physical.
What I can't understand is :
I know the BIOS will set the BAR addresses during the enumeration process. This is allocating the endpoint's function to a certain PCIe bus address and I guess setting BAR can be done without this 'ranges' information(it will assign free address range for that device according to the device's need). By the time linux kernel later reads this 'ranges' property, the BIOS (or bootloader) has already assigned different PCIe address to that device. Then, how is this 'ranges' property used by the kernel?
I am adapting this bootloader for STM32F373CC to my device. To indicate that the device is powered but in bootloader mode, I'd like to turn on some of the status LEDs. However, this bootloader doesn't use the STM Cube MX libraries, so I have to code it low-level. The header file stm32f373xc.h is included, so I can use expressions like GPIOB_BASE.
I tried the following first thing in main(), but unfortunately it doesn't work:
// turn on GPIOB clock: SET_BIT(RCC->AHBENR, RCC_AHBENR_GPIOBEN);
uint32_t* rcc = (uint32_t*)RCC_BASE;
*(rcc+0x14) |= RCC_AHBENR_GPIOBEN; // AHBENR is at offset 0x14
// configure Port B, pins 4 and 5 to GPIO, Open Drain, low.
uint32_t* gpiob = (uint32_t*)GPIOB_BASE;
*(gpiob) |= 0x500; // GPIO output mode --- GPIOB_MODER = 0x500; (bits 11:8 = 0101), offset 0
*(gpiob) &= ~0xA00;
*(gpiob+0x04) |= 0x30; // output type open drain --- GPIOB_OTYPER = 0x30; (bits 5:4 = 11), offset 0x04
*(gpiob+0x0c) &= ~0xF00; // pull up/down off --- GPIOB_PUPDR = 0x0; (bits 11:8 = 0000), offset 0x0c
*(gpiob+0x14) &= ~0x30; // output low --- GPIOB_ODR = 0x0; (bits 5:4 = 00), offset 0x14
Any ideas what I'm missing? How can I find out if the problem is the clocking of the Port B, or the pin configuration?
I found this similar post, but the first answer requires the entire CMSIS, and the second answer lacks comments, so I don't fully understand what they are doing.
I hope that you know that open-drain outputs require pull-up (internal or external)
Use CMSIS definitions, not magic numbers and operations.
requires the entire CMSIS
And what is the problem? CMSIS does not add any overhead to your code, only handy definitions and inline functions, which do not change the size of the code if not used.
Also, HAL has very handy macros useful even if you do not use HAL library itself (it also will not increase the code size even by a single byte)
I will not check your magic offsets and numbers.
First error: after enabling the peripheral clock you need to wait. It is described in the Reference Manual. You do not wait and your first MODER operation has no effect. HAL macros read back the register to make sure that the operation has completed.
Example from STM32L4:
#define __HAL_RCC_GPIOB_CLK_ENABLE() do { \
__IO uint32_t tmpreg; \
SET_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \
/* Delay after an RCC peripheral clock enabling */ \
tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2ENR_GPIOBEN); \
UNUSED(tmpreg); \
} while(0)
Then use the CMSIS registers typedefs and definitions.
#define PIN4 4
#define PIN5 5
GPIOB -> MODER &= ~((0b11 << (2 * PIN5)) | (0b11 << (2 * PIN4)));
GPIOB -> MODER |= ((0b01 << (2 * PIN5)) | (0b01 << (2 * PIN4)));
GPIOB -> OTYPER &= ~((1 << PIN4) | (1 << PIN5));
GPIOB -> OTYPER |= (1 << PIN4) | (1 << PIN5);
GPIOB -> BSRR = (1 << (PIN4 + 16)) | (1 << (PIN5 + 16)); // set the pins low
I try to make master and slave stm32f103 (bluepills) communicate. But I am having trouble with receiving. When I connect my master to logic analyser I can see MOSI as in the picture
Logic Analyser
In the picture, MOSI is sending "Y" letter. But not all clock pulses same.(I don't know if this is the reason of communication fail)
here is my schematics and my code I simplified as much as I can.
Master Code:
int i;
RCC ->APB2ENR |= 0x00001004; //SPI1,GPIOA clock en
GPIOA ->CRL &= 0x00000000;
GPIOA ->CRL |= 0xb0b33333;
SPI1->CR1 = SPI_CR1_SSM| SPI_CR1_SSI| SPI_CR1_MSTR|SPI_CR1_BR_2;
SPI1->CR1 |= SPI_CR1_SPE; // enable SPI
while(1){
SPI1 -> DR = 'A';
for(int i = 0 ;i<400000;i++);
while( !(SPI1->SR & SPI_SR_TXE) ); // wait until transmit buffer empty
}
and Slave
int i;
RCC ->APB2ENR |= 0x0000100c; //SPI1,GPIOA,GPIOB clock en
GPIOB ->CRH &= 0x00000000;
GPIOB ->CRH |= 0x33333333;
GPIOA ->CRL &= 0x00000000;
GPIOA ->CRL |= 0x4b443333;
GPIOA ->CRH &= 0x00000000;
GPIOA ->CRH |= 0x33333333;
SPI1->CR1 = SPI_CR1_SSM| SPI_CR1_SSI| SPI_CR1_BR_2;
SPI1->CR1 |= SPI_CR1_SPE; // enable SPI
SPI1->CR1 &=~SPI_CR1_MSTR; //disable master
for(int c=0;c<5;c++){
LCD_INIT(cmd[c]);
}
while(1){
while( !(SPI1->SR & SPI_SR_RXNE));
char a = SPI1 ->DR;
for (i=0;i<400000;i++);
LCD_DATA(a);
for (i=0;i<400000;i++);
}
}
My Schematic:
Schematic
The problem is slave is not receiving any data.
It stucks in the loop while( !(SPI1->SR & SPI_SR_RXNE));
First, what are your HCLK and APB2 bus frequencies? If I'm not mistaken, you seem to use (fPLCK / 32) for SPI clock and your logic analyzer shows ~2 or 3 MHz clock. If your APB2 frequency is higher than the 72 MHz limit, you may experience clock problems.
In the slave, you use SSM (software slave management) and activate SSI (internal slave select). The name of the SSI bit is misleading: It mimics the physical NSS pin. So when SSI = 1, the slave is not selected. This is probably the reason why the slave ignores the incoming bytes.
My purpose is sampling signal by ADC channel with DMA data moving in STM32Fx board. Generate a square wave to ADC channel. If using DMA mode, some data is out of order or called mess. Same result happened on STM32F207 and STM32F373 board.
(1) When I collect converted data by using ADC EOC interrupt, the data array looks like a square wave. This is OK.
(2) I would like to try DMA circle instead of EOC IRQ, but the data array seems to mess up, some data missing or incorrect. It could worse if sampling rate was increasing. Below are my test results.
The picture shows my test result: EOC IRQ vs DMA circle mode
EOC IRQ vs DMA with sampling 62.5KHz The waveform in DMA became shorter.
The picture shows very worse DMA with sampling 200KHz The data on DMA mode mess up, but it's consistent by using ADC EOC IRQ.
enter code here
<<<< ADC config >>>>
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay =
ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 DeInit */
ADC_StructInit(&ADC_InitStructure);
/* Configure the ADC1 in continuous mode */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels 6 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1,
ADC_SampleTime_480Cycles);
ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);
#ifdef __DMA_ENABLE__
/* Enable DMA request after last transfer (Single-ADC mode) */
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
/* Enable ADC1 DMA since ADC1 is the Master*/
ADC_DMACmd(ADC1, ENABLE);
#else
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
ADC_ITConfig(ADC1, ADC_IT_OVR, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
#endif
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
<<<< DMA config >>>>
/* DMA1 clock enable */
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_DMA2, ENABLE );
/* DMA1 Channel1 Config */
DMA_DeInit(DMA2_Stream0);
DMA_DoubleBufferModeConfig(DMA2_Stream0, (uint32_t)ADCValB, DMA_Memory_1);
DMA_DoubleBufferModeCmd(DMA2_Stream0, ENABLE);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADCValA;
DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t) ADC1) + 0x4C;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = NUM_OF_ADC; // 512 buffer size
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA1 Channel1 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
Finally, I expect the result should be same as that using ADC EOC IRQ.
I have encountered the same problem, as a part of my complicated application, the ADC reads continuously an input PWM data and configured with DMA request in circular mode.
First, I tried to store the converted data in a memory buffer at each End Of Conversion Interrupt. This works well, so I am confident that the ADC is correctly converting the data.
Second, I started the ADC with DMA request in circular mode, (for each End Of Conversion Interrupt, the DMA handler get the ADC converted data and store in a memory buffer). At this stage, when I check the memory buffer via the Debugger - It seams that the data are messed and it's like the DMA was skipping values).
Third, I just wanted to verify, if it's a DMA problem or it's a Debugger one. I started the ADC with DMA request in "normal" mode. And all of a sudden, when opening the Debugger, the memory buffer data are correctly stored.
To summarize, the main difference between the second and the third method when opening the Debugger, is that the DMA handler is still running (in circular mode) and as a result the Debugger can't be able to show correctly the memory buffer data, due to the speed of the ADC conversion time/ DMA Handler requests (~1 µs). And in the other hand (in normal mode), the DMA handlers stops once it has completed filling the buffer.
To conclude, the DMA handler works fine and you can output the square wave with the DAC using your buffer. And if you want to view correctly the data using the Debugger you need to stop the DMA (after a period of time; for example).
HAL_ADC_Stop_DMA(&hadc);
Based on the tabular view of the data you provided, it appears that the DMA is configured properly as the data looks nearly identical to the data obtained from ADC EOC IRQ.
The only variable between relying on DMA and an IRQ is that there may be unexpected bus "collisions" between the DMA Controller and the CPU as, unlike when using an IRQ, they are both running concurrently, potentially resulting in wait states.
From the STM32 Reference Manual Section 13.4:
The DMA controller performs direct memory transfer by sharing the system bus with the Cortex-M4 ® F core. The DMA request may stop the CPU access to the system bus for some bus cycles, when the CPU and DMA are targeting the same destination (memory or peripheral).
And your observed sampling rate-dependent degradation in performance certainly corroborates this hypothesis, as the busmatrix must arbitrate more frequent accesses between the DMA Controller and the CPU.
Without seeing the rest of your code that sets up and reads from the buffer, it is hard to say what aspect of your application code may be causing this issue.
I'm trying to access the SysTick timer of Cortex-M3 so I've to switch to priviledged mode. I'm doing it as
/* Active previlige mode */
asm ("mov r0, #0x0");
asm ("msr control, r0");
asm ("ISB");
But it's not working because I'm unable to write the SYST_CSR register. Any exception entry is required to perform this operation if YES, how?
You cannot raise the mode to privileged directly from user mode (you can change to user mode direct from privileged mode). You have to do it via an SVC call (Supervisor call).
How you raise an SVC call will depend on your compiler if you do it in C, however in assembler you could use asm("svc, #1");
The #1 can be any number. This is made available to the SVC handler. If you want to only use the SVC handler for this purpose only then you don't need to decode the number in the handler and can simply use you assembly above to raise the privilege. However if you want to use the SVC for more than one purpose then you need to decode the number, so that #1 is for raising the privilege, #2 is for doing something else etc. The main thing to know here is that the SVC number will be on the stack you were using when the call was made (either the msp or psp). If you were only ever using one stack then it is easier. You will have to look up the stack frame in user guides.
So you need to Implement an SVC handler. You should be to find some examples on the web. There is a good example in the "Definitive Guide to ARM Cortex-M3 and Cortex M4" book.
Janathan Valvano has SysTick timer code example and other stuff at http://users.ece.utexas.edu/~valvano/arm/#Timer
; SysTickInts.s
; Runs on LM4F120/TM4C123
; Use the SysTick timer to request interrupts at a particular period.
; Daniel Valvano
; September 11, 2013
; This example accompanies the book
; "Embedded Systems: Introduction to ARM Cortex M Microcontrollers"
; ISBN: 978-1469998749, Jonathan Valvano, copyright (c) 2013
; Volume 1, Program 9.7
; "Embedded Systems: Real Time Interfacing to ARM Cortex M Microcontrollers",
; ISBN: 978-1463590154, Jonathan Valvano, copyright (c) 2013
; Volume 2, Program 5.12, section 5.7
;
;Copyright 2013 by Jonathan W. Valvano, valvano#mail.utexas.edu
; You may use, edit, run or distribute this file
; as long as the above copyright notice remains
;THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
;OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
;MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
;VALVANO SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
;OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;For more information about my classes, my research, and my books, see
;http://users.ece.utexas.edu/~valvano/
NVIC_ST_CTRL_R EQU 0xE000E010
NVIC_ST_RELOAD_R EQU 0xE000E014
NVIC_ST_CURRENT_R EQU 0xE000E018
NVIC_ST_CTRL_COUNT EQU 0x00010000 ; Count flag
NVIC_ST_CTRL_CLK_SRC EQU 0x00000004 ; Clock Source
NVIC_ST_CTRL_INTEN EQU 0x00000002 ; Interrupt enable
NVIC_ST_CTRL_ENABLE EQU 0x00000001 ; Counter mode
NVIC_ST_RELOAD_M EQU 0x00FFFFFF ; Counter load value
NVIC_SYS_PRI3_R EQU 0xE000ED20 ; Sys. Handlers 12 to 15 Priority
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
EXPORT SysTick_Init
; **************SysTick_Init*********************
; Initialize SysTick periodic interrupts, priority 2
; Input: R0 interrupt period
; Units of period are 1/clockfreq
; Maximum is 2^24-1
; Minimum is determined by length of ISR
; Output: none
; Modifies: R0, R1, R2, R3
SysTick_Init
; start critical section
MRS R3, PRIMASK ; save old status
CPSID I ; mask all (except faults)
; disable SysTick during setup
LDR R1, =NVIC_ST_CTRL_R ; R1 = &NVIC_ST_CTRL_R (pointer)
MOV R2, #0
STR R2, [R1] ; disable SysTick
; maximum reload value
LDR R1, =NVIC_ST_RELOAD_R ; R1 = &NVIC_ST_RELOAD_R (pointer)
SUB R0, R0, #1 ; counts down from RELOAD to 0
STR R0, [R1] ; establish interrupt period
; any write to current clears it
LDR R1, =NVIC_ST_CURRENT_R ; R1 = &NVIC_ST_CURRENT_R (pointer)
STR R2, [R1] ; writing to counter clears it
; set NVIC system interrupt 15 to priority 2
LDR R1, =NVIC_SYS_PRI3_R ; R1 = &NVIC_SYS_PRI3_R (pointer)
LDR R2, [R1] ; friendly access
AND R2, R2, #0x00FFFFFF ; R2 = R2&0x00FFFFFF (clear interrupt 15 priority)
ORR R2, R2, #0x40000000 ; R2 = R2|0x40000000 (interrupt 15 priority is in bits 31-29)
STR R2, [R1] ; set SysTick to priority 2
; enable SysTick with core clock
LDR R1, =NVIC_ST_CTRL_R ; R1 = &NVIC_ST_CTRL_R
; ENABLE SysTick (bit 0), INTEN enable interrupts (bit 1), and CLK_SRC (bit 2) is internal
MOV R2, #(NVIC_ST_CTRL_ENABLE+NVIC_ST_CTRL_INTEN+NVIC_ST_CTRL_CLK_SRC)
STR R2, [R1] ; store a 7 to NVIC_ST_CTRL_R
; end critical section
MSR PRIMASK, R3 ; restore old status
BX LR ; return
ALIGN ; make sure the end of this section is aligned
END ; end of file