single wire protocol

1 minute read

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 */
}

Updated: