stm32 base usage

2020-08-24

Contents

GPIO Write

cubeMX automatic generate initialization function of GPIo, then we use HAL_GPIO_WritePin


HAL_GPIO_WritePin(GPIOF,LED0_Pin,GPIO_PIN_SET);

GPIO Read

use HAL_GPIO_WritePin


GPIO_PinState pin_state = HAL_GPIO_ReadPin(GPIOE,KEY0_Pin);

NVIC of GPIO

set priority of NVIC in cubeMX, then write weak funcuion: HAL_GPIO_EXTI_Callback


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if(GPIO_Pin == GPIO_PIN_3)
	{
		if(KEY1_SET == 0 ){
			//...
		}else{
			//...
		}
	}
}

General TIM (TIM 2-5)

clock source of TIM2-5 is APB1, 84MHz

if we want to set TIM2 to 1Hz, then

APB1: clock source 84,000,000
PSC: /(84-1) 1,000,000
COUNTER: /(1,000,000-1) 1

Accurate delay using TIM

__HAL_TIM_SetCounter

__HAL_TIM_GetCounter

HAL_TIM_Base_Start

NVIC of TIM

config NVIC of TIM2 in cubemx, rewrite weak function, for example: HAL_TIM_PeriodElapsedCallback


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == TIM2)
	{
		//...
	}
}

do not forget to use HAL_TIM_Base_Start_IT, which stats the NVIC


    HAL_TIM_Base_Start_IT(&htim2); 

UART


    HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);

UART in swd

http://www.embedded-communication.com/en/misc/english-printf-using-st-link-debug-interface-swd-itm-view/

UART with DMA

###Transmit

    HAL_UART_Transmit_DMA(&huart1,tx_buffer,BUFFER_SIZE);

###Receive

first enable uart idle interupt

    __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);//idel
	__HAL_UART_CLEAR_IDLEFLAG(&huart1);
    HAL_UART_Receive_DMA(&huart2, UsartType2.RX_pData, BUFFER_SIZE);

define structure in main

#define BUFFER_SIZE 4096
typedef struct
{
uint8_t  RX_flag:1;        //IDLE receive flag
uint16_t RX_Size;          //receive length
uint8_t  RX_pData[BUFFER_SIZE]; //DMA receive buffer
}USART_RECEIVETYPE;

USART_RECEIVETYPE     UsartType2;

then rewrite the USART1_IRQHandler

    void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */

	uint32_t temp;

	if((__HAL_UART_GET_FLAG(&huart2,UART_FLAG_IDLE) != RESET))  // Checks whether the specified UART idle flag is set or not.
	{
		__HAL_UART_CLEAR_IDLEFLAG(&huart2);                                          // Clears the UART IDLE pending flag.
		HAL_UART_DMAStop(&huart2);                                                          // Stops the DMA Transfer.
		temp = huart2.hdmarx->Instance->NDTR;                                  // Read DMA stream x number of data register
		huart2.hdmarx->Instance->NDTR = 0;                                        // Clear DMA stream x number of data register
		int rx_len =  BUFFER_SIZE - temp;
		// Set RX_flag
		UsartType2.RX_Size =  BUFFER_SIZE - temp;
		UsartType2.RX_flag=1;                             // Set RX_flag
		HAL_UART_Receive_DMA(&huart2, UsartType2.RX_pData, BUFFER_SIZE);  // start DMA interrupt and receives an amount of data in non blocking mode.
	}



  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */



  /* USER CODE END USART2_IRQn 1 */
}

UART with DMA in STM32H743

注意在stm32h743 中,dma无法直接访问DTCMRAM中的内存,因此,需要将dma访问的变量定义在RAM_D2中,具体操作如下:

1. 修改ld文件

可以看ld文件中关于内存的分配:

MEMORY
{
    DTCMRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
    RAM_D1 (xrw)      : ORIGIN = 0x24000000, LENGTH = 512K
    RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 288K
    RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 64K
    ITCMRAM (xrw)      : ORIGIN = 0x00000000, LENGTH = 64K
    FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}

在sections中添加下面定义:

.dma_buffer : /* Space before ':' is critical */
{
	*(.dma_buffer)
} >RAM_D2

是添加dma_buffer定义,放入RAM_D2中。

2. 对dma访问的变量,添加定义__attribute__((section(“.dma_buffer”)))

uint8_t stringTest[1024] __attribute__((section(".dma_buffer"))); // 用于发送 32-align

typedef struct{
    uint8_t  RX_flag;        //IDLE receive flag
    uint16_t RX_Size;          //receive length
}USART_RECEIVE_TYPE;

extern USART_RECEIVE_TYPE UsartType4 ;
extern uint8_t RX4_pData[BUFFER_SIZE];

Uuint8_t RX4_pData[BUFFER_SIZE] __attribute__((section(".dma_buffer"))) ;// 用于接收 32-align

3. 在发送与接收操作前,添加 SCB_CleanInvalidateDCache_by_Addr

接收代码如下:

if((__HAL_UART_GET_FLAG(&huart4,UART_FLAG_IDLE) != RESET))  // Checks whether the specified UART idle flag is set or not.
  {
      __HAL_UART_CLEAR_IDLEFLAG(&huart4);// Clears the UART IDLE pending flag.
      HAL_UART_DMAStop(&huart4);// Stops the DMA Transfer.

      temp = ((DMA_Stream_TypeDef *)huart4.hdmarx->Instance)->NDTR;// Read DMA stream x number of data register
      ((DMA_Stream_TypeDef *)huart4.hdmarx->Instance)->NDTR = 0;
      int rx_len =  BUFFER_SIZE - temp;
      // Set RX_flag
      UsartType4.RX_Size =  rx_len;
      UsartType4.RX_flag=1; // Set RX_flag

      char string[1024];
      sprintf(string,"\n------\n%d\n------\n",rx_len);
      HAL_UART_Transmit(&huart4,string,strlen(string),0xffff);
      for (int i = 0; i < rx_len; ++i) {
          HAL_UART_Transmit(&huart4,&RX4_pData[i],1,0xffff);
      }
      SCB_CleanInvalidateDCache_by_Addr((uint32_t *)RX4_pData,BUFFER_SIZE+32); //重要
      HAL_UART_Receive_DMA(&huart4, RX4_pData, BUFFER_SIZE);  // start DMA interrupt and receives an amount of data in non blocking mode.
  }

发送代码如下:

	if(Uart4IsBusy==0){
        SCB_CleanInvalidateDCache_by_Addr((uint32_t *)stringTest,1024+32);
        HAL_UART_Transmit_DMA(&huart4,stringTest, strlen(stringTest));
        Uart4IsBusy = 1;
    }

注意重写发送完成回调函数:

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
    if(huart->Instance == UART4){
        Uart4IsBusy = 0;
    }
}

USB device

modify the usbd_storage_if.c



#define STORAGE_LUN_NBR                  1
#define STORAGE_BLK_NBR                  100
#define STORAGE_BLK_SIZ                  0x200

int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 6 */
	uint32_t n,i;
	
	for(n = 0; n < blk_len; n++)
	{
		for(i = 0; i < STORAGE_BLK_SIZ; i++)
		{
			buf[n*STORAGE_BLK_SIZ+i] = msc_data[blk_addr+n][i];
		}
	}
	
	
  return (USBD_OK);
  /* USER CODE END 6 */
}

int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
{
  /* USER CODE BEGIN 7 */
	uint32_t n,i;
	
	for(n = 0; n < blk_len; n++)
	{
		for(i = 0; i < STORAGE_BLK_SIZ; i++)
		{
			msc_data[blk_addr+n][i] = buf[n*STORAGE_BLK_SIZ+i];
		}
	}
	
	
  return (USBD_OK);
  /* USER CODE END 7 */
}


SD CARD

cubeMX

SDIO

DMA

NVIC


    HAL_SD_CardInfoTypeDef SDCardInfo1;
	
	HAL_SD_GetCardInfo(&hsd, &SDCardInfo1);
	
	printf(" Warning: this program may erase all the TF card data. \r\n");
     
	printf("\r\n Initialize SD card successfully!\r\n\r\n");
	printf(" SD card information! \r\n");
	printf(" BlockNbr	: %d \r\n",SDCardInfo1.BlockNbr);
	printf(" CardBlockSize : %d \r\n",SDCardInfo1.BlockSize);
	printf(" RCA           : %d \r\n",SDCardInfo1.RelCardAdd);
	printf(" CardType      : %d \r\n",SDCardInfo1.CardType);
	
	
	uint8_t Buffer_Tx[512];
	uint8_t Buffer_Rx[512];
	HAL_StatusTypeDef Status;
	
	int i = 0;
	memset(Buffer_Tx,0x15,sizeof(Buffer_Tx));
	
	
	/*------------------- Block Write --------------------------*/
    	
    if(HAL_SD_WriteBlocks_DMA(&hsd, Buffer_Tx, 0, 1) == HAL_OK)
    {  
            printf("\r\n Write block successfully! %d\r\n",sizeof(Buffer_Tx));
            for(i=0;i<sizeof(Buffer_Tx);i++)
            {
                    printf("%d:0x%08x ",i,Buffer_Tx[i]);
            }
            printf("\r\n");
            
    }
    else
    {
            printf("\r\n Write block fail!\r\n");
    }
    
    /*------------------- Block Read --------------------------*/
    if(HAL_SD_ReadBlocks_DMA(&hsd, Buffer_Rx, 0, 1) == HAL_OK)
    {
        printf("\r\n Read block successfully! %d\r\n",sizeof(Buffer_Rx));
        for(i=0;i<sizeof(Buffer_Rx);i++)
        {
                printf("%d:0x%08x ",i,Buffer_Rx[i]);
        }
        printf("\r\n");
        
    }
    else 
    {
            printf("\r\n Read block fail!\r\n");
    }				

fatfs

ref: https://zhuanlan.zhihu.com/p/27594211

first config sdio

config fats

    FATFS fs;                                              // fatfs
	FIL fnew;                                              // file
	FRESULT res_flash;                                     // result
	UINT fnum;                                             // size
	BYTE ReadBuffer[1024] = {0};                           // buffer
	BYTE WriteBuffer[5] = "12345";                         // buffer
	uint8_t work[2048];
	
	res_flash = f_mount(&fs, "", 1);                       //
	if(res_flash == FR_NO_FILESYSTEM)                      //
	{
			printf("no file system, begin to format...\r\n");
			res_flash = f_mkfs("", FM_FAT32, 0, work, sizeof work);
			if(res_flash == FR_OK)                             
			{
					printf("format success\r\n");
					res_flash = f_mount(NULL, "", 1);
					res_flash = f_mount(&fs, "", 1);
			}
			else
			{
					printf("format fail\r\n");
			}
	}
	else if(res_flash != FR_OK)
	{
			printf("FatFS mount fail(%d)\r\n", res_flash);
			while(1);
	}
	else
	{
			printf("FatFS mount success\r\n");
	}
	
	res_flash = f_open(&fnew, "FatFS.txt", FA_CREATE_ALWAYS | FA_WRITE);
	if(res_flash == FR_OK)
	{
			printf("open file success\r\n\r\n");
			res_flash = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum); 
			res_flash = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);
			res_flash = f_write(&fnew, WriteBuffer, sizeof(WriteBuffer), &fnum);
	}
	else
	{
		printf("open file fail !!!%d \r\n",res_flash);
	}

	f_close(&fnew);
	
	res_flash = f_open(&fnew, "FatFS.txt", FA_OPEN_EXISTING | FA_READ);
	if(res_flash == FR_OK)
	{
			printf("open file success\\r\n\r\n");
			res_flash = f_read(&fnew, ReadBuffer, sizeof(ReadBuffer), &fnum);
			if(res_flash == FR_OK)
			{
					printf(" file size: %d\n", fnum);
					printf(" data: %s\r\n\r\n\r\n", ReadBuffer);
			}
			else
			{
					printf("fail to readd data:(%d)", res_flash);
			}
	}
	else
	{
			printf("fail to open file\r\n");
	}

	f_close(&fnew);