1. PC에 2개의 USB2Serial을 창작

 - COM3과 COM4로 인식됨

2. 2개의 USB2Serial을 크로스(Cross)로 연결

3. 연결이 잘 되는지 테스트

 - 2개의 PUTTY로 각각의 포트를 연결하여 테스트

 - Baudrate는 9600으로 동일

*** 여기까지 잘 됐으면 물리적인 연결은 제대로 되었음

 

4. VirtualBox를 구동한 다음 다음과 같이 설정

  - Ubuntu는 설치되어있다고 가정

5. VirtualBox의 시작버튼을 눌러서 VM을 시작한다. 

만약 윈도우 설정 시리얼 포트를 다른 프로그램이 사용중이면 VM이 시작되지 않는다.

(3번의 putty를 닫지 않아 발생한 문제임)

6. VM이 구동되고 나면 Ubuntu의 터미널을 실행하여 command를 입력한다

   > dmesg | grep tty

7. ttyS0가 나타난다.(만약 4번에서 COM2를 선택했으면 ttyS1이 보임)

 

8. stty -F /dev/ttyS0 명령을 보내면 포트정보를 알 수 있다.

  (여기서는  baudrate가 9600)

  * 참고로 "stty 115200 < /dev/ttyS0" 명령어는 baudrate를 바꿀 수도 있음

  cat /dev/ttyS0 명령어로 수신대기

9. 윈도우에서  putty로 COM3번 접속한다.

(3번과 4번은 연결되어 있고, 4번은 VirtualBox에서 쓰고 있기 때문에)

10. putty에서 텍스트를 입력한 다음 엔터를 치면 리눅스 터미널에서 보인다.

(우분투에서 시리얼 프로그램을 사용하면 엔터 안 치고도 보이고, 서로 주고 받을 수도 있다!!! 귀차니즘)

1. Ubuntu 서버 생성 및 접속 방법

https://onikaze.tistory.com/596

 

2. 관리자 계정으로 변경하기 위해서는

sudo su root

명령어로 root로 변경해야 한다.

 

3. 처음 접속 후 java 설치 방법

https://like-tomato.tistory.com/24

 

4. tomcat, mysql 설치

https://deftkang.tistory.com/60

 

5. 여유공간 확인 명령

df -hT /dev/xvda1

 

6. 기타 명령어들

https://all-record.tistory.com/182?category=733055

 

7. MySQL 외부 접속(사용자 생성 후 -user1- 외부접속 허용)

https://moomini.tistory.com/68

 

 

8. JSP 개발을 위한 설정들...

https://blog.lael.be/post/858

 

BootloaderUpdator.zip
0.03MB
TestBinary.zip
0.85MB
BootLoader.zip
1.12MB

제목이 너무 거창한가?

 

임알못(임베디드를 알지 못하는 인간)이 간단하게 테스트해 본 결과 돌아가길래 올려본다.

 

* 소스파일(2개)

 1) [C#]HEX파일을 읽어서 바이너리로 변환후 시리얼로 전달하는 프로그램(BootloaderUpdator.zip)

    (STM32가 구동되고 10초 안에 바이너리가 전달되어야 한다.

     그렇지 않으면 업데이트 되지 않고 메인 루틴으로 이동한다.)

 2) [STM32] 부트로더 프로그램(BootLoader.zip)

 3) [STM32] 메인 프로그램(TestBinary.zip)

 

 

 

1. 대상 CPU : STM32F765ZI

2. 소프트웨어 종류
1) Before : Main S/W (0x8000000)
2) After  : BootLoader S/W(0x8000000) + Main S/W(0x8010000)
   
3. STM32F765ZI_FLASH.ld 파일
1) Before

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
}


2) After
ㄱ) BootLoader 

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 64K
}

ㄴ) Main 

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx)      : ORIGIN = 0x8010000, LENGTH = 1984K
}



4. 바이너리 파일 : 시리얼을 통하여 hex파일을 읽어서 바이너리로 변경후 
   $FILE,NNN,BBBBB\r\n 
   형식으로 전달한다.
   > NNN : (가변크기)바이너리 크기
   > BBBBB : (가변크기)메인 프로그램 바이너리

5. 부트로더 프로그램
1) 부트로더 프로그램에서 다음 루틴을 통해 Main 프로그램으로 전달 가능하다.

void GoToApplication()
{
// Get the application stack pointer (First entry in the application vector table)
uint32_t appStack = (uint32_t) *((__IO uint32_t*)APPLICATION_ADDRESS);

// Get the application entry point (Second entry in the application vector table)
pFunction appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

// Reconfigure vector table offset register to watch the application bootloader
SCB->VTOR = APPLICATION_ADDRESS;

// Set the application stack pointer
__set_MSP(appStack);

appEntry();

// Infinite loop
while (1);
}


2) Main 프로그램 업데이트 순서
* 정의

#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 32 Kbyte */
#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08008000) /* Base @ of Sector 1, 32 Kbyte */
#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08010000) /* Base @ of Sector 2, 32 Kbyte */
#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x08018000) /* Base @ of Sector 3, 32 Kbyte */
#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08020000) /* Base @ of Sector 4, 128 Kbyte */
#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08040000) /* Base @ of Sector 5, 256 Kbyte */
#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08080000) /* Base @ of Sector 6, 256 Kbyte */
#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x080C0000) /* Base @ of Sector 7, 256 Kbyte */
#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08100000) /* Base @ of Sector 8, 256 Kbyte */
#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x08140000) /* Base @ of Sector 9, 256 Kbyte */
#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x08180000) /* Base @ of Sector 10, 256 Kbyte */
#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x08C00000) /* Base @ of Sector 11, 256 Kbyte */

 

 ㄱ) 플래쉬 Unlock

  void FLASH_If_Init(void)
  {
      HAL_FLASH_Unlock();//HAL 드라이브에 포함된 함수

      /* Clear pending flags (if any) */
      __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
                         FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR);
  }


 ㄴ) 플래쉬 Erase

uint32_t FLASH_If_Erase(uint32_t StartSector)
{
  uint32_t UserStartSector;
  uint32_t SectorError;
  FLASH_EraseInitTypeDef pEraseInit;

  UserStartSector = GetSector(APPLICATION_ADDRESS);

  pEraseInit.TypeErase = TYPEERASE_SECTORS;
  pEraseInit.Sector    = UserStartSector;
  /*
  Main 소프트웨어가 쓰여지기 위해서 2개의 블록이 쓰여진다.
  ADDR_FLASH_SECTOR_2, ADDR_FLASH_SECTOR_3
  0x08010000~0x0801FFFF
  
  */
  pEraseInit.NbSectors = 2; 
  pEraseInit.VoltageRange = VOLTAGE_RANGE_3;

  if (HAL_FLASHEx_Erase(&pEraseInit, &SectorError) != HAL_OK)
  {
 /* Error occurred while page erase */
 return (1);
  }

  return (0);
}


 
 ㄷ) 플래쉬 Write

if (FLASH_If_Write(APPLICATION_ADDRESS, (uint32_t*) &UpdateFileBuffer[StartPos], (EndPos - StartPos) / 4) == FLASHIF_OK)
{
//Success
}

//
uint32_t FLASH_If_Write(uint32_t FlashAddress, uint32_t* Data ,uint32_t DataLength)
{
  uint32_t i = 0;

  for (i = 0; (i < DataLength) && (FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)
  {
/* Device voltage range supposed to be [2.7V to 3.6V], the operation will
   be done by word */
if (HAL_FLASH_Program(TYPEPROGRAM_WORD, FlashAddress, *(uint32_t*)(Data+i)) == HAL_OK)
{
 /* Check the written value */
  if (*(uint32_t*)FlashAddress != *(uint32_t*)(Data+i))
  {
/* Flash content doesn't match SRAM content */
return(FLASHIF_WRITINGCTRL_ERROR);
  }
  /* Increment FLASH destination address */
  FlashAddress += 4;
}
else
{
  /* Error occurred while writing data in Flash memory */
  return (FLASHIF_WRITING_ERROR);
}
  }

  return (FLASHIF_OK);
}



 ㄹ) 플래쉬 Lock

HAL_FLASH_Lock();

uint8_t Flash_If_DeInit(void)
{
  /* Lock the internal flash */
  HAL_FLASH_Lock();
  return 0;
}


 ㅁ) 메인 프로그램쪽으로 이동한다.

GoToApplication()



hex 파일을 열어서 HexData 변수에 할당

 

        byte[] HexData = null;

 

        enum DATA_TYPE
        {
            HEX_FILE_DATA                    = 0x00,
            HEX_FILE_EOF                     = 0x01,
            HEX_FILE_EXTENDED_LINEAR_ADDRESS = 0x04,
            HEX_FILE_MAX
        };

        private void btnFileOpen_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string fileName = dlg.FileName;
                //MessageBox.Show(fileName);
                if (File.Exists(dlg.FileName))
                {
                    lblHexFilePath.Text = dlg.FileName;
                    UInt32 recordLength;
                    UInt32 addressField = 0;
                    UInt32 recordType;
                    byte   checksum;
                    byte   calc_checksum;
                    UInt64 extendedAddress = 0;
                    string dataPayload;

                    //HexData = File.ReadAllBytes(dlg.FileName);
                    //string strFileData = File.ReadAllText(dlg.FileName);

                    List bin_data = new List();
                    Stream stream = dlg.OpenFile();
                    using (StreamReader reader = new StreamReader(stream))
                    {
                        bool hexFileEOF = false;
                        string strLine = reader.ReadLine();
                        while (hexFileEOF == false)
                        {
                            strLine = strLine.Trim();
                            if (strLine.Length > 0 && strLine[0] == ':')
                            {
                                recordLength = StringToHex(ref strLine, 1, 2);
                                addressField = StringToHex(ref strLine, 3, 4);
                                recordType   = StringToHex(ref strLine, 7, 2);
                                dataPayload  = strLine.Substring(9, (int)(recordLength * 2));
                                checksum     = (byte)StringToHex(ref strLine, 1 + (recordLength * 2) + 8, 2);

                                calc_checksum = CalcCheckSum(ref strLine, 1, (recordLength + 4) * 2);
                                calc_checksum ^= 0xFF;
                                calc_checksum += 1;

                                

                                if (checksum == calc_checksum)
                                {
                                    switch((DATA_TYPE)recordType)
                                    {
                                        case DATA_TYPE.HEX_FILE_EXTENDED_LINEAR_ADDRESS:
                                            extendedAddress = StringToHex(ref dataPayload, 0, (uint)dataPayload.Length);
                                            break;
                                        case DATA_TYPE.HEX_FILE_EOF:
                                            hexFileEOF = true;
                                            break;
                                        case DATA_TYPE.HEX_FILE_DATA:
                                            {
                                                UInt64 totalAddress = (extendedAddress << 16) + addressField;

                                                for (uint i=0; i< dataPayload.Length; i+=2)
                                                {
                                                    bin_data.Add((byte)StringToHex(ref dataPayload, i, 2));
                                                }
                                                
                                            }
                                            break;
                                        default:

                                            break;
                                    }
                                }

                            }
                            strLine = reader.ReadLine();
                        }
                    }
                    if(bin_data.Count > 0 && extendedAddress != 0)
                    {
                        HexAddress = (UInt32)extendedAddress;
                        HexData    = bin_data.ToArray();
                    }
                }
            }
        }

        private byte CalcCheckSum(ref String s, uint index, uint len)
        {
            byte checksum = 0;
            byte data;

            for(int i=0; i<len; i+=2)
            {
                data = (byte)StringToHex(ref s, (uint)(index + i), 2);
                //checksum ^= data;
                checksum += data;
            }

            return checksum;
        }

        private UInt32 StringToHex(ref String s, uint index, uint len)
        {
            UInt32 returnAddress = 0;
            

            for(int i=0; i<len; ++i)
            {
                returnAddress *= 16;

                byte c = (byte)s[(int)(index + i)];
                if ((c >= 'A') && (c <= 'F'))
                {
                    returnAddress += (UInt32)(10 + (c - 'A'));
                }
                else if ((c >= 'a') && (c <= 'f'))
                {
                    returnAddress += (UInt32)(10 + (c - 'a'));
                }
                else
                {
                    returnAddress += (UInt32)(c - '0');
                }
            }
            return returnAddress;
        }

특정 사이트에서 취득한 패킷을 재생하기 위한 프로그램이 필요해서 구글링 하던 중...

 

https://www.darknet.org.uk/2007/03/preplay-a-pcap-network-traffic-replay-tool-for-windows/

 

사이트를 찾음..

 

1. 패킷을 보낼 PC와 받을 PC를 1:1로 연결한다.

 

2. 압축 해제(보낼 PC)

e:\work\preplay에 압축을 해제하면 Relese 폴더에서 파일을 찾을 수 있다.

3. ini 파일 수정(보낼 PC)

ini파일을 아래와 같이 수정합니다.

4. 파일 복사(보낼 PC)

e:\work\preplay\File 폴더에 pcap파일 복사

5. 실행화일(PacketSendingUtility.exe)을 실행해서 랜카드 선택한다.

 

 

preplay.zip
0.03MB

 

C#을 쓰다 안 쓰다가 하니깐.. 이런것도 헷갈리네.. -_-

 

1. WinForm(Form1)에다가 tab control 1개(tabControl), 버튼 3개(btnAddType1, btnAddType2, btnClose) 입력

 

2. WinForm을 2개 더 생성(Form2, Form3)

3. 다음과 같이 코딩

        private void btnAddType1_Click(object sender, EventArgs e)
        {
            Form2 form = new Form2();
            form.TopLevel = false;
            tabControl.TabPages.Add((tabControl.TabPages.Count + 1).ToString());
            tabControl.TabPages[tabControl.TabPages.Count - 1].Controls.Add(form);
            tabControl.SelectedIndex = tabControl.TabPages.Count - 1;
            tabControl.TabPages[tabControl.TabPages.Count - 1].Controls.Add(form);
            form.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            form.Show();
        }

        private void btnAddType2_Click(object sender, EventArgs e)
        {
            Form3 form = new Form3();
            form.TopLevel = false;
            tabControl.TabPages.Add((tabControl.TabPages.Count + 1).ToString());
            tabControl.TabPages[tabControl.TabPages.Count - 1].Controls.Add(form);
            tabControl.SelectedIndex = tabControl.TabPages.Count - 1;
            tabControl.TabPages[tabControl.TabPages.Count - 1].Controls.Add(form);
            form.WindowState = System.Windows.Forms.FormWindowState.Maximized;
            form.Show();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            if (tabControl.TabPages.Count > 0)
                tabControl.TabPages.Remove(tabControl.TabPages[tabControl.TabPages.Count - 1]);
            else
                MessageBox.Show("삭제할 탭이 없습니다");
        }

 

4. 테스트 : 추가 삭제 테스트

 

 

+ Recent posts