본문 바로가기
# Semiconductor/[Semicon Academy]

[Harman 세미콘 아카데미] 46일차 - STM32 Manual, Stack/Queue, ARM Setting, UART 송수신 방식(Polling, Interrupt, DMA)

by Graffitio 2023. 8. 30.
[Harman 세미콘 아카데미] 46일차 - STM32 Manual, Stack/Queue, ARM Setting, UART 송수신 방식(Polling, Interrupt, DMA)
728x90
반응형
[STM32 Manual]

 

Bus-Matrix

 

Bus-Matrix


I : 명령어 버스
D : 데이터 입출력용 버스
S : 시스템 Access 버스

 

ARM BA BUS
느린 애들을 빠른 버스에 물릴 필요 없으니,
속도를 두 개로 나눠놨다.

 


 

Memory Map

 

Peripheral에 대한 메모리 맵

bit banding -> 4bit씩 다뤄줘야 한다.

따라서 HAL 함수로 다 묶어놨음

HAL Drive 함수

 


 

Order Information

 

-40~125도짜리가 가장 좋다

 


 

Reference Manual

 

stm32f411re.pdf
1.82MB

 


 

[Stack / Queue]

 

기본 개념

 

<Stack>

Stack

스택의 입출력은 맨 위에서 이루어지며, 중간의 데이터 삭제가 불가능하다.

Stack에 저장되는 데이터 하나하나를 Element(요소)라 하며, 요소가 하나도 없을 때 Empty Stack(공백 스택)이라 부른다.

스택은 아래 그림처럼 같은 구조와 크기의 자료를 정해진 방향으로만 쌓을 수 있고 Top으로 정한 곳을 통해서만 접근이 가능하다. 또한 비어 있는 스택에서 요소를 추출하려 할 때를 Stack underflow, 스택이 넘치는 경우를 Stack overflow라 한다.

 

<Queue>

Queue

한쪽 끝에서는 삽입 작업, 다른 쪽 끝에서는 삭제 작업이 이루어진다.

삭제 연산이 수행되는 곳은 전단(Front), 삽입 연산이 수행되는 곳을 후단(Rear)이라 하며

접근 방법은 가장 첫 요소와 끝 요소로만 가능하다.

 

 

Stack vs Queue

 

Stack vs Queue

Stack Queue
연산 설명 예시 연산 설명 예시
Push 항목을 스택에 추가 스택에 1 추가 Enqueue 항목의 큐를
뒤쪽에 추가
큐에 1 추가
Pop 스택의 맨 위 항목을
제거하고 반환
스택에서 1 제거 Dequeue 큐의 맨 앞 항목을
제거하고 반환
큐에서 1 제거
Peek / Top 스택의 맨 위
항목을 조회
스택의 맨 위
항목 조회
Front 큐의 맨 앞
항목을 조회
큐의 맨 앞
항목 조회
IsEmpty 스택이 비어 있는지
확인
스택 비어있는지
확인
IsEmpty 큐가 비어있는지
확인
큐가 비어있는지
확인
Size 스택에 있는
항목의 갯수 조회
스택 크기 조회 Size 큐에 있는 항목의
갯수 조회
큐의 크기 조회
방식 LIFO(Last in, First Out) 방식 FIFO(First in, First Out)

 

Stack 예시

스택: 3 <- 7 <- 2 <- 9
Push(5) => 스택: 5 <- 3 <- 7 <- 2 <- 9
Pop() => 스택: 3 <- 7 <- 2 <- 9
Peek() => 3
IsEmpty() => False
Size() => 4

 

Queue 예시

큐: 4 <- 8 <- 1 <- 6
Enqueue(2) => 큐: 4 <- 8 <- 1 <- 6 <- 2
Dequeue() => 큐: 8 <- 1 <- 6 <- 2
Front() => 8
IsEmpty() => False
Size() => 4

 


 

[STM32 Setting]

 

 

 

 

 

 

외부 clock 사용

 

우리가 쓰는 STM32 보드 적정 전압은 3.3V

웬만하면 아두이노 핀맵 쓰지 말 것

 

 

 

32.768 이 것이 내부 클락

외부에 8M짜리 크리스탈 달려 있음 - 100MHz 까지 지원함.
내부 클락은 오차가 많다.

 

8M로 놓고 HSE로 놓고 MUX 나와서 뻥튀기 한 후 PLLCLK 선택

HCLK에 100 넣으면 알아서 Clock Configuration 실행함

 

APB1 Timer 클락과 Peripheral 클락은 서로 다른 것이므로 잘 구분할 것

 

아마 초기 셋팅은 8M말고 25M로 되어 있을 것이다.

이거 외부 클락이랑 안 맞춰주면 동기화 안 됨

 

Project Manager

 

여기 체크되면, Main 함수에 각 기능별로 파일 분할이 가능하도록 셋팅된다.

main에 다 박혀 있으면 결국 못 찾음

 

핀이 겹쳐있어서 사용 못한다.

 

 

아랫쪽에 하드웨어 셋팅

Middle Ware에 RTOS 들어갈 것

 

임베디드로 갈 거면 나만의 레이어드를 구축해야 한다.

어플리케이션 계층

 

UART async

 

 

DMA 생성

 

UART2에 대한 global Interrupt 허용

 


 

[STM32 폴링, 인터럽트, DMA 방식]

 

폴링(Polling) : 제어기가 상태 레지스터로 Busy 비트(1 : 바쁨, 0 : 명령받을준비)를 이용해 호스트가 반복적으로 소거될 떄 까지 Busy 비트를 검사한다. 즉, 매 주기마다 명렁어가 무엇인지 묻는 방식이다. CPU가 계속 Busy인지 아닌지 체크해야 되기 때문에 단한번의 폴링으로 끝나는 빠른 하드웨어 장치에선 효율적, 느린 하드웨어 장치에서 비효율적이다.

인터럽트(Interrupt) : CPU가 프로그램을 실행하는 중에 I/O 하드웨어 장치나 다른 예외 상황의 발생으로 인해 특별한 처리가 필요할 때 이를 알려 처리하도록 한다. 즉, CPU가 일일이 폴링하지 않고, 용건 있는 장치가 직접 요청을 통보하는 방식이다. 인터럽트가 발생하면 현재 CPU의 각종 레지스터와 상태를 저장하고, 미리 정의해 놓은 인터럽트 핸들링, ISR(Interrupt Service Routine)을 수행한 후 저장 했던 프로그램으로 돌아가 정상적으로 동작한다. 폴링과 대비된다.

DMA(Direct Memory Access) : CPU 간섭 없이 메모리와 하드웨어 장치 간의 데이터를 전송하다. DMA 명령 블록에 전송할 자료가 있는 곳의 포인터와 전송할 장소에 대한 포인터, 그리고 전송될 바이트 수를 기록한다. CPU는 이 블록 주소를 DMA에게 알려주고 다른 작업을 진행, DMA는 CPU 도움 없이 혼자 DMA 명령 블록에 접근해 입/출력을 수행한다.(할 일에 대한 위임장을 CPU가 DMA에게 위임) 끝나면 CPU에게 인터럽트를 건다. 그럼 CPU의 가용시간이 증가 해 보다 효율적이다.

 


 

tx_Data Interrupt

 

LED 20번 토글되면, tx_Data가 출력되도록 설정

 

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t tx_Data[2000];
int ledcount;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
//{
//	HAL_URAT_Transmit_IT(&huart2, tx_Data, sizeof(tx_Data));
//}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  for(int i = 0 ; i < 2000 ; i++)
  {
	  tx_Data[i] = 'x';
  }

  HAL_UART_Transmit_IT(&huart2, tx_Data, sizeof(tx_Data));
  HAL_Delay(200);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	  HAL_Delay(500);

	  ledcount++;
	  if((ledcount%20) == 0)
	  {
		  HAL_UART_Transmit_IT(&huart2, tx_Data, sizeof(tx_Data));
	  }

	  //HAL_UART_Transmit(&huart2, tx_Data, sizeof(tx_Data), 1000);
  }
  /* USER CODE END 3 */
}

 


 

HalfCallback

 

하프콜백UART인터럽트가 발생해 0~999까진 z가 채워지고,

출력을 완료 했을 때, 콜백UART인터럽트가 발생해 1000~2000까진 y가 채워진다.

마찬가지로 ledCount가 20배수 가 될 때 마다 해당 배열문자들을 출력한다.

 

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t tx_Data[2000];
int ledcount;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
//void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
//{
//	HAL_URAT_Transmit_IT(&huart2, tx_Data, sizeof(tx_Data));
//}

void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
{
	for(int i=0;i<1000;i++)
	{
		tx_Data[i] = 'z';
	}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	for(int i=1000;i<2000;i++)
	{
		tx_Data[i] = 'y';
	}
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
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();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */

  for(int i = 0 ; i < 2000 ; i++)
  {
	  tx_Data[i] = 'x';
  }

  HAL_UART_Transmit_DMA(&huart2, tx_Data, sizeof(tx_Data));
  // HAL_Delay(200);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	  HAL_Delay(500);

	  ledcount++;
	  if((ledcount%20) == 0)
	  {
		  HAL_UART_Transmit_DMA(&huart2, tx_Data, sizeof(tx_Data));
	  }

	  //HAL_UART_Transmit(&huart2, tx_Data, sizeof(tx_Data), 1000);
  }
  /* USER CODE END 3 */
}

 

 


728x90
반응형