[STM32 Manual]
Bus-Matrix
I : 명령어 버스
D : 데이터 입출력용 버스
S : 시스템 Access 버스
ARM BA BUS
느린 애들을 빠른 버스에 물릴 필요 없으니,
속도를 두 개로 나눠놨다.
Memory Map
bit banding -> 4bit씩 다뤄줘야 한다.
따라서 HAL 함수로 다 묶어놨음
HAL Drive 함수
Order Information
Reference Manual
[Stack / Queue]
기본 개념
<Stack>
스택의 입출력은 맨 위에서 이루어지며, 중간의 데이터 삭제가 불가능하다.
Stack에 저장되는 데이터 하나하나를 Element(요소)라 하며, 요소가 하나도 없을 때 Empty Stack(공백 스택)이라 부른다.
스택은 아래 그림처럼 같은 구조와 크기의 자료를 정해진 방향으로만 쌓을 수 있고 Top으로 정한 곳을 통해서만 접근이 가능하다. 또한 비어 있는 스택에서 요소를 추출하려 할 때를 Stack underflow, 스택이 넘치는 경우를 Stack overflow라 한다.
<Queue>
한쪽 끝에서는 삽입 작업, 다른 쪽 끝에서는 삭제 작업이 이루어진다.
삭제 연산이 수행되는 곳은 전단(Front), 삽입 연산이 수행되는 곳을 후단(Rear)이라 하며
접근 방법은 가장 첫 요소와 끝 요소로만 가능하다.
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로 되어 있을 것이다.
이거 외부 클락이랑 안 맞춰주면 동기화 안 됨
여기 체크되면, Main 함수에 각 기능별로 파일 분할이 가능하도록 셋팅된다.
main에 다 박혀 있으면 결국 못 찾음
아랫쪽에 하드웨어 셋팅
Middle Ware에 RTOS 들어갈 것
임베디드로 갈 거면 나만의 레이어드를 구축해야 한다.
어플리케이션 계층
[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 */
}
'# Semiconductor > [Semicon Academy]' 카테고리의 다른 글
[Harman 세미콘 아카데미] 48일차 - ARM 및 RTOS 활용(RTOS, UART_rx, UART의 여러 가지 방식) (0) | 2023.09.01 |
---|---|
[Harman 세미콘 아카데미] 47일차 - ARM 및 RTOS 활용(Interrupt, DMA, PWM) (0) | 2023.08.31 |
[Harman 세미콘 아카데미] 45일차 - PSpice(LDO, Buck) (0) | 2023.08.29 |
[Harman 세미콘 아카데미] 44일차 - Embedded Project(선풍기 만들기 / ATmega128 / AVR) (2) | 2023.08.29 |
[Harman 세미콘 아카데미] 43일차 - ARM & RTOS 활용(Timer, EXTI, DMA) (0) | 2023.08.25 |