single wire protocol
STM32F743ZI는 SWPMI 기능 있음.
-O0
69 static inline void delay_tenth_us(uint32_t tenth_us) {
delay_tenth_us:
0800071c: 0x000080b4 push {r7}
0800071e: 0x000085b0 sub sp, #20
08000720: 0x000000af add r7, sp, #0
08000722: 0x00007860 str r0, [r7, #4]
70 volatile uint32_t delay = tenth_us * 5;
08000724: 0x00007a68 ldr r2, [r7, #4]
08000726: 0x00001346 mov r3, r2
08000728: 0x00009b00 lsls r3, r3, #2
0800072a: 0x00001344 add r3, r2
0800072c: 0x0000fb60 str r3, [r7, #12]
71 while(delay--);
0800072e: 0x000000bf nop
08000730: 0x0000fb68 ldr r3, [r7, #12]
08000732: 0x00005a1e subs r2, r3, #1
08000734: 0x0000fa60 str r2, [r7, #12]
08000736: 0x0000002b cmp r3, #0
08000738: 0x0000fad1 bne.n 0x8000730 <delay_tenth_us+20>
72 }
0800073a: 0x000000bf nop
0800073c: 0x000000bf nop
0800073e: 0x00001437 adds r7, #20
08000740: 0x0000bd46 mov sp, r7
08000742: 0x5df8047b ldr.w r7, [sp], #4
08000746: 0x00007047 bx lr
-O3
==
최적화 옵션을 사용한 경우, 아래와 같이 굉장히 간결한 코드가 생성됨
171 delay_tenth_us(10);
0800086a: 0x00000299 ldr r1, [sp, #8]
0800086c: 0x00004a1e subs r2, r1, #1
0800086e: 0x00000292 str r2, [sp, #8]
08000870: 0x00000029 cmp r1, #0
08000872: 0x0000fad1 bne.n 0x800086a <main+78>
캐쉬에 의한 문제인지 확인했으나, 캐쉬는 기본값이 disable임. 아래 코드를 -O0 (Disable Optimization) 옵션으로 컴파일하여 실행
uint32_t val1, val2;
uint32_t start1, end1;
volatile int r=0, g=0, b=0;
volatile int val=0, inc_mode=1, mode=0;
static inline void delay_0p35us(int src) {
__asm volatile(
" push {r0} \n"
" movs r0, %0 \n"
"1: subs r0, r0, #1 \n"
" cmp r0, #0 \n"
" bne.n 1b \n"
" pop {r0} \n"
:
: "r" (src)
);
}
//#define SET_PIN HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_SET)
//#define RESET_PIN HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_RESET)
#define SET_PIN {GPIOE->BSRR = GPIO_PIN_9;}
#define RESET_PIN {GPIOE->BSRR = GPIO_PIN_9<<16;}
static inline void init() {
SET_PIN;
}
static inline void reset() {
RESET_PIN;
delay_sub_us(4000);
// SET_PIN;
}
// high-0.35us, low-0.8us
static inline void send_zero(void) {
SET_PIN;
// delay_sub_us(3); // 0.35us
// __asm volatile(
// " nop \n" // 한개만 있을 때 0.18us
// " nop \n" // 두개 있을 때, 0.22us
// " nop \n" // 세개 있을 때,0.22us
// " nop \n" // 0.23us
// " nop \n" // 0.23us
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n"
// " nop \n" // 0.25us
// );
delay_0p35us(50); //
RESET_PIN;
// delay_sub_us(20); // 0.8us
delay_0p35us(140);
}
// high-0.7us, low-0.6us
static inline void send_one(void) {
SET_PIN;
// delay_sub_us(20); // 0.7us
delay_0p35us(150);
RESET_PIN;
// delay_sub_us(8); // 0.6us
delay_0p35us(80);
}
void set_color(int r, int g, int b) {
reset();
// g
volatile int mask = 0x80;
while(mask) {
if(g & mask) send_one();
else send_zero();
mask >>= 1;
}
// r
mask = 0x80;
while(mask) {
if(r & mask) send_one();
else send_zero();
mask >>= 1;
}
// b
mask = 0x80;
while(mask) {
if(b & mask) send_one();
else send_zero();
mask >>= 1;
}
SET_PIN;
}
/* 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 */
HAL_MPU_Disable();
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
SysTick_Config(SystemCoreClock / 1000);
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM1_Init();
MX_ETH_Init();
/* USER CODE BEGIN 2 */
/*
* 타이머를 동작시키면 LED가 안 켜짐
*/
// HAL_TIM_Base_Start_IT(&htim1);
// HAL_TIM_Base_Start(&htim1);
/* USER CODE END 2 */
/* Init scheduler */
// osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */
// MX_FREERTOS_Init();
/* Start scheduler */
// osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
start1 = htim1.Instance->CNT;
delay_0p35us(300);
// delay_tenth_us(10);
end1 = htim1.Instance->CNT;
set_color(0, 0, 0);
set_color(0, 255, 0);
__disable_irq();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
// HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
// HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
// HAL_Delay(1000);
// __disable_irq();
// val1++;
// __enable_irq();
// exp1
// set_color(255, 0, 0);
// delay_sub_us(50000000L);
// set_color(0, 255, 0);
// delay_sub_us(50000000L);
// set_color(0, 0, 255);
// delay_sub_us(50000000L);
// exp2
// if(val > 256) { inc_mode = 0; }
// else if (val < 0) { inc_mode = 1; }
// if(inc_mode == 0) { val--; }
// else { val++; }
// r = (val % 256);
// g = (val+ 80) % 256;
// b = (val+160) % 256;
// set_color(r, g, b);
// delay_sub_us(500000L);
// exp3
switch(mode)
{
case 0:
r = 255-val;
g = val;
b = 0;
if(++val >= 256) {
mode = 1;
val = 0;
}
break;
case 1:
g = 255-val;
b = val;
r = 0;
if(++val >= 256) {
mode = 2;
val = 0;
}
break;
case 2:
b = 255-val;
r = val;
g = 0;
if(++val >= 256) {
mode = 0;
val = 0;
}
break;
}
set_color(r, g, b);
delay_sub_us(500000L);
}
/* USER CODE END 3 */
}