설명할 내용이 많아서 다음과 같이 3번에 나눠서 글을 써야겠네요.

1/3 : DFU-Bootloader 툴 설정
2/3 : DFU-Bootloader 프로그램 수정
3/3 : DFU-Bootloaderble APP 프로그램 수정

오늘은 1/3 : DFU-Bootloader 툴 설정 에 관해서 글을 써 보겠습니다.

STM32F4xx 중에서 제가 테스트한 MCU는 STM32F411 과 STM32F446 입니다.
두 디바이스 모두, DFU(Device Firmware Upgrade) 동작이 잘 됩니다.

DFU는 2가지 방법으로 구현을 할 수 있는데,
1. Embeded DFU mode : MCU 내부에 이미 들어있는 기능으로 평소에 JTAG로 동작하던 일반적인 펌웨어를 특정 Flash Memory 주소(0x08000000)에 다운로드할 수 있고,다음과 같은 특정한 핀 설정으로 진입한다. 초기 부팅 시 Boot1 핀은 PB2 핀과 기능을 공유한다.



2. Custom DFU Mode : MCU Flash 메모리에 User가 필요에 따라서 각종 DFU 진입 조건(사용자가 일반 핀입력이나 여러가지 조건으로 지정할 수 있다)과 APP Flash Memory 시작 주소를 수정할 수 있다. APP 프로그램의 설정을 수정해야 하는 번거러움이 있다.


제가 Embeded DFU를 사용하지 않고 Custom DFU를 사용하려 하는 이유는,
APP f/w 가 Flash MEM 의 최초 시작 주소부터 프로그램의 기능에 따라 늘어나는데, 얼마나 크게 만들어 질지 몰라서 
1. Flash data Memory(EEPROM Emulation 기능)를 위치시킬 주소를 정하기가 번거롭고,

여유롭게 뒤쪽에 있는 Sector에 data Flash를 위치 시키려고 보니,
뒤쪽으로 갈수록 Sector 당 Flash MEM 크기가 너무 큰 단위로 증가를 해서 버리는 메모리가 많았습니다.
Flash 메모리를 쓸려면 일단 Erase 해야 하는데, Erase 방법이 Setor 별로 지우던가 전체 메모리를 지워던가 2가지밖에 없었습니다.
그래서 또 다음과 같은 불합리한 문제가 있어서 Custom DFU를 사용하게 되었습니다.
2. 뒤로 갈수로 Sector 당 Flash MEM 크기가 증가하여 낭비되는 메모리가 많다.
3. Sector 당 메모리가 크면 1 sector를 지우는데 시간이 많이 걸린다.

STM32F411 과 STM32F446 은 플래쉬 메모리의 크기에 따라 2가지(256KB,512KB)로 나뉩니다.
그에 따른 Sector 구조는 다음과 같습니다.







Necleo 보드는 USB 콘넥터가 보드내에 없기 때문에 DFU 테스트를 위해서는 안쓰는 USB 케이블을 하나 잘라서 연결을 해야 합니다. 다음은 제가 만들어 붙인 USB 케이블 모습입니다.



이제 DFU를 테스트하기 위한 하드웨어는 다 준비가 됐기 때문에, CUBE-MX 툴로 프로그램을 만들어 보겠습니다.
예전에 쓴 글에 MCU 설정은 많이 나와 있으므로 바로 PINOUT 설정 내용을 그림으로 올리겠습니다.
1. DFU용 USB-FS 핀 2개
2. 외부 CLOCK 입력 핀 : 4개
3. 디버깅용 UART2(Necleo 보드의 JTAG IC에 의해 USB-to-UART 와 연결되어 있다)



클럭 설정은 USB를 사용하기 때문에 USB CLK 를 48MHz로 맞추다 보니, System Clk은 96MHz로 설정된다.
System Clk 에 STM32F411의 최대 클럭인 100MHz 를 입력하면 자동으로 최적의 클럭을 계산해 준다.





기본으로 위와 같이 Disable 로 설정이 안되어 있어서 얼마전에 Custom DFU가 안되는 줄 알고 한참 해멨는데, 주의해야 겠습니다.

 

다음으로 CUBE MX툴의 Config 탭의 USB DEVICE 버튼을 클릭해서 파라메터를 설정합니다.





여기서 눈여겨 볼 내용은 2가지 입니다.
1. USBD_DFU_APP_DEFAULT_ADD : 나중에 업로드할 APP f/w 의 Flash Memory Start Address 를 입력합니다.
Sector 단위로 구분하여 App f/w 를 위치시킬 Sector의 시작 주소를 넣어 줍니다. 저는 Sector 2 부터 사용하려고 0x08008000을 입력했습니다.
2. USBD_DFU_MEDIA Inteface : 부트로더 프로그램의 시작 주소와 각각의 메모리의 Sector 별 특징을 넣어 줍니다.
이 파라메터는 꽤 복잡하게 구성되어 있는데, 해당 입력란을 클릭하면 아래 설명이 나와 있습니다.

USBD_DFU_MEDIA Interface USBD_DFU_MEDIA Parameter Description: The description of the flash (used by PC tool DFuSe) Each Alternate setting string descriptor must follow this memory mapping so that the PC Host Software can decode the right mapping for the selected device: ● @: To detect that this is a special mapping descriptor (to avoid decoding standard descriptor) ● /: for separator between zones ● Maximum 8 digits per address starting by “0x” ● /: for separator between zones ● Maximum of 2 digits for the number of sectors ● *: For separator between number of sectors and sector size ● Maximum 3 digits for sector size between 0 and 999 ● 1 digit for the sector size multiplier. Valid entries are: B (byte), K (Kilo), M (Mega) ● 1 digit for the sector type as follows: – a (0x41): Readable – b (0x42): Erasable – c (0x43): Readable and Erasabled (0x44): Writeable – e (0x45): Readable and Writeable – f (0x46): Erasable and Writeable – g (0x47): Readable, Erasable and Writeable Note: If the target memory is not contiguous, the user can add the new sectors to be decoded just after a slash"/" as shown in the following example: "@Flash /0xF000/1*4Ka/0xE000/1*4Kg/0x8000/2*24Kg"

제가 위의 내용을 토대로 그림으로 좀 정리를 해 봤습니다.



이 파라메터는 나중에 DFU F/W Upgrade 툴인 DfuSe 프로그램에서 읽어서 사용하게 됩니다.
어떻게 사용되는지 미리 알아 보겠습니다.



다음은 DFU 모드로 들어가기위해, 여러가지 조건들을 만들어 넣을 수 있겠지만 Necleo 보드의 User 스위치를 누르면 진입하도록 GPIO 설정에서 핀내부 풀업해 줍니다. (스위치가 누르면 GND와 붙기 때문에)



인터넷에서 DFU 관련 사이트를 찾아보니 HEAP 크기를 늘려 주라고 되어 있었는데, 왜 그런지는 모르겠습니다.
예로써, 0x2000 크기를 Heap으로 잡아 놨던데, 실험 결과 0x800 만 잡아서 문제는 (아직까지) 없었습니다.
Heap 을 늘리면 RAM 의 ZI(Zero Initialize Data)가 늘어 나는 것이 차이라면 차이랄까?



여기까지 CUBE MX툴에서 할 일은 모두 끝났습니다.
다음 단계로 KEIL 컴파일러용 코드를 만들어서 JTAG로 프로그램을 다운로드하고 리셋을 눌러서 부트로더를 실행해서 윈도우의 장치관리자에서 STM Device in DFU Mode 가 뜨면 성공입니다.

아직 프로그램을 추가하고 수정해야 하지만, 이 상태로 STM Device in DFU Mode 가 떠야 그 다음으로 넘어갈 수 있습니다.





회사 일이 많이 바빠서 테스트는 다 했지만 글을 못 올리네요. 약간 설명할 내용이 많아서 시간을 내기가 더 힘든 것 같습니다.
곧 프로그램 수정방법도 올려 보겠습니다.

궁금하신 분은 KEIL 소스코드를 올려 놓을 테니, 미리 보고 공부하셔도 됩니다. ^^


다음의 소스 코드 첨부합니다.


며칠동안 STM32F446 으로 DFU Custom Bootloader 를 열심히 테스트해 봤는데,


결과는 안됐습니다.

STM32F446 은 기본으로 DFU 부트로더가 내장되어 있어서,
BOOT1,BOOT0 을 High로 하고 리셋을 하면 USB로 펌웨어를 다운로드 할 수 있고 동작을 확인해 봤습니다.

그런데 Custom으로 DFU를 구현하는데에는 실패했는데,
STM32F446 이 안되는 것 같습니다.

STM32F407 로 되는 소스를 중국 사이트에서 보고 그대로 했고, 구글 사이트에서도 보고 따라했는데..
다들 문제가 없는 것 같은데 잘 안되네요.

CUBE MX 툴로 프로그램을 하고 있는데, CUBE MX 툴이 다루기는 쉬운데 아직 버그가 많다고 합니다.

지난 번에도 STM32F446 으로 DMA mem to GPIO 를 동작 시키는 데에도 잘 안 됐던 것도 
제 생각에는 CUBE MX 툴이 의심이 갑니다.

다음번에 STM32F411로 한번 해 볼 예정입니다.


역시 CUBE MX 버그인 것 같습니다. 
STM32F411 에서는 똑같은 프로그램인데, DFU 모드로 진입합니다.
아.. 이거 언제 고쳐질런지. (mem-to-GPIO DMA 와 Custom USB DFU)

원인 찾았습니다. 죄송합니다. 아래 댓글에 그동안 안됐던 내용 적어놨습니다.
STM32F446 CUBE MX 툴 이상 없습니다. 내일이나 모레 DFU 부트로더 프로그램에 대한 내용을 다루겠습니다.


STM32F411에서 USB DFU 드라이버가 장치관리자에 설치된 화면은 다음과 같습니다.




STM32F411 에서는 SDIO DMA 로 SD-Card가 잘 읽혔습니다.


방법이 어렵지 않아서 금방 테스트가 끝났는데, STM32F446 에서는 DMA를 사용하면 f_mount() 함수에서 멈춰버렸습니다.
DMA를 사용할 경우 sd_diskio.c 의 SD_read 함수 내의 
BSP_SD_ReadBlocks() 함수를 BSP_SD_ReadBlocks_DMA() 함수로 바꿔주면 됩니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
  * @brief  Reads Sector(s)
  * @param  lun : not used
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT SD_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_OK;
  /*if(BSP_SD_ReadBlocks((uint32_t*)buff, 
                       (uint64_t) (sector * BLOCK_SIZE), 
                       BLOCK_SIZE, 
                       count) != MSD_OK)*/
  if(BSP_SD_ReadBlocks_DMA((uint32_t*)buff, 
                       (uint64_t) (sector * BLOCK_SIZE), 
                       BLOCK_SIZE, 
                       count) != MSD_OK)
  {
    res = RES_ERROR;
  }
  
  return res;
}
 
/**
  * @brief  Writes Sector(s)
  * @param  lun : not used
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT SD_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
  DRESULT res = RES_OK;
  /*if(BSP_SD_WriteBlocks((uint32_t*)buff, 
                        (uint64_t)(sector * BLOCK_SIZE), 
                        BLOCK_SIZE, count) != MSD_OK)*/
  if(BSP_SD_WriteBlocks_DMA((uint32_t*)buff, 
                        (uint64_t)(sector * BLOCK_SIZE), 
                        BLOCK_SIZE, count) != MSD_OK)
  {
    res = RES_ERROR;
  }
  
  return res;
}
cs


STM32F446 Nucleo 보드에서 DMA를 사용하지 않으면 동작은 잘 되는데, 
가끔 Error이 발생해서 SD-Card 와의 선을 짧게 하니 잘 동작 했습니다.
보드의 아트웍 영향인건지는 확실히 모르겠는데, 배선도 좀 짧으면 좋은 것 같습니다.



이 상태로 13KByte 의 데이터를 읽는데 10ms 정도의 시간이 걸렸으니 
거의 1MB/sec 의 속도밖에 안나와서 SDIO를 왜 쓰나 싶더군요.

그래서 처음부터 다시 프로젝트를 만들어서 동작을 시켜봤는데, 역시나 결과는 DMA 기능은 구현이 안되네요.

그런데, 뭔가 틀려진 점이 있는데, DMA를 안 썼을 때 13KB를 읽는데 10ms 걸렸던 것이 2ms 로 대폭 줄었습니다.
24KB를 읽었더니 3ms 고요. 마치 DMA가 동작되는 듯이 느껴질 정도로 빨라졌지만 DMA는 동작되지 않는 상황.
왜 빨라졌는지 원인은 못 찾았지만 CUBEMX 툴이 아직 안정화가 덜 됐나 봅니다.

빨라진 이유는 제가 코드를 잘 못 만들어서 그렇네요. f_read()함수가 512 Byte씩 읽어야 되는 줄 알고 24K 파일을 
512Byte 단위로 f_read()함수를 이용해 여러번 나눠서 읽었더니 느리고 한번에 24KB를 다 읽으니 빠르네요.
예전에 테스트를 했을 때, 512-Byte 이상 읽으면 안 읽혔었는데 이번에 해 보니 한번에 많은 데이터도 읽기 가능하네요. 

[512 Byte 씩 여러번 읽어서 느렸던 코드내용]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
uint8_t read_f_dat(uint8_t *pf_dat,FIL* fp)
{
    UINT i,testBytes;
    uint32_t f_size;
 
    f_size = 13000;
 
    // #define _MAX_SS 512
    
    for (i=0;i<f_size;i+=_MAX_SS)
    {
        if ((f_size - i) < _MAX_SS)
        {
            res = f_read(fp, &pf_dat[i],(f_size - i), &testBytes);
        }
        else
        {
            res = f_read(fp, &pf_dat[i],_MAX_SS, &testBytes);
        }
    }
}
cs

[한번에 많은 데이터를 읽어서 빨라지도록 수정된 코드]
1
2
3
4
5
6
7
8
9
uint8_t read_f_dat(uint8_t *pf_dat,FIL* fp)
{
    UINT testBytes;    
    uint32_t f_size;
 
    f_size = 13000;
    
    res = f_read(fp, &pf_dat[0],f_size, &testBytes);
}
cs

아뭏든 현재 첨부한 프로젝트는 DMA는 동작이 안되는 것으로 보이고, 계속해서 방법을 찾아보다가 
잘 되면 DMA SDIO-4bit 관련 글을 다시 올려 보겠습니다.


다음은 Nucleo - STM32F446 보드에서 DMA가 안되서 새로 프로젝트를 만들었던 과정입니다.

1. 먼저 MCU를 STM32F446로 선택하고, SDIO,UART2,GPIO 1개 출력(오실로 스코프로 시간이 얼마나 걸리는지 체크를 위해)



2. SDIO 신호와 u-SD-Card를 점퍼선으로 연결.



3. SDIO 를 DMA 로 동작하도록 CUBEMX 에서 설정.



4. sd_diskio.c 파일에서 SD_read/SD_write 함수 안의 BSP_SD_ReadBlocks/BSP_SD_WriteBlocks 함수를 바꾸지 않고 그대로 사용했는데 24KB 읽는데 걸리는 시간이 3ms 걸렸음.



5. 혹시 다 읽힌 것 맞는지 알아보려고 해리포터 소설을 UART로 뿌려보니 제대로 읽혀 있었습니다.
DMA가 동작한 것으로 믿어야겠죠? (제가 미쳤나 봅니다. 이런 상황을 가지고 DMA가 된다고 생각했다니.. 사기꾼이 될 뻔한 것을 글을 다시 보고 수정하면서 정정합니다.)
SDIO는 많은 양을 읽을수록 속도가 점점 더 빨라지는 듯 합니다.

그리고 STM32F411 은 42MHz 로도 DMA가 동작하는데, STM32F446 은 45MHz로 일반 방식에서는 동작하지 않았습니다.
(차후 DMA 구현되면 다시 비교해 볼 예정)

[STM32F4xx 에서 SDIO CLK를 최대(411:42MHz,446:45MHz)로 설정한 코드 내용]
1
2
3
4
5
6
7
8
9
10
11
12
/* SDIO init function */
static void MX_SDIO_SD_Init(void)
{
 
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 0;
}
cs

STM32F446 이 DMA가 안된 상태에서 비교를 하니 의미가 많이 없지만, 
또한 411은 SDIO_CLK=42MHz 이고 446은 22.5MHz 이기때문에, 
이 상태에서는 (당연하게도)STM32F411 이 더 빨랐습니다. 

STM32F446(SDIO_CLK:22.5MHz)은 13KB 읽는데 2ms, 24KB 3ms가 걸렸는데, 
STM32F411(SDIO_CLK:42MHz) 은 13KB/1.4ms , 24KB/2ms 밖에 안걸립니다. 

24KB 읽는 것을 기준으로 STM32F411 은 최대 속도 12MB/s , STM32F446 은 최대속도 8MB/s 나오네요.

이 속도는 앞서서도 말씀 드렸듯이 한번에 많이 읽으면 더 빨라집니다.

6. 해리포터 소설을 24KB 만큼 읽어서 출력해 봄.



7. main() 주요 동작 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
int main(void)
{
 
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration----------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SDIO_SD_Init();
  MX_USART2_UART_Init();
  MX_FATFS_Init();
 
  /* USER CODE BEGIN 2 */
    read_TAR_file_DMA();
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */
 
  /* USER CODE BEGIN 3 */
 
  }
  /* USER CODE END 3 */
 
}
 
/* SDIO init function */
static void MX_SDIO_SD_Init(void)
{
 
  hsd.Instance = SDIO;
  hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
  hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
  //hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_ENABLE;
  hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
  hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
  hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
  hsd.Init.ClockDiv = 0;
 
}
 
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 10);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  /* DMA2_Stream6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 20);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
 
}
 
/* USER CODE BEGIN 4 */
void read_TAR_file_DMA(void)
{
     #if _USE_LFN
    TCHAR lfn[_MAX_LFN + 1];
    fno_t.lfname = lfn;
    fno_t.lfsize = sizeof lfn;
    #endif
    
    BYTE testBuffer[24000];
   uint8_t path[13];            
 
    DWORD cnt_rd_Byte=24000;
  UINT testBytes;
    DWORD cnt_i;
    UINT i,cnt_512;
    uint32_t image_offset;
 
 
    //sprintf(path,"1.tar");
    sprintf(path,"aaa.txt");
    printf("%s\n\r",path);
    
    res_t = f_mount(&fs32_t,SD_Path,1);
    printf("SD Mount : res f_mount : %02X\n\r",res_t);
    res_t = f_open(&fil_t, (char*)path, FA_READ); 
    printf("res f_open : %02X, fil_t.fsize : %d\n\r",res_t,fil_t.fsize);
 
    printf("Read Txt File Test\n\r");
    
    GPIOB->ODR ^= GPIO_PIN_5;    
    res_t = f_read(&fil_t, testBuffer, cnt_rd_Byte, &testBytes);
    GPIOB->ODR ^= GPIO_PIN_5;    
    printf("res_t = f_read : %02X\n\r",res_t);
    
    for(i=0;i<24000;i++)
        printf("%c",testBuffer[i]);
}
 
/* USER CODE END 4 */
 
cs



추가로 DMA 인터럽트도 DMA 동작이 안되는 것과 관련이 있을 수도 있다 싶어서 인터럽트 설정 부분도 올려 봅니다.
혹시 왜 DMA가 안되는지 아시는분 알려주시면 대단히 고맙겠습니다.

아래와 같이 인터럽트를 여러가지로 변경해 봤는데, DMA 동작은 여전히 안됐습니다. 
그런데 DMA를 사용하지 않아도 SDIO_CLK 22.5MHz의 속도로써 늦은 속도는 아닌 것 같습니다.
(STM32F411 SDIO_CLK 42MHz(DMA)에서 13KB 전송시 1.4ms 이고, STM32F446 SDIO_CLK 22.5MHz(No DMA) 에서 2ms 걸렸기 때문에)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/** 
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 20);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  /* DMA2_Stream6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 30);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
 
static void MX_DMA_Init(void
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 10);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  /* DMA2_Stream6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 20);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
 
static void MX_DMA_Init(void
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();
  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 00);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
  /* DMA2_Stream6_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 00);
  HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
cs



다음의 소스코드 첨부합니다.

sdio_pure_v1.zip


+ Recent posts