Implementation of Interrupt Allocation

usulrasolas
Posts: 26
Joined: Tue Jun 09, 2020 5:27 pm

Re: Implementation of Interrupt Allocation

Postby usulrasolas » Sun Jul 12, 2020 12:28 am

This felt weird but worked?
  1. void iram_attr scan_semaphore(){
  2. fast_command(FAST_ADC_START);
  3. vTaskDelay(40 / portTICK_PERIOD_MS);
  4.     for(int i=0;i<17;i++){
  5. read_adc_wchid();
  6. vTaskDelay(40 / portTICK_PERIOD_MS);
  7. };
  8. }
it's like centering a vcr on the right signal for the blanking, I have the pin pulled up and the adc just sometimes outputs mdat to irq and I had to reject the information. this function replaced start_scan

usulrasolas
Posts: 26
Joined: Tue Jun 09, 2020 5:27 pm

Re: Implementation of Interrupt Allocation

Postby usulrasolas » Sun Jul 12, 2020 8:14 pm

I still can't really get this to implement with a interrupt only solution, any calling of adc read events from the interrupt causes crashes and right now my reads are on a loop and I'm protecting my read function with a semaphore and nothing else... interrupt overlaps incorrectly with other events and still not getting solution I want...
  1. int32_t IRAM_ATTR read_adc_wchid(){
  2.  
  3.      int32_t adc_reading = 0;
  4.      char adc_sign = 0x0;
  5.      char adc_channel = 0x0;
  6.     ets_printf("Semaphore Take\n");
  7.     xSemaphoreTake(irqSem, portMAX_DELAY);
  8.     ets_printf("Semaphore Taken\n");
  9.     //ets_printf("Semaphore Give\n");
  10.     //xSemaphoreGive(irqSem);
  11.    // ets_printf("Semaphore Given\n");
  12.     ets_printf("Reading\n");
  13.     read_from_register(REG_ADCDATA,4);
  14.     ets_printf("Read\n");
  15.     adc_sign = recvbuf[1] & 0b00001111;
  16.     adc_channel = recvbuf[1] & 0b11110000;
  17.     adc_channel = adc_channel >> 4;
  18.     if (MCP_MODEL == 3461 || MCP_MODEL == 3462 || MCP_MODEL == 3464){
  19.         adc_reading = recvbuf[3];
  20.         adc_reading = adc_reading<<8;
  21.         adc_reading = adc_reading | recvbuf[4];
  22.         if(adc_sign!=0x0){//In case of a negative value, convert to negative
  23.             adc_reading = -65536 + adc_reading;
  24.         }
  25.  
  26.     }
  27.  
  28.     else if (MCP_MODEL == 3561 || MCP_MODEL == 3562 || MCP_MODEL == 3564){
  29.         adc_reading = recvbuf[2];
  30.         adc_reading = adc_reading << 8;
  31.         adc_reading = adc_reading | recvbuf[3];
  32.         adc_reading = adc_reading << 8;
  33.         adc_reading = adc_reading | recvbuf[4];
  34.         if(adc_sign!=0x0){//In case of a negative value, convert to negative
  35.             adc_reading = -16777216 + adc_reading;
  36.         }
  37.  //           if((adc_channel = 0b00001111)){
  38.    //        offsetbits[0] = recvbuf[2];
  39.     //        offsetbits[1] = recvbuf[3];
  40.     //       offsetbits[2] = recvbuf[4];
  41.      //      if ((adc_sign!=0x0)){
  42.      //          offsetbits[0] = offsetbits[0] | 0b10000000;
  43.      //      }
  44.      //      else {
  45.       //       offsetbits[0] <<= 1;
  46.      //        offsetbits[0] >>= 1;
  47.       //      }
  48.     //    }
  49.     }
  50.     int adc_intch = adc_channel;
  51.     adc_results[adc_intch] = adc_reading;
  52.     ets_printf("Semaphore Give\n");
  53.     xSemaphoreGive(irqSem);
  54.     ets_printf("Semaphore Given\n");
  55.     //ets_printf("Semaphore Take\n");
  56.     //xSemaphoreTake(irqSem, portMAX_DELAY);
  57.     //ets_printf("Semaphore Taken\n");
  58.  return adc_reading;
  59. }
  60.  
  61. static void IRAM_ATTR gpio_isr_handler(void* arg)
  62. {
  63.     ets_printf("Interrupt Start\n");
  64.     BaseType_t mustYield=false;
  65.     xSemaphoreGiveFromISR(irqSem, &mustYield);
  66.     if (mustYield) portYIELD_FROM_ISR();
  67.     ets_printf("Interrupt Stop\n");
  68. }
  69.  
  70. void config_interrupt(){
  71.  
  72.     gpio_config_t io_conf;
  73.     io_conf.intr_type = GPIO_INTR_NEGEDGE;
  74.     io_conf.pin_bit_mask = 1<<GPIO_IRQ;
  75.     io_conf.mode = GPIO_MODE_INPUT;
  76.     io_conf.pull_down_en = 0;
  77.     io_conf.pull_up_en = 1;
  78.     irqSem=xSemaphoreCreateBinary();
  79.     gpio_config(&io_conf);
  80.     gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
  81.     gpio_isr_handler_add(GPIO_IRQ, gpio_isr_handler, (void*) GPIO_IRQ);
  82.     gpio_intr_disable(GPIO_IRQ);
  83.    
  84. }
  85.  
  86. void IRAM_ATTR scan_semaphore(){
  87.  
  88.     fast_command(FAST_ADC_START);//Send the read cmd
  89.     ets_printf("Interrupt Enable\n");
  90.     gpio_intr_enable(GPIO_IRQ);
  91.     ets_printf("Interrupt Enabled\n");
  92.                 for(int i=0;i<17;i++){
  93.                     ets_printf("Delay Start\n");
  94.                     vTaskDelay(40 / portTICK_PERIOD_MS);
  95.                     ets_printf("Delay End\n");
  96.                     read_adc_wchid();
  97.                     ets_printf("Read Loop\n");
  98.                 };
  99.     ets_printf("Interrupt Disable\n");
  100.     gpio_intr_disable(GPIO_IRQ);
  101.     ets_printf("Interrupt Disabled\n");
  102. }
  103.  
  104. void app_main(void)
  105. {
  106.  
  107.     init_adc(EXT_CLK);
  108.     enter_scan_mode();
  109.     read_scan_reg();
  110.     config_interrupt();
  111.     vTaskDelay(1000 / portTICK_PERIOD_MS);
  112.     while(1) {
  113.    
  114.         scan_semaphore();
  115.         printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",adc_results[0],adc_results[1],adc_results[2],adc_results[3],adc_results[4],adc_results[5],adc_results[6],adc_results[7],adc_results[8],adc_results[9],adc_results[10],adc_results[11],adc_results[12],adc_results[13],adc_results[14],adc_results[15]);
  116. }
  117.  
How should I call the read event here so that it can trigger from the interrupt? I've tried about 30 permutations and still not got it.

usulrasolas
Posts: 26
Joined: Tue Jun 09, 2020 5:27 pm

Re: Implementation of Interrupt Allocation

Postby usulrasolas » Sun Jul 12, 2020 11:14 pm

any advice on what to use to allow me to call the read function immediately after/in response to the interrupt?
Deferred handling? using rtos task notifcation as a lightweigh semaphore? task suspension followed by xTaskResumeFromISR?
I'm unsure of my options.
All I really need is to make sure the read command triggers as soon as the interrupt releases but I'm reading conflicting use cases between rtos and esp documentation?
I understand why I can't call another semaphore give or take, or call the spi while interrupt is active, that includes the functions called in the isr. but I want to directly call the read function in response to the interrupt.... I've got it working where I can do a non-loop event with a delay and register all the interrupts correctly, I just don't understand how to call the other function in response to the interrupt.

ESP_Sprite
Posts: 9764
Joined: Thu Nov 26, 2015 4:08 am

Re: Implementation of Interrupt Allocation

Postby ESP_Sprite » Mon Jul 13, 2020 5:59 am

A semaphore isn't to protect anything here, it's signalling between the IRQ and the task that something interesting happened. I think you're confusing the use with a mutex (which is pretty similar) here.

In the code above, the IRQ core looks correct. All you need to do is rip all code referring to semaphores out of the rest of the routines, then simply place a single xSemaphoreTake(irqSem, portMAX_DELAY); after the line saying 'gpio_intr_enable(GPIO_IRQ);' in scan_semaphore. The logic is that that the semaphoreTake call blocks until the IRQ has actually given the semaphore, so the rest of the code will only happen when the IRQ has happened.

(Also, on second thought, something like a task notification may be a bit more optimal here... but first course of action is to get this working, I'd say.)

usulrasolas
Posts: 26
Joined: Tue Jun 09, 2020 5:27 pm

Re: Implementation of Interrupt Allocation

Postby usulrasolas » Mon Jul 13, 2020 7:27 pm

Thanks so much, right now I have it working with the semaphore as you suggested.

Right now I am keeping the interrupt enabled during the read window for scan, and then creating task to check for bool irqready that is also toggled by irq trigger. I have a delay function at end of the task loop to allow for the code to resume as no taskdelay at end of every task loop would not allow other code to return due to priorties I believe.

This works, but I will definitely want to use a task notification like notifiy from isr to resume the read function.

Who is online

Users browsing this forum: Baidu [Spider] and 260 guests