Отговори на тема  [ 11 мнения ] 
CBS setup 
Автор Съобщение
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение CBS setup
http://mbed.org/users/igorsk/programs/DriverLibrary/601ro/docs/lpc17xx__uart_8c_source.html

Код:
/*********************************************************************//**
00216  * @brief        General UART interrupt handler and router
00217  * @param[in]    UARTx    Selected UART peripheral, should be UART0..3
00218  * @return        None
00219  *
00220  * Note:
00221  * - Handles transmit, receive, and status interrupts for the UART.
00222  * Based on the interrupt status, routes the interrupt to the
00223  * respective call-back to be handled by the user application using
00224  * this driver.
00225  * - If callback is not installed, corresponding interrupt will be disabled
00226  * - All these interrupt source below will be checked:
00227  *           - Transmit Holding Register Empty.
00228  *             - Received Data Available and Character Time Out.
00229  *             - Receive Line Status (not implemented)
00230  *             - End of auto-baud interrupt (not implemented)
00231  *             - Auto-Baudrate Time-Out interrupt (not implemented)
00232  *             - Modem Status interrupt (UART0 Modem functionality)
00233  *             - CTS signal transition interrupt (UART0 Modem functionality)
00234  **********************************************************************/
00235 void UART_GenIntHandler(LPC_UART_TypeDef *UARTx)
00236 {
00237     uint8_t pUart, modemsts;
00238     uint32_t intsrc, tmp, tmp1;
00239
00240     pUart = getUartNum(UARTx);
00241
00242     /* Determine the interrupt source */
00243     intsrc = UARTx->IIR;
00244     tmp = intsrc & UART_IIR_INTID_MASK;
00245
00246     /*
00247      * In case of using UART1 with full modem,
00248      * interrupt ID = 0 that means modem status interrupt has been detected
00249      */
00250     if (pUart == 1) {
00251         if (tmp == 0){
00252             // Check Modem status
00253             modemsts = LPC_UART1->MSR & UART1_MSR_BITMASK;
00254             // Call modem status call-back
00255             if (pfnModemCbs != NULL){
00256                 pfnModemCbs(modemsts);
00257             }
00258             // disable modem status interrupt and CTS status change interrupt
00259             // if its callback is not installed
00260             else {
00261                 LPC_UART1->IER &= ~(UART1_IER_MSINT_EN | UART1_IER_CTSINT_EN);
00262             }
00263         }
00264     }
00265
00266     // Receive Line Status
00267     if (tmp == UART_IIR_INTID_RLS){
00268         // Check line status
00269         tmp1 = UARTx->LSR;
00270         // Mask out the Receive Ready and Transmit Holding empty status
00271         tmp1 &= (UART_LSR_OE | UART_LSR_PE | UART_LSR_FE \
00272                 | UART_LSR_BI | UART_LSR_RXFE);
00273         // If any error exist
00274         if (tmp1) {
00275             // Call Call-back function with error input value
00276             if (uartCbsDat[pUart].pfnErrCbs != NULL) {
00277                 uartCbsDat[pUart].pfnErrCbs(tmp1);
00278             }
00279             // Disable interrupt if its call-back is not install
00280             else {
00281                 UARTx->IER &= ~(UART_IER_RLSINT_EN);
00282             }
00283         }
00284     }
00285
00286     // Receive Data Available or Character time-out
00287     if ((tmp == UART_IIR_INTID_RDA) || (tmp == UART_IIR_INTID_CTI)){
00288         // Call Rx call back function
00289         if (uartCbsDat[pUart].pfnRxCbs != NULL) {
00290             uartCbsDat[pUart].pfnRxCbs();
00291         }
00292         // Disable interrupt if its call-back is not install
00293         else {
00294             UARTx->IER &= ~(UART_IER_RBRINT_EN);
00295         }
00296     }
00297
00298     // Transmit Holding Empty
00299     if (tmp == UART_IIR_INTID_THRE){
00300         // Call Tx call back function
00301         if (uartCbsDat[pUart].pfnTxCbs != NULL) {
00302             uartCbsDat[pUart].pfnTxCbs();
00303         }
00304         // Disable interrupt if its call-back is not install
00305         else {
00306             UARTx->IER &= ~(UART_IER_THREINT_EN);
00307         }
00308     }
00309
00310     intsrc &= (UART_IIR_ABEO_INT | UART_IIR_ABTO_INT);
00311     // Check if End of auto-baudrate interrupt or Auto baudrate time out
00312     if (intsrc){
00313         // Clear interrupt pending
00314         UARTx->ACR |= ((intsrc & UART_IIR_ABEO_INT) ? UART_ACR_ABEOINT_CLR : 0) \
00315                         | ((intsrc & UART_IIR_ABTO_INT) ? UART_ACR_ABTOINT_CLR : 0);
00316         if (uartCbsDat[pUart].pfnABCbs != NULL) {
00317             uartCbsDat[pUart].pfnABCbs(intsrc);
00318         } else {
00319             // Disable End of AB interrupt
00320             UARTx->IER &= ~(UART_IER_ABEOINT_EN | UART_IER_ABTOINT_EN);
00321         }
00322     }
00323 }
00324
00325 /**
00326  * @}
00327  */



/*********************************************************************//**
01448  * @brief        Setup call-back function for UART interrupt handler for each
01449  *                 UART peripheral
01450  * @param[in]    UARTx    Selected UART peripheral, should be UART0..3
01451  * @param[in]    CbType    Call-back type, should be:
01452  *                         0 - Receive Call-back
01453  *                         1 - Transmit Call-back
01454  *                         2 - Auto Baudrate Callback
01455  *                         3 - Error Call-back
01456  *                         4 - Modem Status Call-back (UART1 only)
01457  * @param[in]    pfnCbs    Pointer to Call-back function
01458  * @return        None
01459  **********************************************************************/
01460 void UART_SetupCbs(LPC_UART_TypeDef *UARTx, uint8_t CbType, void *pfnCbs)
01461 {
01462     uint8_t pUartNum;
01463
01464     pUartNum = getUartNum(UARTx);
01465     switch(CbType){
01466     case 0:
01467         uartCbsDat[pUartNum].pfnRxCbs = (fnTxCbs_Type *)pfnCbs;
01468         break;
01469     case 1:
01470         uartCbsDat[pUartNum].pfnTxCbs = (fnRxCbs_Type *)pfnCbs;
01471         break;
01472     case 2:
01473         uartCbsDat[pUartNum].pfnABCbs = (fnABCbs_Type *)pfnCbs;
01474         break;
01475     case 3:
01476         uartCbsDat[pUartNum].pfnErrCbs = (fnErrCbs_Type *)pfnCbs;
01477         break;
01478     case 4:
01479         pfnModemCbs = (fnModemCbs_Type *)pfnCbs;
01480         break;
01481     default:
01482         break;
01483     }
01484 }
01485
01486 /*********************************************************************//**




Нещо не мога да вържа драйверите към вектора на прекъсване, Когато се опитвам да ползвам подонби драйвери, при влизане в прекъсване , вектора на прекъсването ме праща в някакъв безкраен цикъл даден по умолчание ... Как става в това ГЦЦ.

_________________
Вниманиене съмвишист....ИЙ.


Пон Авг 29, 2011 9:55 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: CBS setup
RM написа:
вектора на прекъсването ме праща в някакъв безкраен цикъл даден по умолчание ... Как става в това ГЦЦ.


Тоя цикъл да не би случайно да е fault exception ? :D

Като викаш функция при ARM най-младшия бит указва дали да се смени режима (thumb/arm).... от тук и "указател към функция" е малко подвеждащ.
Ако го ползваш като адрес за данни (както ти май го присвояваш към void*) се взема началния адрес на функцията.... И след това като го кастнеш до указател към функция компилатора няма откъде да знае каква е била функцията (arm или thumb). Всъщност разчита че му подаваш адрес + mode.


С две думи или не лъжи GCC с тайпкастове и не му крий типовете... или след като си го излъгал му добавяй 1 за thumb функции...


Пон Авг 29, 2011 10:17 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение Re: CBS setup
Това е драйвер за LPC17xx УАРТ.0.1.2. Предоставен е свободно от NXP.
До сега не съм го ползвал, по право почти не съм ползвал такива процесори, освен I2C с полиране на трансфера без прекъсване. Сега ми трябва една температура един ОУ с управляемо усилване, и то на и2с. Температурния датчик ще ми дава температура минимум през 100мс, и ще ми трябват прекъсванията на и2ц, или не мога да измисля трансвер с полиране към повече от 1 слейф без да замотам нещата.
В стартъп фаила имам
#pragma weak UART_IRQHandler = Default_Handler
след това
static void Default_Handler(void)
{
/* Go into an infinite loop. */
while (1)
{
}
}
Да .... и сега функцията за обработка на прекъсванията на УАРТ са ми в съвсем друг файл lpc17xx_uart.c
Ако направя така: :oops:
В началото на стартъп фаила
extern void UART_GenIntHandler (void); // въпреки че функцията има атрибути, може ли да е void
и след това...
#pragma weak UART_IRQHandler = UART_GenIntHandler

Как да вържа вектора UART_IRQHandler с обработката на прекъсванията UART_GenIntHandler във външен файл

_________________
Вниманиене съмвишист....ИЙ.


Вто Авг 30, 2011 1:03 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: CBS setup
досега не съм се занимавал с LPC а да почна аз едва ли ще ползвам техен код. Така че не мога а и не искам да вниквам какво правят те и какво правиш ти...

Това, което мога да помогна е принципни въпроси свързани с АРМ архитектурата и GCC. Единия проблем ти го казах с указателите към функции и тайпкастовете.
А другото нещо е WEAK атрибута - той може да се слага към произволен ликерски символ (функиция, глобална променлива и т.н.) Няма отношение към типа на нещото. Има отношение към линкването (свързването). Нормално при линкване ако се появят две дефиниции на нещо от един и същ тип се получава грешка. Но ако едно от нещата е WEAK няма да има грешка, то ще се игнорира и вместо него ще линкне и ползва другото нещо.

Идеята е не само да няма грешки, чрез WEAK може да се портва чужд код, без да се налага да пипаш из чуждите сорсове. Примерно (не знам дали е така при теб) може да имаш готов стартъп файл, в който има някакъв хендлър на UART. Може да го използваш тоя код така както си е и по подразбиране ще се ползва тоя хендлър в него. Но ако не те кефи и ако тоя хендлър е с WEAK атрибут ти може някъде другаде в твоя проект да направиш функция със същото име и тип, но без weak. При линкване ще се ползва твоята функция, а wеак-функциията ще изчезне. Забележи, че така може да подменяш функции, без да пипаш чуждите сорс файлове. Така ако утре излезе нова версия на чуждия файл - само си го копираш, без да се притесняваш че ще изгубиш твоите редакции...


Вто Авг 30, 2011 1:59 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение Re: CBS setup
С клизма ... проблема замазах така.

extern void UART_StdIntHandler(void); //Указах му че има външна


#pragma weak UART_IRQHandler = UART_Handler

в същия файл с нова функция викам extern-а която ми трябва
static void UART_Handler(void)
{
void UART_StdIntHandler(void);
}

:o една дивотия се замазва с две други ...

_________________
Вниманиене съмвишист....ИЙ.


Вто Авг 30, 2011 2:42 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: CBS setup
верно правиш дивотии ;-)

Значи в стартъп файла ти предполагам имаш векторна таблица, в която за uart-a вектора е UART_IRQHandler

Тъй като не се знае дали тоя стартъп код ще се ползва с uart или без, хората са ти сложили:

Код:
#pragma weak UART_IRQHandler = Default_Handler


Тая прагма създава weak символ UART_IRQHandler който сочи към Default_Handler, така стартъп файла ще може да се компилира при всякакви обстоятелства.
Има си вектор, има си и хендлът (дефаулта)....

От тук нататък най-логичното е ти да сложиш още сорс файл в който да има нормален/истински UART_IRQHandler без атрибути и без прагми. При свързване линкера ще види че имаш един нормален символ UART_IRQHandler и един weak. И навсякъде ще замести с нормалния.


Ти обаче правиш втори weak UART_IRQHandler, който сочи към UART_Handler..... Що??

Искаш да объркаш линкера и да се чуди кой от двата weak-а да ползва?


Вто Авг 30, 2011 4:17 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение Re: CBS setup
Малко бях зает но успях да си направя, комуникацията.
miro_atc , благодаря ти много. Не знам но ми харесват тези драйвери, притеснителното за мен е че са написани много професионално и трябваше да седна да разгледам много добре кода. Не е като CVAVR , CCS или микроелектроника. :cry: Отне ми 10-ки часове разучаване.

_________________
Вниманиене съмвишист....ИЙ.


Пет Сеп 02, 2011 10:53 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение Re: CBS setup
:D Искам да питам още нещо! Как наи-добре да си организирам достъпа до Read/Write array в предварително дефинирана в опциите на компилатора област.

_________________
Вниманиене съмвишист....ИЙ.


Съб Сеп 03, 2011 1:49 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: CBS setup
ммм... не съм убеден, че разбирам какво се опитваш да направиш :oops:

По принцип имаш препроцесор (CPP), компилатор (GCC) и линкер (LD). Това са три различни неща, всяко работи с различни понятия и си имат различни опции, макар че може да работиш само с GCC и да го накараш то индиректно да извиква останалите. В последния случай опциите наистина са на едно място, но въпреки всичко е добре да знаеш коя опция за кого де отнася.

Сега опции за дефиниране на array не знам да има. Не че знам всичко де, но мисля че няма такова животно ;-)
Има опция (-D) с която може да дефинираш символ - просто символ. Това е опция на препроцесора, т.е. може да имаш #ifdef примерно с тоя символ. Но пак подчертавам, че това няма връзка с типове и масиви на компилатора. Идеята на препроцесорните символи е по-скоро да си конфигурираш кода, примерно ако еди кой си символ е дефиниран да се компилира еди какво си...

опс... всъщност ти говориш за "област", която е дефинира в опциите на компилатора.. Е па такова животно хептен няма ;-)
Не знам за области... има "секции", но секциите не се дефинират в компилатора. На ниво компилация не е нужно и не се дефинират секции. Може само да кажеш кой обект в коя секция да бъде. Това става в сорса, не чрез опции.
Виж на линкера май може да му дефинираш секции чрез опции, макар че по-разумно е да се ползва скрипт файл. Но хайде първо кажи за какво иде реч, че да не гадая и да не обяснявам неща дето може и да не те интересуват....


Съб Сеп 03, 2011 5:24 pm
Профил
Ранг: Почетен член
Ранг: Почетен член
Аватар

Регистриран на: Нед Окт 19, 2008 7:26 pm
Мнения: 672
Мнение Re: CBS setup
Нещо съм в грешка :oops: Конфигурацийте са били за IROM IRAM1
Интересуваше ме използването на In-Application Programming (IAP)
за дефиниране на FRAM и записване на променливи в определена област от вътрешния flash (10к цикъла) или някъде го четох ЕЕПРОМ емулиране.
Въпреки че навсякъде не го препоръчват. Има го в един линкерски скрипт но за LPC2106.

_________________
Вниманиене съмвишист....ИЙ.


Съб Сеп 03, 2011 6:03 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 6:52 pm
Мнения: 11265
Местоположение: Добрич
Мнение Re: CBS setup
Това са съвсем основни неща дето е добре да се научат още преди да седнеш да работиш с GCC :P

Значи компилаторът прави от сорс файл т.н. обектен файл. Подаваш му един сорс файл (само един) и той "компилира" като резултатът от компилацията е списък с обекти, дето се записват в обектния файл. Обектите могат да са някакви глобални променливи, може да са финкции (код). Но важното в случая е компилаторът изобщо, ама изобщо не се интересува дали тия обекти ще разполагат в ROM, RAM, в EXE-файл, DLL, BIN или някакъв друг файл. Може и никъде да не се разполагат, ако не се ползват.... Но това се решава на един малко по-късен етап, наречен линкване...

Само да кажа, че компилаторът задава секция за всеки обект. Има няколко секции по подразбиране - за код (.text), за read only (.rodata, .init, .fini) данни и за read-write данни с инициализация (.data) и без инициализация (.bss). Секциите по подразбиране леко варират според версията на компилатора, езика Ц и Ц++ и т.н.
И другото което зависи от компилатора е дали всички обекти от даден тип да са в една секция, или за всеки да се прави отделна секция (виж -ffunction-sections -fdata-sections). Това последното е важно, понеже оптимизацията е на ниво секция. Ако нищо от дадена секция не се ползва се разкарва цялата секция, иначе остава цялата. Така че ако искаш неизползваните променливи и функции да се оптимизират, по-добре всеки обект да си е в отделна секция...

Сега линкерът.... На него му даваш списък с обектни файлове (и/или библиотеки) и му казваш какво да ти скалъпи от тях. За целта му се задават и някакви правила (обикновено линкер скрипт), чрез които му казваш "вземи тия обекти от тия файлове (входни секции) и ги сложи еди къде си (изходни секции)".
Едва при попълването на изходните секции се получават "някакви" адреси. Казвам някакви щото зависи какво точно се скалъпва, иначе адресите са малко виртуални. Секцията може да се разполага на един адрес в bin-файла (или каквото там се генерира) а пък после при зареждане в таргета да е на друг адрес.

Тъй... да се върнем на проблема..
Значиш имаш някакви FRAM, EPROM или каквито там памети искаш.... Тия памети са ти на опреден адрес и с определн размер и най-добре в линкерския скрипт да ги опишеш:

Код:
MEMORY
{
  rom (rx)   : ORIGIN = 0x00000000, LENGTH = 256k
  ram (rwx)  : ORIGIN = 0x20000000, LENGTH = 48k
  fram (rwx)  : ORIGIN = 0x30000000, LENGTH = 10k
//.....
}


После си описваш секциите:
Код:
SECTIONS
{

   .my_text_section :
   {
        KEEP(*(.ExceptionVectors))
      *(.text .text.*)
   } >rom
   

   .my_rodata :
   {
       
      *(.rodata .rodata*)
      
        KEEP(*(.init))
       KEEP(*(.fini))
     } > ram AT > rom

         // и така всички секции...

}


Забележи първата изходно секция my_text_section - в нея казвам да се сложат всички обекти от всички файлове (*) и входна секция ExceptionVectors. После цялата изходна секция се разполага в rom дето по-горе го дефинирахме... За подробности в синтаксиса може да прочетеш ръководството на LD ;-)

Te по тоя начин може да си правиш всякакви секции и да си ги разполагаш където и както си искаш... Остана само как в сорса да кажеш коя променлива/функция в коя секция да отиде (ако не искаш да е в секция по подразбиране):

Код:
extern "C" char * const MY_TABLE[] __attribute__ ((section (".ExceptionVectors")))  =
{
//.....


В случая масивчето ще отиде в моята секцийка ExceptionVectors, а тя пък ще отиде в началото на rom-а ...

Така може от група сорсове да генерираш един, два или повече изходни файлове с каквото съдържание искаш. Имаш контрол върху всичко, ограничен си само от фантазията и знанията си ;-) Ех, има и малко подводни камъни... но то къде ли ги няма ;-)


Съб Сеп 03, 2011 7:15 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 11 мнения ] 

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 0 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни