본문 바로가기
Embedded SW/Embedded SW Introduction

Flash Driver API 최적화 작업 2편(TC275 인피니언)

by 방구석 임베디드 2022. 9. 17.
반응형

이제 Flash Driver에 관련되어 어정도 매듭을 짓는 글을 쓰도록 하겠습니다.

 

지금 저는 인피니언 MCU TC275를 이용하여 

Flash Driver 예제 코드를 포팅하고

Flash를 Write, Erase 수행할수 있도록

API를 최적화 작업을 하고 있습니다.

 

이전글을 아래와 같이 첨부하오니

참고해 주시기 바랍니다.

Flash Driver 포팅 및 Erase, Write 동작 확인 정리 (TC275 인피니언 MCU)

Flash Driver Code, Flash 메모리 Reference Manual 분석 (TC275 인피니언)

Flash Driver API 최적화 작업 (TC275 인피니언)

 

앞글 예제로 저는

static uint32_t arry[24]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};

데이터를 쓸대 저는 32바이트의 배수로 데이터를 썼습니다.

하나의 Page가 32바이트로 구성이 되어 있기 때문에

한번에 32바이트씩 써지기 때문에

우선 32바이트로 써지는 예제를 한번 구현해 보았습니다.​

 

그러데 32바이트의 배수로 데이터를 구성하지 않을 경우도 있을 것입니다.

예를 들면 arr[22] 일때 이제 32바이트의 배수가 아닙니다.

API를 조금도 일반적으로 사용하기 위해서

이러한 부분도 호환하여 만들면 좋을 것 같스니다.

 

그러면 한번 Write해 보도록 하겠습니다.

한번 이데로 Write를 해보도록 할게요.

보이시나요?

page2 가  부분이 아예 써지지 않게 되었습니다.

따라서 아래 코드에서 마지막 단계에서

data가 남아있다면 이것을 Write하도록 설계해야 합니다.

static void PFlashProgram(uint32_t write_addr, uint32_t ori_addr, uint32_t size)
{
    uint32 offset;
    uint32 page;
    uint16 endinitSfty_pw;
    uint32_t no_of_pages = size/FLASHDEMO_PFLASH_PAGE_LENGTH;
    uint32_t* pDataAddress = (uint32_t*)ori_addr;
    uint32_t temp_addr;
    uint32_t temp = 0u;

    endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPasswordInline();

    temp = 0u;

    /* program the given no of pages */
    for (page = 0u; page < no_of_pages; ++page)
    {
        temp_addr = write_addr + page * FLASHDEMO_PFLASH_PAGE_LENGTH;
        g_Pflash.command.enterPageMode(temp_addr);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);

        /* write 32 bytes (8 doublewords) into assembly buffer */
        for (offset = 0; offset < FLASHDEMO_PFLASH_PAGE_LENGTH; offset += 8)
        {
            g_Pflash.command.loadPage2X32(temp_addr, pDataAddress[temp], pDataAddress[temp+1]);
            temp += 2u;
        }

        /* write page */
        IfxScuWdt_clearSafetyEndinitInline(endinitSfty_pw);
        g_Pflash.command.writePage(temp_addr);
        IfxScuWdt_setSafetyEndinitInline(endinitSfty_pw);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);
    }
}

위의 예제를 가지고 한번 설명해 보도록 하겠습니다.

32 + 32 + 24 바이트를 쓰려고 한다면

앞에 32 + 32 이렇게 2번밖에 써지지 않습니다.

 

따라서 24바이트를 다시 써야 하는데

그냥 쓰면 안되고

24바이트 + 8바이트

여기서 나머지 바이트는 0으로 채워주어야 합니다.

 

이유는 현재 Flash 구조상 32바이트씩 쓸수 있기 때문입니다.

 

한번 나머지 부분을 0으로 채우는 코드를 추가해 보도록 하겠습니다.

uint32_t rest_data_size = size % FLASHDEMO_PFLASH_PAGE_LENGTH;

코드를 추가하였고

24바이트가 reset_data_size로 나오게 되는 것을 확인할 수 있습니다.

for(i=0;i<rest_data_size/4u;i++)
{
	rest_data[i] = pDataAddress[temp];
	temp++;
}

그리고 rest_data 배열을 0으로 초기화하고

24바이트를 복사하면

우리가 원하는 32바이트의 배열이 만들어지게 됩니다!!

static void PFlashProgram(uint32_t write_addr, uint32_t ori_addr, uint32_t size)
{
    uint32 offset;
    uint32 page;
    uint16 endinitSfty_pw;
    uint32_t no_of_pages = size/FLASHDEMO_PFLASH_PAGE_LENGTH;
    uint32_t* pDataAddress = (uint32_t*)ori_addr;
    uint32_t temp_addr;
    uint32_t temp = 0u;
    uint32_t rest_data_size = size % FLASHDEMO_PFLASH_PAGE_LENGTH;
    uint32_t rest_data[8] = {0u,};
    int i;

    endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPasswordInline();

    temp = 0u;

    /* program the given no of pages */
    for (page = 0u; page < no_of_pages; ++page)
    {
        temp_addr = write_addr + page * FLASHDEMO_PFLASH_PAGE_LENGTH;
        g_Pflash.command.enterPageMode(temp_addr);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);

        /* write 32 bytes (8 doublewords) into assembly buffer */
        for (offset = 0; offset < FLASHDEMO_PFLASH_PAGE_LENGTH; offset += 8)
        {

            g_Pflash.command.loadPage2X32(temp_addr, pDataAddress[temp], pDataAddress[temp+1]);
            temp += 2u;
        }

        /* write page */
        IfxScuWdt_clearSafetyEndinitInline(endinitSfty_pw);
        g_Pflash.command.writePage(temp_addr);
        IfxScuWdt_setSafetyEndinitInline(endinitSfty_pw);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);
    }



    if(rest_data_size > 0u)
    {
        endinitSfty_pw = IfxScuWdt_getSafetyWatchdogPasswordInline();
        temp_addr = temp_addr +  FLASHDEMO_PFLASH_PAGE_LENGTH;

        for(i=0;i<rest_data_size/4u;i++)
        {
            rest_data[i] = pDataAddress[temp];
            temp++;
        }

        g_Pflash.command.enterPageMode(temp_addr);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);


        temp = 0u;

        /* write 32 bytes (8 doublewords) into assembly buffer */
        for (offset = 0; offset < FLASHDEMO_PFLASH_PAGE_LENGTH; offset += 8)
        {
            g_Pflash.command.loadPage2X32(temp_addr, rest_data[temp], rest_data[temp+1]);
            temp += 2u;
        }

        /* write page */
        IfxScuWdt_clearSafetyEndinitInline(endinitSfty_pw);
        g_Pflash.command.writePage(temp_addr);
        IfxScuWdt_setSafetyEndinitInline(endinitSfty_pw);

        /* wait until unbusy */
        g_Pflash.command.waitUnbusy(0u, g_Pflash.flashType);
    }
}

위의 코드를 잘 한번 살펴보세요 ㅎ

위의 코드가 바로, 32배수가 아닌경우에도 쓸수있도록 만든 API입니다.

물론 마지막 Page의 남는부분은 0으로 채워져 있기는 하지만요 ㅎㅎ

 

이제 한번 Flash Write를 수행해 보도록 하겠습니다.

우리가 원하는 arry[22]가 써지고 있는것을 확인할수 있스니다.

하나당 4바이트니까

22 x 4 = 88바이트가 써진것이 보이시나요?

그리고 나머지 8바이트는 그냥 0으로 채워진것이 보이시죠?

해당 코드는 아래 카페에서 다운로드 가능하오니 참고하시기 바랍니다.

https://cafe.naver.com/binaryembedded/149

 

이상으로 Flash Driver 포팅 및 최적화 작업을 맟치도록 하겠습니다.

반응형

댓글