라즈베리파이가 지원하지 않는 카메라 연결이 어려운 이유

12471 단어 EmbeddedEmbedded

Raspberry Pi 3B 모델에 PCAM5C 카메라를 연결하려고 디바이스 트리, 드라이버 수정해보았다.
도저히 안 붙는다 싶어서 파이카메라는 원래 어떻게 작동하였는지 알아보았음.

결과적으로 다른 카메라를 연결하는데는 실패하였지만
왜 안되는지 생각해보면서 작성한 글이다.

라즈베리파이 카메라 회로도 확인

아래는 핀과 케이블 규격이 호환되는 PCAM5C라는 제품(OV5640기반)을
PiCam과 비교하여 붙일 수 있는지 체크한 내용이다.

라즈베리파이 카메라 회로도

카메라가 받아오는 클럭의 소스를 라즈베리파이 AP가 아닌 카메라 보드 위의 24MHz 크리스탈에서 받아오고있다.

라즈베리파이 AP에서 받아올 수 있다면 디바이스드라이버나 트리수준에서 제어한 뒤에 클럭을 제어할 수 있어보인다..

PCAM5C 카메라 회로도 확인

회로도


12MHz 클럭을 보드에서 받아옴.

I2C, MIPI 핀맵 구성은 같다.

PCAM5C를 라즈베리파이의 CSI포트에 연결할 경우 클럭을 넣어줄 수 없음.

작동 방식을 분석하여 핀맵을 변경하던 드라이버를 수정하던 뭔가 진행해서 클럭을 따로 넣어줄 수 있는지 알아봐야 할 것 같음.

카메라 활성화

raspi-config 파일 분석

카메라를 사용하기위해 raspi-config의 camera enable 과정을 확인해보았다.
대체 뭘 했길래 카메라가 설정되는지 알고싶었기 때문에 raspi-config 스크립트를 열어보았고,
아래는 스크립트를 보면서 이해하는데 필요한 부분을 일부 발췌한 내용을 옮겨적었다.

:<<'HIDDEN_PARAMS'
  CONFIG=/boot/config.txt
  INTERACTIVE=True
  ...
HIDDEN_PARAMS

:<<'HIDDEN_METHODS'
  set_config_var() {
    lua - "$1" "$2" "$3" <<EOF > "$3.bak"
  local key=assert(arg[1])
  local value=assert(arg[2])
  local fn=assert(arg[3])
  local file=assert(io.open(fn))
  local made_change=false
  for line in file:lines() do
    if line:match("^#?%s*"..key.."=.*$") then
      line=key.."="..value
      made_change=true
    end
    print(line)
  end
  if not made_change then
    print(key.."="..value)
  end
  EOF
  mv "$3.bak" "$3"
  }

  get_config_var() {
    # lua script.
    lua - "$1" "$2" <<EOF
  local key=assert(arg[1])
  local fn=assert(arg[2])
  local file=assert(io.open(fn))
  local found=false
  for line in file:lines() do
    local val = line:match("^%s*"..key.."=(.*)$")
    if (val ~= nil) then
      print(val)
      found=true
      break
    end
  end
  if not found then
     print(0)
  end
  EOF
  }

  get_camera() {
    CAM=$(get_config_var start_x $CONFIG)
    if [ $CAM -eq 1 ]; then
      echo 0
    else
      echo 1
    fi
  }
HIDDEN_METHODS

do_camera() {
  # -e : if 조건; 해당 파일이 있으면 true
  # whiptail : 인터페이스 생성에 필요함.
  # start_x.elf 파일이 있는지 확인함.
  if [ ! -e /boot/start_x.elf ]; then  
    whiptail --msgbox "Your firmware appears to be out of date (no start_x.elf). Please update" 20 60 2
    return 1
  fi
  
  sed $CONFIG -i -e "s/^startx/#startx/"
  sed $CONFIG -i -e "s/^fixup_file/#fixup_file/"

  # whiptail option (default no)
  DEFAULT=--defaultno
  CURRENT=0
  
  # -eq 값이 같으면 참.
  # camera 못찾으면 0 그 이외에는 0이아닌 다른값.
  # 카메라 못찾으면 여기로 들어감.
  if [ $(get_camera) -eq 0 ]; then
      DEFAULT=
      CURRENT=1
  fi
  
  # 정상종료 : $?==0 / 실패 등 비정상종료 : $?==1
  if [ "$INTERACTIVE" = True ]; then
    whiptail --yesno "Would you like the camera interface to be enabled?" $DEFAULT 20 60 2
    RET=$?
  else
    RET=$1
  fi
  
  # 카메라 찾은경우
  # DEFAULT=--defaultno
  # CURRENT=0
  # 카메라 활성화 여부
  # 활성화; RET=0 / 비활성화; RET=1
  
  # 카메라 찾은 상태에서 활성화; 재부팅 플래그 활성화
  if [ $RET -eq $CURRENT ]; then
    ASK_TO_REBOOT=1
  fi
  
  # 카메라 활성화시
  if [ $RET -eq 0 ]; then
    
    # /boot/config.txt 내부의 start_x 속성 값을 1로 변경
    set_config_var start_x 1 $CONFIG
    
    # /boot/config.txt 내부의 gpu_mem 속성 값을 가져옴.
    CUR_GPU_MEM=$(get_config_var gpu_mem $CONFIG)
    
    # -z 문자열의 길이가 0이면 참
    # -n 문자열의 길이가 0이 아니면 참
    # -lt 값1 < 값2 , -le 값1 <= 값2
    # -gt 값1 > 값2 , -ge 값1 >= 값2
    
    # 받아온 gpu_mem 속성 값이 nil이거나 128보다 작을 경우
    if [ -z "$CUR_GPU_MEM" ] || [ "$CUR_GPU_MEM" -lt 128 ]; then
      # /boot/config.txt의 gpu_mem 속성 값을 128로 변경함.
      set_config_var gpu_mem 128 $CONFIG
    fi
    STATUS=enabled
    
  # 카메라 비활성화시
  elif [ $RET -eq 1 ]; then
    # /boot/config.txt의 start_x 속성 값을 0으로 변경
    set_config_var start_x 0 $CONFIG
    
    sed $CONFIG -i -e "s/^start_file/#start_file/"
    STATUS=disabled
    
  # undefined, 아무것도 안함.
  else
    return $RET
  fi
  
  # 활성/비활성 결과 메시지 보여줌.
  if [ "$INTERACTIVE" = True ]; then
    whiptail --msgbox "The camera interface is $STATUS" 20 60 1
  fi
}

raspi-config에서 Camera 활성화시 /boot/config.txt의 start_x와 gpu_mem 속성 값이 변경됨.

  • start_x 속성 값만 변경하여 카메라 활성여부를 체크함.
  • 부팅과정에서 /boot/config.txt 파일에 기록된 속성과 값들을 체크하여 시스템을 설정함.

config.txt는 뭘까?

config.txt는 뭘까?
Raspberry pi boot process

대략 GPU가 /boot/config.txt를 읽고나서 일련의 작업이 구성되고 CPU(및 OS)가 초기화 된다는 맥락인 것 같다.

카메라 활성 이후

커널 메시지 및 모듈 상태

  • i2c는 비활성화 상태
  • lsmod와 dmesg를 사용하여 i2c, ov56* 등의 키워드로 걸러봤을 때, 결과가 나오지 않음
  • 위의 상황인데 카메라가 작동하고있음

RPi의 VideoCore와 PiCam 사이에 뭔가 인터페이스가 있거나 직접 통신을 하거나 둘중 하나임.

VideoCore는 제어가 가능할까?

뭔가 있을 것 같아서 VideoCore이 주변 페리퍼럴에 어떤 상호작용을 하는지 알아보기 위해 블록 다이어그램을 찾았지만 못찾았다.

그러다가 포럼 게시물 하나를 읽게되었음.

이쯤되면 차라리 라즈베리파이를 안쓰고 카메라관련 프로세싱 과정이 오픈되어있는 다른 SBC를 사용 해 볼 생각도 든다.

비디오프로세싱 전용 코어가 있고 우린 그걸 제어할 수 없지..!

결론

내부 직원이 아닌이상 못하지않을까...

라즈베리파이의 부팅과정 중 GPU가 초기화되는 단계가 있고, 이 때 boot 파티션의 start_x.elf 파일에 있는 카메라 조작 관련 코드를 실행시킴.

근데 그 내용은 비공개 상태이며 앞으로도 공개될 가능성이 상당히 낮다.
(공식적으로 브로드컴과 라즈베리파이제단에서 공개하지 않는다고 하는 항목 중 하나)

심지어 이게 I2C 등으로 제어될 줄 알았는데 VideoCore에 직접 연결되어있다.

좋은 웹페이지 즐겨찾기