Перейти к содержанию
    

kan35

Участник
  • Постов

    643
  • Зарегистрирован

  • Посещение

  • Победитель дней

    1

Весь контент kan35


  1. а разве знаковое число не двоично дополненное, 0x88 это же -120 то есть если даже знак продублируется, то должно получиться 0xFF78, но выходит 0xFF88... Получаются довольно смешные конструкции: ... = ((unsigned short)((unsigned char)x)) << 1; это если я хочу привести к 16 битному виду и сдвинуть на 1 разряд. То есть два раза подряд привожу тип, это же не должно быть так...
  2. Доброго всем дня! наткнулся на неожиданное поведение компилятора MCC18 (для PIC18), по нему значится как "ANSI '89 compatibility" Привожу тип и получаю разные результаты в зависимости...: signed char x = 0x88; unsigned short y = x; // y=0xFF88 unsigned short y = (unsigned short)x; // y=0xFF88 unsigned short y = (unsigned char)x; // y=0x0088 Ранее этот же кусочек кода работал в GCC/ARM, IAR AVR и всегда было unsigned short y = x; // y=0x0088 Я как человек старой закалки понимаю, что нужно было явно приводить тип, и даже самым надежным будет приведение через указатель в память, типа такого: unsigned short y = *(unsigned short *)&x; // y=0x0088 Но все таки, даже если делать просто приведение по умолчанию как y=x - что за результат-то такой 0xFF88? И почему приведение (unsigned char) делает как мне нужно, а (unsigned short) - опять странное 0xFF88. Это какая то особенность старого ANSI '89? как будто не логично это...
  3. Похоже я нашел таки проблему! И она в недостаточно подробной справке к порту или точнее недоисследованности ситуации с математикой. Да, я посмотрел в карте памяти MATH_DATA udata 0x000000 data 0x000010 .tmpdata udata 0x000010 data 0x00000c В моем случае сумма не 19 байт, а 28. И я как честный человек поменял portCOMPILER_MANAGED_MEMORY_SIZE с 19 на 28. И решил я поискать где этот макрос используется, обнаружил- что нигде кроме резервирования памяти и вот полез я в port.c. /* Store the .tempdata and MATH_DATA areas as described above. */ \ CLRF FSR0L, 0 \ CLRF FSR0H, 0 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF POSTINC0, PREINC1 \ MOVFF INDF0, PREINC1 \ MOVFF FSR0L, PREINC1 \ MOVFF FSR0H, PREINC1 \ Не разумею я этот птичий язык, но понимаю, что MOVFF POSTINC0, PREINC1 делается 19 раз, соответсвенно делалось и на Restore. Поэтому, добавил еще 9 строк MOVFF POSTINC0, PREINC1 и 9 строк соответственно в MOVFF POSTDEC1, POSTDEC0 И таким образом я наконец то, я надеюсь, что сохраняю и восстанавливаю математический контекст как надо! Надеюсь, ком нибудь будет полезно.
  4. Да, режим джедая это конечно хорошо, но все таки хотелось бы победить его, а не как сейчас - он победил меня. Вот, например мои утилиты работы со строками в карте памяти: .udata_string_my.o udata 0x000dae data 0x000000 .idata_string_my.o idata 0x000dae data 0x000000 то есть не занимают память вне стека. И вот так выглядит функция, которая "ошибается" при сравнении строк (если без критических секций): unsigned char strings_strcmpram2pgm (const char * str_pgm, rom const char * str_ram) { unsigned int ptr = 0; STRINGS_ENTER_CRITICAL(); while (str_pgm[ptr] == str_ram[ptr] && str_ram[ptr] != 0) { ptr++; } if (ptr && str_pgm[ptr] == str_ram[ptr] && str_ram[ptr] == 0) { STRINGS_EXIT_CRITICAL(); return 0; } STRINGS_EXIT_CRITICAL(); return 1; } (другие функции тоже ошибаются если что). В общем - что тут криминального, чего ему не хватает то - просто даже любопытно.
  5. Доброго дня всем! Еще один не понятный момент. Указано в справке к порту для PIC18 https://www.freertos.org/a00097.html что код компилятора C18 не реентрантный, в частности по 32 битной математике, и это отдельно решается, ок. В то же время я обнаружил, что стандартные функции типа strtsr, strcpy, memcpy и т д - тоже глючат если их в разных потоках вызывать, что значит, что они тоже не реентратные. Попробовал написать свои функции для работы со строками, и оказалось, что они получаются тоже не реентрантные, в итоге все их заключаю в критические секции и все работает нормально. Конечно использовать критические секции по этому поводу не хотелось бы, так как это потребует снижать скорости по последовательным портам, и накладывать прочие ограничения. Может быть кто сталкивался с такой вот проблемой нереентранности на PIC18 и C18 и есть какие-нибудь изящные решения...
  6. string_received это глобальный массив к сожалению и действительно, строки можно было бы передавать индексом в таком случае, но я решил сделать указателем. Это как раз на случай если массив в какой то момент сделаю динамическим.
  7. Именно, передаются указатели, я же так и написал в самом первом сообщении. Queue - это инструмент, который мне удобен, я передаю сигнал о готовности строки и другая задача просыпается и сразу получает указатель на эту строку. Обертка в данном случае это наиболее изящное решение, спасибо!
  8. Расползание темы в разные дебри не связанные с вопросом я всегда одобряю, так как это однозначно лучше молчания! Спасибо всем гуру. Не знаю, как так уже вышло, но я всегда объявлял массивы строк как char string_received[2][64]; В данном случае при обращении к строкам они лежат друг за другом в памяти, сперва string_received[0], потом string_received[1], каждая по 64.
  9. Не надо меня подозревать, пожалуйста 🙂 Мне так нужно и я так использую. Действительно на низкой оптимизации такое поведение меня не смутило бы. У меня оптимизация - максимальная.
  10. Вопрос, наверное, стоит закрыть. И данная псевдопроблема не имеет красивого решения, так как если бы в памяти выделилось место под указатель, то в принципе я бы эту память и потерял после этого. Придется иметь некий массив из временных указателей, спасибо разработчикам mcc18, если кому то интересно про эту фичу пиков почитать - вот здесь обсуждение, например https://forum.microchip.com/s/topic/a5C3l000000M2v4EAC/t241282 А, кстати, есть еще один компилятор от Микрочипа - XC8, может быть кто знает - есть ли в природе порт FreeRTOS под него? Может он попрямее будет, если уж его взяли на смену mcc18.
  11. Принимающая сторона ждет не char **, а char * 🙂 По сути - адрес строки в ОЗУ. xQueueTCPRxedString = xQueueCreate( 2, sizeof( char *) ); И да, при приеме из очереди мы сами назначаем тип: unsigned char * str_rcv; if (xQueueReceive(xQueueTCPRxedString, &str_rcv, 5000) == pdTRUE) { Спасибо за оправку в учебники, я, действительно, не эксперт по Си, поэтому и обращаюсь в благородным гуру! Мое мнение такое, что должна возникнуть переменная, в которой будет содержаться адрес строки. И потом эту переменную скормить в QueueSend, после чего переменная может и исчезнуть (и хорошо, если бы исчезла), это уже без разницы, так как её контент уже в queue. И как я уже сообщил ранее, если вручную её создать, то оно и работает, вопросов с этим нет. Но в силу того, что компилятор довольно кривой, он не чистит стек, если переменная не используется далее, то есть все временные переменные остаються в стеке. В итоге стек засоряется так быстро, что не успеваешь моргнуть, поэтому стараюсь писать чище. Кстати, стек под одну функцию в pic18 что то около 100 байт 🙂, в mcc18 к сожалению это не обходится, хотя я не понимаю, почему так они сделали. Компилятор даже такую ошибку выдает - "Стек заполнен"- такие дела... В общем, как мне видится, запись должна быть что-то в виде такого: xQueueSend(xQueueTCPRxedString, &((char *)string_received[0]), 0); Но компилятор не пропускает это, "Syntax error". Логично, что если делать как я ранее делал xQueueSend(xQueueTCPRxedString, string_received[0], 0); то в Queue попадает первые два байта строки, что в общем не то, то нужно. Кстати, если делать как jcxz предложил: xQueueSend(xQueueTCPRxedString, &string_received[0][0], 0); то в Quue попадают те же первые два байта строки, не?😎 Передавать в Queue &string_received[0][0] или string_received[0] или &string_received[0] - это всё одно и то же, но я проверил на всякий случай)) В общем, есть ощущение, что без промежуточной переменной не обойтись, как ни крути. Первый раз такое в Си мне встретилось, ранее считал, что все, что можно при желании можно уложить в одну строку кода.
  12. Доброго дня всем! Столкнулся с такой проблемой, надо передать строку через Queue. Скорее вопрос по Си, но все таки для FreeRTOS. Есть массив из строк: char string_received[2][64]; Я хочу передать указатель или на string_received[0] или на string_received[1]. Соотвественно, я делаю так: char * data; data = string_received[0]; xQueueSend(xQueueTCPRxedString, &data, 0); И это работает, все хорошо. А как бы мне не заводя новую переменную передать указатель? xQueueSend(xQueueTCPRxedString, &string_received[0], 0); - так не пойдет, а как правильно? PS: я бы может и не заморачивался сделать одной строкой, но как только я создаю переменную char * data, то я навсегда теряю память в стеке, то есть она не удалится после того, как она перестанет быть нужна, такой дурацкий компилятор у меня (mcc18 если что 🙂).
  13. О, спасибо, поймал байт!!! я про этот регистр и не знал, кстати на TX это не влияет почему-то. Всем огромнейшее спасибо за помощь, два дня потерял на поиски (думал, что в SPP что-то не так делаю), прежде чем спросить, и уже собирался перепаивать мк.
  14. Пока для упрощения я просто пытаюсь поймать хотя бы срабатывание. Вообще, изначально я прерывание сделал. Но оно не работало, и начал разбираться что происходит и такой простейший код написал. RX и TX тоже пробовал замыкать (модем выключал) - тоже ничего.
  15. Написал комментарии к инициализационному коду, чтобы выглядело опрятнее: unsigned short ulBaud; unsigned char dummy_byte; /* Calculate the baud rate generator constant. SPBRG = ( (FOSC / Desired Baud Rate) / 4 ) - 1 */ ulBaud = (unsigned short)(48000000l / ulWantedBaud); ulBaud /= ( unsigned short ) 4; ulBaud -= ( unsigned short ) 1; // IO pins setup TRISAbits.TRISA3 = 1; // RX as input TRISAbits.TRISA2 = 0; // TX as output // baudrate init BAUDCON1 = 0; // reset unwanted bits BAUDCON1bits.BRG16 = 1; // 16 bit BRR BAUDCON1bits.RXDTP = 0; // normal polarity for direct shifter switch SPBRG1 = ulBaud; // BR low byte SPBRGH1 = ulBaud>>8; // BR high byte // SPP-Lite setup //RPINR0_1 &= 0xF0; // write 0 to [3:0], RP3 to USART1_RX RPINR0_1bits.U1RXR = 0; //RPOR2_3 = (RPOR2_3&0xF0)|0x01; // RP2 to USART1_TX RPOR2_3bits.RPO2R = 0x1; // TX serup TXSTA1 = 0; // reset unwanted bits TXSTA1bits.TX9 = 0; // 9th bit disable TXSTA1bits.TXEN = 1; // transmitter enable TXSTA1bits.SYNC = 0; // anync mode TXSTA1bits.BRGH = 1; // high baud rate enable //RC setup RCSTA1 = 0; // reset unwanted bits RCSTA1bits.SPEN = 1; // UART enable RCSTA1bits.RX9 = 0; // 9th bit disable RCSTA1bits.CREN = 1; //continues receive mode // Interrupt setup // IPR1bits.RC1IP = 0; //serLOW_PRIORITY; // PIE1bits.RC1IE = 1; // IPR1bits.TX1IP = 0; //serLOW_PRIORITY; // PIE1bits.TX1IE = 1; Ошибки я тоже тестирую: while(1) { uart_send_string(line_at); //uart_send_data(line_at, 4); vTaskDelay(100); if (PIR1bits.RC1IF) { while(1) { Blink(); vTaskDelay(500); } } if (RCSTA1bits.FERR || RCSTA1bits.OERR) { while(1) { Blink(); vTaskDelay(50); } } } В этом цикле постоянно отправляется AT\r\n, в ответ модем сыпет ОК. Обе линии я проверяю виртуальным компортом и в терратерме вижу это всё хорошо. То есть такое ощущение складывается, как будто в UART вообще ничего не залетает. Еще, я не уточнил ранее подключение, модем подключен к линиям RA3 - прием, RA2 - передача в модем.
  16. Уважаемые коллеги, столкнулся с такой простой задачей и в силу того, что я новичок - не могу понять в чем проблема. К порту USART1 подключен модем. Передавать данные получилось довольно легко, а вот с приемом - никак. Настроил скорость - 115200, выдаю AT\r, в ответ летит ОК\r. И вот тут дальше - ни в какую. Инизиализиру так: TRISAbits.TRISA3 = 1; // RX as input RPINR0_1 &= 0xF0; // write 0 to [3:0], RP3 to USART1_RX RCSTA1 = 0; // reset unwanted bits RCSTA1bits.SPEN = 1; RCSTA1bits.RX9 = 0; RCSTA1bits.CREN = 1; Далее в цикле передачи проверяб флаг заполнености буфера приемника if (PIR1bits.RC1IF) {//И никогда сюда не попадаю. Анализатором на ножке данные вижу, они точно там есть и с ними все в порядке. Но флаг не взводится. Такое подозрение, что я неправильно как то сконфигурировал SPP_Lite на вход. Или что то не доделал, а что?.. С примерами в интернете довольно сложно по этому чипу... Заранее спасибо за подсказки!
  17. Driver_GV, Многократное спасибо за помощь и подсказки! Соответсвенно, я выбрал Legacy и скачал. Этот: правильно же? Или лучше старее брать? Действительно, нашел проект под USB-CDC VCP под PIC18F67J94. Открыл его в среде MPLAB-IDE 8.95. Однако ж он с ходу не собрался, к сожалению, воюю дальше. За ваш пример так же огромное спасибо. Но там нет файла проекта, а я пока без него не могу 🙂 Придется вручную собирать, чтобы попробовать
  18. Доброго дня всем. Нужен совет! Pадача у меня самая простая - сделать утилиту для конфигурирования устройства. Но столкнулся, что под этот камень конкретно не так много примеров и тем более с USB. В этой связи вопрос - USB на семействе PIC18 везде одинаковый? И у меня еще ограничение - компилятор MCC18 (так как часть приложения уже писана под него). В общем, порекомендуйте стек CDC/VCP, который не будет сложно портировать под PIC18F67J94. С уважением, Александр
  19. Update Оказалось, что опция "Enable Multi-bank stack model" Должна быть активна. То есть порт с сайта FreeRTOS.org вполне тоже рабочий. Только вот в нем не хватает файла-проекта под MPLAB X. Поисследовав файл проекта под MPLAB IDE нашел конфигурационную строку TS{C2AF05E7-1416-4625-923D-E114DB6E2B96}=-w3 -DMPLAB_PIC18F_PORT -Ls -Opa- -nw 2074 -nw 2066 И здесь опция -Ls как раз про это. Мне надо было внимательнее это прошерстить с самого начала, сэкономил бы день. Кстати, может ли меня кто-нибудь ткнуть носом - что эта опция дает? Я почему то думал, что она включает по-банковый доступ к памяти, а получается наоборот - банки объединает в один массив? или как? Я смотрел в документации Микрочипа, но там тоже нет объяснения для меня.
  20. Ну в общем, можно сказать победа. Наладил кое-как. Хотя до конца не понял что именно сделал, что оно заработало, сейчас буду искать что... Все таки работает НЕ в extended mode. В extended постоянно сваливается в ресет когда в первый раз восстанавливает контекст. Проект прикрепил, правда на старой версии FreeRTOS пока. Может быть кому то это будет полезно когда-нибудь. Если налажу современный официальный порт, я его выложу тоже. gitprj.X_good.zip
  21. Да, задачу поставил и не отступлю. С вашей помощью, конечно:-) Во FReeRTOS стеки под задачи выделяются из общей кучи. То есть 2кБ - 7*100 = 1.3кБ свободного места в куче. + обычный стек - 256 байт, и остается еще 1кБ свободного. Тут не так все плохо. Все таки оказалось, что прерывания срабатывают,однако происходит как я понимаю сброс контроллера при restore_context, тут что-то у меня с памятью. Даже вряд ли из за extended mode. Подскажите, как правильно его сконфигурировать, чтобы ОЗУ предсталов линейном виде? Я в опциях компилятора только вижу. При чем в обычном режиме выгоядит иначе, чем в extended. Обычный extended А в коде ничего нужно активировать? Или во фьюзах?
  22. Там стек каждой по сто байт, всего куча операционки - 2кб. Я согласен, что ресурсы ограничены, но у меня будет 5-7 задач, поэтому я в этом принципиально не сомневаюсь. Решил попробовать откомпилировать в extented mode, почему то в прерывание таймера не запрыгивает в таком варианте, почему такое может быть? Почему так пробую - в примерах c гита он включен. На сколько это может быть принципиально?
  23. Я все таки настроен на FreeRTOS, а порты доступны только для C18, поэтому на нем. Принял решение оставаться на MPLAB X. Опробовал официальный порт с сайна FreeRTOS, а так же старый пример с гитхаба (https://github.com/sybreon/freertos-pic18). И оба раза столкнулся со странной одинаковой проблемой. Во первых пришлось немного подкрутить настройку таймера 1, чтобы запустился системный таймер. static void prvSetupTimerInterrupt( void ) { const unsigned long ulConstCompareValue = ( ( configCPU_CLOCK_HZ / portTIMER_FOSC_SCALE ) / configTICK_RATE_HZ ); unsigned long ulCompareValue; unsigned char ucByte; /* Interrupts are disabled when this function is called. Setup CCP1 to provide the tick interrupt using a compare match on timer 1. Clear the time count then setup timer. */ TMR1H = ( unsigned char ) 0x00; TMR1L = ( unsigned char ) 0x00; /* Set the compare match value. */ ulCompareValue = ulConstCompareValue; CCPR1L = ( unsigned char ) ( ulCompareValue & ( unsigned long ) 0xff ); ulCompareValue >>= ( unsigned long ) 8; CCPR1H = ( unsigned char ) ( ulCompareValue & ( unsigned long ) 0xff ); CCP1CONbits.CCP1M0 = portBIT_SET; /*< Compare match mode. */ CCP1CONbits.CCP1M1 = portBIT_SET; /*< Compare match mode. */ CCP1CONbits.CCP1M2 = portBIT_CLEAR; /*< Compare match mode. */ CCP1CONbits.CCP1M3 = portBIT_SET; /*< Compare match mode. */ PIE3bits.CCP1IE = portBIT_SET; /*< Interrupt enable. */ /* We are only going to use the global interrupt bit, so set the peripheral bit to true. */ INTCONbits.GIEL = portBIT_SET; /* Provided library function for setting up the timer that will produce the tick. */ //OpenTimer1( T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_1 & T12_CCP1_T34_CCP2345 ); // timer 1 setup // Timerx clock source is the system clock (FOSC) T1CONbits.TMR1CS1 = portBIT_CLEAR; T1CONbits.TMR1CS0 = portBIT_CLEAR; // no prescaler (1:1) T1CONbits.T1CKPS1 = portBIT_CLEAR; T1CONbits.T1CKPS0 = portBIT_CLEAR; // Do not synchronize external clock input T1CONbits.NOT_T1SYNC = portBIT_SET; // 16 bit T1CONbits.RD16 = portBIT_CLEAR; // enable timer T1CONbits.TMR1ON = portBIT_SET; // init done signal LATG = 0b10; } Вроде все нормально, сделал выдачу клока на пин, и получил четкий сигнал 500Гц (1кГц системной частоты). Потом сделал две задачи для мигания каждая своим портом. #pragma config XINST=OFF #pragma config FOSC=PRIPLL #pragma config CLKOEN=OFF #pragma config IESO=ON #pragma config PLLDIV=PLL4X #pragma config POSCMD=HS static void vTask1(void *pvParameters) { while (1) { taskENTER_CRITICAL(); LATE ^= 0b01; taskEXIT_CRITICAL(); //vTaskDelay(1000); } } static void vTask2(void *pvParameters) { while (1) { taskENTER_CRITICAL(); LATE ^= 0b10; taskEXIT_CRITICAL(); //vTaskDelay(1000); } } /* * */ void main(void) { /* Power up Configuration*/ TRISE = 0xF0; TRISG = 0xFC; LATE = 0; LATG = 0; /* Create tasks */ xTaskCreate(vTask1, "T1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); xTaskCreate(vTask2, "T2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); /* Start the scheduler. Will never return here. */ vTaskStartScheduler(); return; } И тут должно было мне прийти счастье, но нет. Я получаю такую картинку: Дело в том, что на порту емкостная нагрузка, потому последовательность такая: 1мс вверху, потом 1мс генерация 300+кГц, потом 1мс внизу и так далее. На обоих задачах одно и то же. Как только раскомментирую vTaskDelay в задачах - перестает выдавать что-либо. Есть видимость, что многозадачность как то и работает, но что происходит не понятно - как будто задачи работают с нестабильной скоростью или как то так... задержки не работают совсем. Что может такое быть!? При чем как уже упомянут оба доступных примера работают одинаково. Моего кода в них практически нет. Что я упускаю? Приложил проект, может быть кому то будет любопытно взглянуть на это безобразие с виду простое. Всем спасибо за подсказки и помощь! gitprj.X.zip
  24. Я так понимаю, что в основном отладчиком никто не пользуется, тем более, что он требует особой сборки кода, что, конечно не может не настораживать. Да, не идеально работает на Pickit-3. В таком раскладе, действительно, есть смысл работать на MPLAB X, и отлаживаться строкам, тем более, что найти ICD2 в наше непростое время вряд-ли удастся. Вы написали про бутлодер- имеете в виду свой собственный бутлодер? или у микрочипа есть контроллеры с такими специальными бутлодерами с USB и т д?
  25. Установил 8.95. Действительно, симулятор на mcc заработал, это уже классно. А на какой версии будет работать дебагер?:-) Или ни на какой? update вообще то - отладка работает. Хоть и не без глюков. Например ставишь точку останова - запускаешь и оно крутится пока паузу не нажмешь и вот ты стоишь на точке останова. По шагам ходит. Все это в принципе уже радует!
×
×
  • Создать...