Recent Posts

Pages: 1 2 [3] 4 5 ... 10
21
Ray

Check that TASK_SNMP is in ctNodes[] in TaskConfig.h

In addition, make sure that you have no new task with the same name.

    {"MsnMp",     fnSNMP,       SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},


#define TASK_SNMP               'n'                                      // SnMP protocol task

This looks wrong - TASK_SNMP should match the first character of the task's string name.

Try with

    {"nsnMp",     fnSNMP,       SMALL_QUEUE, (DELAY_LIMIT)(NO_DELAY_RESERVE_MONO), 0, UTASKER_STOP},

instead!

Regards

Mark

22
Hi Mark,
Well, I'm drilling down and feel I'm close to the root problem, I must be missing something important.

The ARP appeared to be contributing to the problem because it changed so frequently in my noisy environment. 
Locking down the ARP to only required entries from requests seemed to solve the problem however, my system failed in the middle of the night.  Modbus worked, SNMP GET worked, UDP broadcast worked.  Everything but traps. 

With another solid day of debugging with the simulator, I think I've reached a conclusion: 
TASK_SNMP is not in the taskTable and unable to process the trap queue. extern void fnSNMP(TTASKTABLE *ptrTaskTable)
This is how the trap queue draws down, and resends when the message from ARP arrives.  This task is never called.

I added //uTaskerStateChange(TASK_SNMP, UTASKER_ACTIVATE); to my period timer and it falied to find a TASK_SNMP entry
I tried to follow extern TASK_LIMIT uTaskerStart()  these are the tasks it loaded

wdog
ARP
Eth
TCP
usb
O-MOD
app
maintenance
MassSt
DHCP
dNS
period
IGMP
NetInd
keeper
1
2
3
4
5 mine
6 mine
7 mine
8 mine
9 mine
lowPower
NULL

I'm not sure why SNMP doesn't get processed into the task array?
23
Hi Ray

In ip.c I see that only ARPs directed directly to your IP address are entered so I am not sure that it is appropriate to remove that when ARP_IGNORE_FOREIGN_ENTRIES is enabled.
However the ARP table should not be critical since the worst thing that can happen is that a resolution needs to first be performed when the destination is not yet known.
You can also increase the size of the ARP table so that entries don't need to be deleted when new ones are entere but there is not space for all.

Regards

Mark

24
Hi Mark,
Yes, I believe ARP is not the root cause, rather, it is possible the ARP process is just a little overwhelmed in my noisy network envornment.
The ARP request for 172.22.0.1 is for the gateway, probably for NTP - I've disabled this for now.


I mistakenly changed one of the ARP_IGNORE_FOREIGN_ENTRIES  in static void fnSendARP_response(ARP_INPUT *ptrArpInput)
On line 682, if we received our own ARP request, it wasn't being added, I have fixed this.
What I meant to comment out was your suggestion in fnHandleARP_response()
That is now commented out with the preprocessor, however it didn't fix the problem of extra ARP entires.

Additionally, there is an instance of fnAddARP() located in ip.c  line 688
This was adding all the misc ARP's it received, I have diabled with the preprocessor, now my ARP table has 3 and only 3 entries (+ broadcast)

This didn't resovle my trap problem. The symptom was trap manager 1 worked but 2 or 3 didn't.   
As always your amazing debugger to the rescue and discovered in static int fnSendTrap() function, line 1099 fnSendUDP()  has extra information OR'd into the SocketHandle and would fail the first check.   

Commenting this allows traps beyond manager 1 to send /* | ptrSNMP_manager_details[iManagerRef].snmp_manager_details | ((iManagerRef & USER_INFO_MASK) << USER_INFO_SHIFT)*/
I have no idea what those values are for, but commenting them out allows my 3 managers to receive traps.

if (fnSendUDP((USOCKET)(SNMPSocketNr /* | ptrSNMP_manager_details[iManagerRef].snmp_manager_details | ((iManagerRef & USER_INFO_MASK) << USER_INFO_SHIFT)*/)  ,(unsigned char*)ptrSNMP_manager_details[iManagerRef].snmp_manager_ip_address, SNMP_MANAGER_PORT, (unsigned char*)&UDP_Message.tUDP_Header, (unsigned short)iNewLength, OWN_TASK) == NO_ARP_ENTRY)

which failes the first check of fnSendUDP(USOCKET SocketHandle, unsigned char *dest_IP, unsigned short usRemotePort, unsigned char *ptrBuf, unsigned short usDataLen, UTASK_TASK OwnerTask)

    if (_UDP_SOCKET_MASK(SocketHandle) > UDP_SOCKETS) {                  // {7}
        return INVALID_SOCKET_HANDLE;
    }
   
Cautiously, all is well...I'm running a 5 day blast on coldstart traps to make sure we don't bog down.

Thank You
Ray
25
Hi Ray

In fnHandleARP_response()

you could try removing the registration of received ARP requests that were not destined to your IP address as follows, which may help reduce the ARP entries that you are not interested in.

    else {                                                               // it was not an ARP to our IP address but we can still add it to our table or refresh the entry
    #if !defined ARP_IGNORE_FOREIGN_ENTRIES
        if (uMemcmp(ucRequestingIP, cucBroadcast, IPV4_LENGTH) != 0) {   // ignore broadcasts
            fnAddARP(ucRequestingIP, ucRequestingMAC, &arp_details);     // {14}
        }
    #endif
    #if defined USE_IP_STATS
        fnIncrementEthernetStats(SEEN_FOREIGN_ARP_FRAMES, _NETWORK_ID);  // update statistics for foreign addresses
    #endif
    }


ARP entries will probably not be an issue though.


Looking at the wireshark recording I see that the traps are initially sent to 172.22.1.94

15mins later I see that there are ARPs being sent out to resolve the address 172.22.0.1, which are not answered. These maybe due to the traps that you are trying to send but may be due to other causes.

In any case you need to find out why the ARP (assuming associated with the trap after a certain time) is presumably being sent to a different address, potentially on a different sub-net, since this is possibly the issue.
Since you are working with the simulator this should be quite easy to do:
- set a break point in the ARP transmission when it starts to see how the destination address is being defined.
- let it run until the problem starts
- enable the break point again to see what is causing the ARP to be sent (possibly the trap want to send data) and compare how the destination address is being defined. I expect you'll find a difference that will explain why it stops working after a certain time.
- Traps can be sent form anywhere and don't need to be called in the SNMP task.

Regards

Mark
26
I should add I appear to be getting the same result in the simulator.  This is where my debug effort currently is.   
27
Hi Mark,
I really thought I had the SNMP traps working, but somehow It is again failing.  To troubleshoot, I temporarily added 7 MIB spots for the ARP table as a debug because CLI isn't available.  On the included wireshark filtered capture  the first entry is ARP to the SNMP manager, and my 2 test traps flow freely   .  then appx 75 seconds in it appears to be an ARP refresh?
then traps are locked out   then 5 minutes later a gateway ARP refresh? then 5 minutes later traps begin for a short time, then ARP blocking again.  Eventually the system locks up with this - but my Modbus polling is good and SNMP GET communication is unaffected?   Just traps.

Since this is very odd behavior, I'm guessing that my method for sending traps is the problem. 
However, my ARP table is full of unwanted entries despite having ARP_IGNORE_FOREIGN_ENTRIES defined.



so I think I've got 2 questions:
1)  Is the ARP_IGNORE_FOREIGN_ENTRIES  supposed to ignore all random ARP requests on the network?  It doesn't appear to do this based on the ipaddresses in the ARP table

2)  Do SNMP traps need to be implemented in a specific way so that they get an ARP notification?  do they need to be called within the snmp void fnSNMP(TTASKTABLE *ptrTaskTable)??


Thanks
Ray




in my MIB handler, the extern unsigned char fnInitialiseSNMP(void)  ( called in Application.c - in my fnPIT_timerTask  every 5 seconds)

        if (ulCount_5000ms) --ulCount_5000ms;
        else
        {
          ulCount_5000ms = 500;
          if (SnmpStarted == 0)
          {
           if( fnInitialiseSNMP() == 1) SnmpStarted = 1;
          }
          else
          {
            if (SendColdStartTrap == 0)
            {
                fnSendSNMPTrap(SNMP_COLDSTART, 0, 1);//ALL_SNMP_MANAGERS);
                SendColdStartTrap = 1; 
            }
            else// cold start has been sent
            {
              fnSendSNMPTrap(SNMP_COLDSTART, 0, 1);//  test with just the easy to send trap
            }
          }

28
NXPTM M522XX, KINETIS and i.MX RT / i.MX RT TEMPMON
« Last post by mark on July 11, 2023, 09:30:29 PM »
The i.MX RT 10xx includes a temperature monitor module (TEMPMON) that allows interrupts to be generated if the core temperature exceeds two programmable high temperature levels or falls below a low programmable lower limit level.

Software can also read the present die temperature at any time.

In order for it to work correctly it needs the bandgap reference to be enabled, plus the 480MHz PLL and the 32kHz RTC modules to be operating.

The temperature monitor is factory calibrated and the calibration values can be read from the HW_OCOTP_ANA1 registers. These are used by software to extrapolate the temperature and also to correctly set temperature limits.

The support in the µTasker project is enabled with the define SUPPORT_TEMPMON which adds an interface to read the core temperature via the ADC API in a compatible manner for projects that also run on processors that use ADC based temperature reading.

An example of reading the temperature periodically can be activated in ADC_Timers.h by activating the define ADC_INTERNAL_TEMPERATURE when using the ADC reference. For compatibility the ADC API is used with the input set to

adc_setup.int_adc_bit = ADC_TEMP_SENSOR; // ADC internal temperature

which is how ADC based temperature reading is performed.

Although there is no interrupt generated when the measurement has completed such an interrupt is emulated so that applications remain compatible. The only difference is that the result returned when collecting the value is in °C x 100 (allowing hundredth of degree resolution) and not the raw ADC value itself. Therefore the only modification at the application level is to remove any HW specific conversion that may originally have been performed and use the result directly (or after modification to the desired form). The following shows retrieving and rounding to 1°C resolution:

Code: [Select]
ADC_SETUP adc_setup; // interrupt configuration parameters
ADC_RESULTS results;
adc_setup.int_type = ADC_INTERRUPT; // identifier
adc_setup.int_adc_mode = (ADC_READ_ONLY | ADC_GET_RESULT);
adc_setup.int_adc_controller = 0;
adc_setup.int_adc_result = &results;
fnConfigureInterrupt((void *)&adc_setup);
results.sADC_value[0] += 50;
results.sADC_value[0] /= 100; // the approximate temperature
rounded up/down to 1°C
fnDebugDec(results.sADC_value[0], DISPLAY_NEGATIVE);
fnDebugMsg(" degC\r\n");

In this particular case the conversion was started previously and it shows just the subsequent retrieval. The conversion was started using the standard API for the ADC with the ADC_TEMP_SENSOR defined as input. When multiple ADC controllers are implemented in the i.MX RT the same one should be referenced for the conversion and retrieval, although there is only one TEMPMON module shared by both and the ADC controller is not actually used.
29
NXPTM M522XX, KINETIS and i.MX RT / Re: Closing and reopening handles
« Last post by mark on June 21, 2023, 03:24:47 PM »
Hi Neil

You can call with the ucDriverMode set to MODIFY_CONFIG is you want to change the UART settings (such as the baud rate).

The UART doesn't support close and re-open since this is something that is never (up to now) needed in an embedded system. It would be possible since the driver handles a close but it would require the UART's memory management to be changed to use dynamic heap (such as when the buffer sizes need to change) rather than uMalloc() as it presently uses.

If you want to stop the UART for some time you can also do

fnDriver( GSMPortID, ( TX_OFF | RX_OFF ), 0 );

and then later re-enable it with

fnDriver( GSMPortID, ( TX_ON | RX_ON ), 0 );

Regards

Mark

30
NXPTM M522XX, KINETIS and i.MX RT / Closing and reopening handles
« Last post by neil on June 21, 2023, 10:51:30 AM »
Hi Mark,
  Hope you are keeping well..

I call the below to open a Uart and pulse input channels. If I want to call the routine again, do I have to close any handles first? If so how is this done?

Best Regards
Neil

--------------------------

TTYTABLE tGSMInterfaceParameters;                                       // table for passing information to driver
QUEUE_HANDLE fnSetGSMSerialMode(unsigned char ucDriverMode)//
{
    GPTIMER_SETUP gptimer_setup;                                         // interrupt configuration parameters
    tGSMInterfaceParameters.Channel = 1;                            // set UART channel for serial use
    tGSMInterfaceParameters.ucSpeed = SERIAL_BAUD_115200; // baud rate
    tGSMInterfaceParameters.Rx_tx_sizes.RxQueueSize = 400;       // input buffer size
    tGSMInterfaceParameters.Rx_tx_sizes.TxQueueSize = 800;       // output buffer size
//    tGSMInterfaceParameters.Rx_tx_sizes.TxQueueSize = 3000;       // output buffer size Large size as may be used with diagnostics
   
    tGSMInterfaceParameters.Task_to_wake = TASK_GSM;                        // wake self when messages have been received
    tGSMInterfaceParameters.Config = (CHAR_8 | NO_PARITY | ONE_STOP | CHAR_MODE | RTS_CTS |  INFORM_ON_FRAME_TRANSMISSION);
 //   tGSMInterfaceParameters.ucDMAConfig = 0; // NO DMA for UART1

    gptimer_setup.int_type = GPT_TIMER_INTERRUPT;
    gptimer_setup.int_handler = DCDPulse_int;
    gptimer_setup.channel = 1;                                           // general purpose timer channel 1
    gptimer_setup.int_priority = GPTIMER0_INTERRUPT_PRIORITY;            // define interrupt priority
    gptimer_setup.mode = GPT_CAPTURE_RISING_EDGE; // set up capture mode and define the timer clock
                                                                     
    gptimer_setup.usCaptureCount = 0;                         // request this many capture values to be recorded before calling our interrupt
    gptimer_setup.capture_list = 0;                          // the capture list for saving to
   fnConfigureInterrupt((void *)&gptimer_setup);                        // enter interrupt for DMA timer test
    if ((GSMPortID = fnOpen( TYPE_TTY, ucDriverMode, &tGSMInterfaceParameters )) != 0)
     { // open or change the channel with defined configurations (initially inactive)
        fnDriver( GSMPortID, ( TX_ON | RX_ON ), 0 );                  // enable rx and tx
      if (tGSMInterfaceParameters.Config & RTS_CTS) {                   //

            fnDriver( GSMPortID, (MODIFY_INTERRUPT | ENABLE_CTS_CHANGE), 0 ); // activate CTS interrupt when working with HW flow control (this returns also the present control line states)
            fnDriver( GSMPortID, (MODIFY_CONTROL | SET_RTS), 0 );     // activate RTS line when working with HW flow control

        }
     }
         
    return GSMPortID;     
}
Pages: 1 2 [3] 4 5 ... 10